46#include <netinet/in.h> 
   77#define INITIAL_NUM_FILES   8 
  154#define MOH_QUIET       (1 << 0) 
  155#define MOH_SINGLE      (1 << 1) 
  156#define MOH_CUSTOM      (1 << 2) 
  157#define MOH_RANDOMIZE       (1 << 3) 
  158#define MOH_SORTALPHA       (1 << 4) 
  159#define MOH_RANDSTART       (MOH_RANDOMIZE | MOH_SORTALPHA)  
  160#define MOH_SORTMODE        (3 << 3) 
  162#define MOH_CACHERTCLASSES  (1 << 5)     
  163#define MOH_ANNOUNCEMENT    (1 << 6)     
  164#define MOH_PREFERCHANNELCLASS  (1 << 7)     
  166#define MOH_LOOPLAST (1 << 8)  
  169#define MOH_NOTDELETED          (1 << 30)        
  170#define MOH_REALTIME          (1 << 31)        
  205    unsigned int delete:1;
 
 
  222#define LOCAL_MPG_123 "/usr/local/bin/mpg123" 
  223#define MPG_123 "/usr/bin/mpg123" 
  229#define mohclass_ref(class,string)   (ao2_t_ref((class), +1, (string)), class) 
  232#define mohclass_unref(class,string) ({ ao2_t_ref((class), -1, (string)); (struct mohclass *) NULL; }) 
  234#define mohclass_unref(class,string) _mohclass_unref(class, string, __FILE__,__LINE__,__PRETTY_FUNCTION__) 
  241            ast_log(
LOG_WARNING, 
"Attempt to unref mohclass %p (%s) when only 1 ref remained, and class is still in a container! (at %s:%d (%s))\n",
 
  242                class, class->name, file, line, 
funcname);
 
  259    ast_verb(3, 
"Started music on hold, class '%s', on channel '%s'\n",
 
  263        "event", 
"MOH_STREAM_BEGIN",
 
  265            "class", moh_class_name
 
  274    json_object = 
ast_json_pack(
"{s: s}", 
"class", moh_class_name);
 
 
  298    cel_event = 
ast_json_pack(
"{ s: s }", 
"event", 
"MOH_STREAM_END");
 
 
  345    state->announcement = 0;
 
 
  367        state->announcement = 1;
 
  373        state->announcement = 0;
 
  389        state->save_pos = -1;
 
  393        state->save_pos = -1;
 
  396        for (tries = 0; tries < 20; tries++) {
 
  402        state->save_pos = -1;
 
  410            state->pos %= file_count;
 
  412        state->save_pos = -1;
 
  416    for (tries = 0; tries < file_count; ++tries) {
 
  423        state->pos %= file_count;
 
  426    if (tries == file_count) {
 
  436    if (
state->samples) {
 
  443        if (
state->samples > loc && loc) {
 
 
  495    if (
state->origwfmt) {
 
  500        if (
state->mohwfmt) {
 
  503        state->origwfmt = tmp;
 
 
  511    int res = 0, sample_queue = 0;
 
  517    sample_queue = 
state->sample_queue;
 
  520    while (sample_queue > 0) {
 
  530        if (!
state->announcement) {
 
  548        sample_queue = 
state->sample_queue;
 
 
  589    if (
state->save_total != file_count || strcmp(
state->
name, class->name) != 0) {
 
  605    state->save_total = file_count;
 
 
  633        class = 
mohclass_unref(class, 
"Unreffing ao2_find from finding by digit");
 
  634        ast_channel_musicclass_set(chan, classname);
 
 
  661    if (!strcasecmp(class->dir, 
"nodir")) {
 
  664        dir = opendir(class->dir);
 
  665        if (!dir && strncasecmp(class->dir, 
"http://", 7)) {
 
  672        argv[argc++] = 
"mpg123";
 
  675        argv[argc++] = 
"--mono";
 
  677        argv[argc++] = 
"8000";
 
  681            argv[argc++] = 
"2048";
 
  687            argv[argc++] = 
"4096";
 
  689            argv[argc++] = 
"8192";
 
  695            argv[argc++] = argptr;
 
  703            argv[argc++] = argptr;
 
  708    if (!strncasecmp(class->dir, 
"http://", 7)) {
 
  710        argv[argc++] = fns[files];
 
  713        while ((de = readdir(dir)) && (files < 
MAX_MP3S)) {
 
  714            if ((strlen(de->d_name) > 3) &&
 
  716                  (!strcasecmp(de->d_name + strlen(de->d_name) - 4, 
".raw") ||
 
  717                   !strcasecmp(de->d_name + strlen(de->d_name) - 4, 
".sln"))) ||
 
  718                 !strcasecmp(de->d_name + strlen(de->d_name) - 4, 
".mp3"))) {
 
  720                argv[argc++] = fns[files];
 
  739    if (!strncasecmp(class->dir, 
"http://", 7) && time(
NULL) - class->start < 
respawn_time) {
 
  745    if (class->pid < 0) {
 
  757        dup2(fds[1], STDOUT_FILENO);
 
  763        if (strncasecmp(class->dir, 
"http://", 7) && strcasecmp(class->dir, 
"nodir") && chdir(class->dir) < 0) {
 
  767        setpgid(0, getpid());
 
  769            execv(argv[0], argv);
 
  776            execvp(
"mpg123", argv);
 
  779        fprintf(stderr, 
"MOH: exec failed: %s\n", strerror(
errno));
 
 
  791    switch (kill_method) {
 
  793        return killpg(pid, signum);
 
  795        return kill(pid, signum);
 
 
  803    if (
killer(pid, SIGHUP, kill_method) < 0) {
 
  804        if (
errno == ESRCH) {
 
  809        ast_debug(1, 
"Sent HUP to pid %d%s\n", pid,
 
  813    if (
killer(pid, SIGTERM, kill_method) < 0) {
 
  814        if (
errno == ESRCH) {
 
  819        ast_debug(1, 
"Sent TERM to pid %d%s\n", pid,
 
  823    if (
killer(pid, SIGKILL, kill_method) < 0) {
 
  824        if (
errno == ESRCH) {
 
  829        ast_debug(1, 
"Sent KILL to pid %d%s\n", pid,
 
 
  836#define MOH_MS_INTERVAL     100 
  843    struct timeval deadline, tv_tmp;
 
  846    deadline.tv_usec = 0;
 
  848        pthread_testcancel();
 
  850        if (class->srcfd < 0) {
 
  851            if ((class->srcfd = 
spawn_mp3(
class)) < 0) {
 
  859            struct pollfd pfd = { .fd = 
ast_timer_fd(class->timer), .events = POLLIN | POLLPRI, };
 
  876            pthread_testcancel();
 
  887                pthread_testcancel();
 
  898        if ((strncasecmp(class->dir, 
"http://", 7) && strcasecmp(class->dir, 
"nodir")) && 
AST_LIST_EMPTY(&class->members))
 
  903        if ((res2 = read(class->srcfd, sbuf, 
len)) != 
len) {
 
  907                pthread_testcancel();
 
  908                if (class->pid > 1) {
 
  909                    killpid(class->pid, class->kill_delay, class->kill_method);
 
  913                ast_debug(1, 
"Read %d bytes of audio while expecting %d\n", res2, 
len);
 
  918        pthread_testcancel();
 
  923            if ((res = write(moh->
pipe[1], sbuf, res2)) != res2) {
 
  924                ast_debug(1, 
"Only wrote %d of %d bytes to pipe\n", res, res2);
 
 
  948        if (sscanf(
args.duration, 
"%30d", &timeout) == 1) {
 
 
  998#define get_mohbyname(a,b,c)    _get_mohbyname(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__) 
 1010        "get_mohbyname", file, lineno, 
funcname);
 
 1013        ast_log(
LOG_WARNING, 
"Music on Hold class '%s' not found in memory. Verify your configuration.\n", 
name);
 
 
 1051    struct mohclass *
class = moh->parent;
 
 1058    close(moh->
pipe[0]);
 
 1059    close(moh->
pipe[1]);
 
 1063    moh->
parent = 
class = 
mohclass_unref(class, 
"unreffing moh->parent upon deactivation of generator");
 
 
 1186        if (!strcasecmp(
var->name, 
"name")) {
 
 1188        } 
else if (!strcasecmp(
var->name, 
"mode")) {
 
 1190        } 
else if (!strcasecmp(
var->name, 
"entry")) {
 
 1194                if (!playlist_entries) {
 
 1196                    if (!playlist_entries) {
 
 1207                    char *last_pos_dot = strrchr(dup, 
'.');
 
 1208                    char *last_pos_slash = strrchr(dup, 
'/');
 
 1209                    if (last_pos_dot && last_pos_dot > last_pos_slash) {
 
 1210                        ast_log(
LOG_WARNING, 
"The playlist entry '%s' may include an extension, which could prevent it from playing.\n",
 
 1217                ast_log(
LOG_ERROR, 
"Playlist entries must be a URL or an absolute path, '%s' provided.\n", 
var->value);
 
 1219        } 
else if (!strcasecmp(
var->name, 
"directory")) {
 
 1221        } 
else if (!strcasecmp(
var->name, 
"application")) {
 
 1223        } 
else if (!strcasecmp(
var->name, 
"announcement")) {
 
 1226        } 
else if (!strcasecmp(
var->name, 
"digit") && (isdigit(*
var->value) || strchr(
"*#", *
var->value))) {
 
 1228        } 
else if (!strcasecmp(
var->name, 
"sort")) {
 
 1229            if (!strcasecmp(
var->value, 
"random")) {
 
 1231            } 
else if (!strcasecmp(
var->value, 
"alpha")) {
 
 1233            } 
else if (!strcasecmp(
var->value, 
"randstart")) {
 
 1236        } 
else if (!strcasecmp(
var->name, 
"loop_last")) {
 
 1249        } 
else if (!strcasecmp(
var->name, 
"kill_escalation_delay")) {
 
 1256        } 
else if (!strcasecmp(
var->name, 
"kill_method")) {
 
 1257            if (!strcasecmp(
var->value, 
"process")) {
 
 1259            } 
else if (!strcasecmp(
var->value, 
"process_group")) {
 
 1265        } 
else if (!strcasecmp(
var->name, 
"answeredonly")) {
 
 1270    if (playlist_entries) {
 
 1275            ao2_ref(playlist_entries, -1);
 
 
 1288static int on_moh_file(
const char *directory, 
const char *filename, 
void *obj)
 
 1295    if (*filename == 
'.') {
 
 1296        ast_debug(4, 
"Skipping '%s/%s' because it starts with a dot\n",
 
 1297            directory, filename);
 
 1305        ast_debug(4, 
"Skipping '%s/%s' because it doesn't have an extension\n",
 
 1306            directory, filename);
 
 1312        ast_debug(4, 
"Skipping '%s/%s' because it doesn't have at least a two " 
 1313            "character extension\n", directory, filename);
 
 1320            (
int) (
extension - filename), filename) < 0) {
 
 
 1345    const char **s1 = (
const char **) 
a;
 
 1346    const char **s2 = (
const char **) 
b;
 
 1347    return strcasecmp(*s1, *s2);
 
 
 1352    char dir_path[
PATH_MAX - 
sizeof(
class->dir)];
 
 1355    if (class->dir[0] != 
'/') {
 
 1361    ast_debug(4, 
"Scanning '%s' for files for class '%s'\n", dir_path, class->name);
 
 1382    class->files = files;
 
 
 1399        ast_verb(3, 
"Files not found in %s for moh class:%s\n",
 
 1400            class->dir, class->name);
 
 
 1435    } 
else if (old->
flags != new->flags) {
 
 
 1446    } 
else if (!
strcasecmp(class->mode, 
"mp3nb")) {
 
 1448    } 
else if (!
strcasecmp(class->mode, 
"quietmp3nb")) {
 
 1450    } 
else if (!
strcasecmp(class->mode, 
"quietmp3")) {
 
 1463        class->timer = 
NULL;
 
 1470            class->timer = 
NULL;
 
 
 1481#define moh_register(moh, reload, unref) _moh_register(moh, reload, unref, __FILE__, __LINE__, __PRETTY_FUNCTION__) 
 1492            moh = 
mohclass_unref(moh, 
"unreffing potential new moh class (it is a duplicate)");
 
 1506                moh = 
mohclass_unref(moh, 
"unreffing potential new moh class (init_files_class failed)");
 
 1519                moh = 
mohclass_unref(moh, 
"unreffing potential new moh class (no playlist entries)");
 
 1528                moh = 
mohclass_unref(moh, 
"unreffing potential new moh class (init_app_class_failed)");
 
 1535            moh = 
mohclass_unref(moh, 
"unreffing potential new moh class (unknown mode)");
 
 1543        moh = 
mohclass_unref(moh, 
"Unreffing new moh class because we just added it to the container");
 
 
 1549#define moh_unregister(a) _moh_unregister(a,__FILE__,__LINE__,__PRETTY_FUNCTION__) 
 1622            e->
command = 
"moh unregister class";
 
 1624                "Usage: moh unregister class <class>\n" 
 1625                "       Unregisters a realtime moh class.\n";
 
 1634    len = strlen(
a->argv[3]);
 
 1650        ast_cli(
a->fd, 
"No such realtime moh class '%s'\n", 
a->argv[3]);
 
 
 1660#define moh_class_malloc()  _moh_class_malloc(__FILE__,__LINE__,__PRETTY_FUNCTION__) 
 1667        "Allocating new moh class", file, line, funcname);
 
 1671        class->kill_delay = 100000;
 
 1675        if (!class->files) {
 
 
 1692            char *category = 
NULL;
 
 1693            size_t entry_count = 0;
 
 1711            if (entry_count == 0) {
 
 1721            "Music on Hold class '%s' not found in memory/database. " 
 1722            "Verify your configuration.\n",
 
 
 1739    int warn_if_not_in_memory = !realtime_possible;
 
 1740    const char *classes[] = {
NULL, 
NULL, interpclass, 
"default"};
 
 1744        classes[1] = mclass;
 
 1746        classes[0] = mclass;
 
 1765    for (i = 0; i < 
ARRAY_LEN(classes); ++i) {
 
 1768            if (!
mohclass && realtime_possible) {
 
 1955        ast_channel_latest_musicclass_set(chan, 
mohclass->
name);
 
 
 1989    ast_debug(1, 
"Destroying MOH class '%s'\n", class->name);
 
 2001        tid = 
class->thread;
 
 2003        pthread_cancel(tid);
 
 2008    if (class->pid > 1) {
 
 2010        int bytes, tbytes = 0, stime = 0;
 
 2012        ast_debug(1, 
"killing %d!\n", class->pid);
 
 2014        stime = time(
NULL) + 2;
 
 2015        killpid(class->pid, class->kill_delay, class->kill_method);
 
 2018                (bytes = read(class->srcfd, 
buff, 8192)) && time(
NULL) < stime) {
 
 2019            tbytes = tbytes + bytes;
 
 2022        ast_debug(1, 
"mpg123 pid %d and child died after %d bytes read\n",
 
 2023            class->pid, tbytes);
 
 2026        close(class->srcfd);
 
 2032        class->timer = 
NULL;
 
 2039        pthread_join(tid, 
NULL);
 
 
 2100        if (!strcasecmp(cat, 
"general")) {
 
 2102                if (!strcasecmp(
var->name, 
"cachertclasses")) {
 
 2104                } 
else if (!strcasecmp(
var->name, 
"preferchannelclass")) {
 
 2123            if (!strcasecmp(class->mode, 
"custom") || !strcasecmp(class->mode, 
"playlist")) {
 
 2124                strcpy(class->dir, 
"nodir");
 
 2126                ast_log(
LOG_WARNING, 
"A directory must be specified for class '%s'!\n", class->name);
 
 2127                class = 
mohclass_unref(class, 
"unreffing potential mohclass (no directory)");
 
 2133            class = 
mohclass_unref(class, 
"unreffing potential mohclass (no mode)");
 
 2136        if (
ast_strlen_zero(class->args) && !strcasecmp(class->mode, 
"custom")) {
 
 2137            ast_log(
LOG_WARNING, 
"An application must be specified for class '%s'!\n", class->name);
 
 2138            class = 
mohclass_unref(class, 
"unreffing potential mohclass (no app for custom mode)");
 
 
 2158    ast_verb(2, 
"Destroying musiconhold processes\n");
 
 
 2172            "Usage: moh reload\n" 
 2173            "       Reloads the MusicOnHold module.\n" 
 2174            "       Alias for 'module reload res_musiconhold.so'\n";
 
 2180    if (
a->argc != e->
args)
 
 
 2196        e->
command = 
"moh show files";
 
 2198            "Usage: moh show files\n" 
 2199            "       Lists all loaded file-based MusicOnHold classes and their\n" 
 2206    if (
a->argc != e->
args)
 
 
 2239        e->
command = 
"moh show classes";
 
 2241            "Usage: moh show classes\n" 
 2242            "       Lists all MusicOnHold classes.\n";
 
 2248    if (
a->argc != e->
args)
 
 2254        ast_cli(
a->fd, 
"\tMode: %s\n", 
S_OR(class->mode, 
"<none>"));
 
 2255        ast_cli(
a->fd, 
"\tDirectory: %s\n", 
S_OR(class->dir, 
"<none>"));
 
 2257            ast_cli(
a->fd, 
"\tAnnouncement: %s\n", 
S_OR(class->announcement, 
"<none>"));
 
 2260            ast_cli(
a->fd, 
"\tApplication: %s\n", 
S_OR(class->args, 
"<none>"));
 
 2261            ast_cli(
a->fd, 
"\tKill Escalation Delay: %zu ms\n", class->kill_delay / 1000);
 
 2262            ast_cli(
a->fd, 
"\tKill Method: %s\n",
 
 2265        if (strcasecmp(class->mode, 
"files")) {
 
 
 2283    const struct mohclass *
class = obj;
 
 
 2290    struct mohclass *
class = obj, *class2 = arg;
 
 2292    return strcasecmp(class->name, class2->name) ? 0 :
 
 2293        (flags & 
MOH_NOTDELETED) && (class->delete || class2->delete) ? 0 :
 
 
 2319                "disabling music on hold.\n");
 
 
 2361        class = 
mohclass_unref(class, 
"unref of class from module unload callback");
 
 2366        ast_log(
LOG_WARNING, 
"Unable to unload res_musiconhold due to active MOH channels\n");
 
 
void ast_cli_unregister_multiple(void)
char * strsep(char **str, const char *delims)
Asterisk main include file. File version handling, generic pbx functions.
void ast_unregister_atexit(void(*func)(void))
Unregister a function registered with ast_register_atexit().
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
#define ao2_iterator_next(iter)
@ AO2_ALLOC_OPT_LOCK_NOLOCK
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_t_iterator_next(iter, tag)
int ao2_match_by_addr(void *obj, void *arg, int flags)
A common ao2_callback is one that matches by address.
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
#define ao2_t_link(container, obj, tag)
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
void * __ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags, const char *tag, const char *file, int line, const char *func)
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
#define ao2_alloc_options(data_size, destructor_fn, options)
#define ao2_t_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn, tag)
#define ao2_t_unlink(container, obj, tag)
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
int __ao2_ref(void *o, int delta, const char *tag, const char *file, int line, const char *func)
void * __ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag, const char *file, int line, const char *func) attribute_warn_unused_result
#define ao2_t_callback(c, flags, cb_fn, arg, tag)
void ast_cel_publish_event(struct ast_channel *chan, enum ast_cel_event_type event_type, struct ast_json *blob)
Publish a CEL event.
@ AST_CEL_STREAM_BEGIN
A stream started.
@ AST_CEL_STREAM_END
A stream ended.
static unsigned char * buff
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_activate_generator(struct ast_channel *chan, struct ast_generator *gen, void *params)
void ast_channel_stream_set(struct ast_channel *chan, struct ast_filestream *value)
void * ast_channel_music_state(const struct ast_channel *chan)
const char * ast_channel_musicclass(const struct ast_channel *chan)
struct stasis_topic * ast_channel_topic(struct ast_channel *chan)
A topic which publishes the events for a particular channel.
#define ast_channel_lock(chan)
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
const char * ast_channel_uniqueid(const struct ast_channel *chan)
void ast_deactivate_generator(struct ast_channel *chan)
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
struct ast_format * ast_channel_writeformat(struct ast_channel *chan)
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
const char * ast_channel_language(const struct ast_channel *chan)
void ast_channel_music_state_set(struct ast_channel *chan, void *value)
struct ast_filestream * ast_channel_stream(const struct ast_channel *chan)
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
#define ast_channel_unlock(chan)
ast_channel_state
ast_channel states
Standard Command Line Interface.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
unsigned int ast_codec_samples_count(struct ast_frame *frame)
Get the number of samples contained within a frame.
Generic File Format Support. Should be included by clients of the file handling routines....
off_t ast_tellstream(struct ast_filestream *fs)
Tell where we are in a stream.
#define ast_file_read_dir(dir_name, on_file, obj)
Iterate over each file in a given directory.
struct ast_filestream * ast_openstream_full(struct ast_channel *chan, const char *filename, const char *preflang, int asis)
Opens stream for use in seeking, playing.
struct ast_frame * ast_readframe(struct ast_filestream *s)
Read a frame from a filestream.
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
int ast_closestream(struct ast_filestream *f)
Closes a stream.
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct stasis_message_type * ast_channel_moh_stop_type(void)
Message type for stopping music on hold on a channel.
struct stasis_message * ast_channel_blob_create_from_cache(const char *uniqueid, struct stasis_message_type *type, struct ast_json *blob)
Create a ast_channel_blob message, pulling channel state from the cache.
struct stasis_message_type * ast_channel_moh_start_type(void)
Message type for starting music on hold on a channel.
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
#define CONFIG_STATUS_FILEMISSING
struct ast_config * ast_load_realtime_multientry(const char *family,...) attribute_sentinel
Retrieve realtime configuration.
const char * ast_variable_find_in_list(const struct ast_variable *list, const char *variable)
Gets the value of a variable from a variable list by name.
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
int ast_check_realtime(const char *family)
Check if realtime engine is configured for family.
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
@ CONFIG_FLAG_FILEUNCHANGED
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
struct ast_variable * ast_load_realtime(const char *family,...) attribute_sentinel
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_REMOVE(head, elm, field)
Removes a specific entry from a list.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Asterisk locking-related definitions:
#define AST_PTHREADT_NULL
Asterisk module definitions.
#define ast_module_unref(mod)
Release a reference to the module.
#define ast_module_ref(mod)
Hold a reference to the module.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODPRI_CHANNEL_DEPEND
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
void ast_install_music_functions(int(*start_ptr)(struct ast_channel *, const char *, const char *), void(*stop_ptr)(struct ast_channel *), void(*cleanup_ptr)(struct ast_channel *))
void ast_uninstall_music_functions(void)
#define ast_opt_high_priority
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DATA_DIR
Core PBX routines and definitions.
#define ast_poll(a, b, c)
static struct ast_frame * moh_files_readframe(struct ast_channel *chan)
static char * complete_mohclass_realtime(const char *line, const char *word, int pos, int state)
Support routing for 'moh unregister class' CLI This is in charge of generating all strings that match...
static int moh_filename_strcasecmp(const void *a, const void *b)
static int moh_files_generator(struct ast_channel *chan, void *data, int len, int samples)
static void moh_release(struct ast_channel *chan, void *data)
static void moh_handle_digit(struct ast_channel *chan, char digit)
static struct ast_generator mohgen
static void moh_file_vector_destructor(void *obj)
static struct ast_cli_entry cli_moh[]
static struct ast_variable * load_realtime_musiconhold(const char *name)
static void * monmp3thread(void *data)
static int _moh_unregister(struct mohclass *moh, const char *file, int line, const char *funcname)
static void ast_moh_destroy(void)
static int play_moh_exec(struct ast_channel *chan, const char *data)
#define get_mohbyname(a, b, c)
static void local_ast_moh_stop(struct ast_channel *chan)
static int moh_class_mark(void *obj, void *arg, int flags)
static void moh_rescan_files(void)
static struct ao2_container * mohclasses
static void moh_post_stop(struct ast_channel *chan)
static int _moh_register(struct mohclass *moh, int reload, int unref, const char *file, int line, const char *funcname)
static int moh_files_next(struct ast_channel *chan)
#define moh_register(moh, reload, unref)
static int moh_scan_files(struct mohclass *class)
static void killpid(int pid, size_t delay, enum kill_methods kill_method)
static int load_moh_classes(int reload)
static char * handle_cli_moh_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int init_app_class(struct mohclass *class)
static int init_files_class(struct mohclass *class)
static int stop_moh_exec(struct ast_channel *chan, const char *data)
@ KILL_METHOD_PROCESS_GROUP
#define moh_class_malloc()
static int moh_diff(struct mohclass *old, struct mohclass *new)
#define MOH_PREFERCHANNELCLASS
static void * moh_files_alloc(struct ast_channel *chan, void *params)
static struct mohdata * mohalloc(struct mohclass *cl)
static int moh_generate(struct ast_channel *chan, void *data, int len, int samples)
static int start_moh_exec(struct ast_channel *chan, const char *data)
static char * handle_cli_moh_show_classes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define mohclass_ref(class, string)
static struct ast_generator moh_file_stream
#define MOH_CACHERTCLASSES
static void moh_files_release(struct ast_channel *chan, void *data)
static int moh_class_inuse(void *obj, void *arg, int flags)
static int moh_digit_match(void *obj, void *arg, int flags)
static int moh_class_cmp(void *obj, void *arg, int flags)
static int killer(pid_t pid, int signum, enum kill_methods kill_method)
static void moh_files_write_format_change(struct ast_channel *chan, void *data)
static int on_moh_file(const char *directory, const char *filename, void *obj)
static int spawn_mp3(struct mohclass *class)
static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclass)
static void moh_class_destructor(void *obj)
static char * handle_cli_moh_show_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void moh_post_start(struct ast_channel *chan, const char *moh_class_name)
static int load_module(void)
Load the module.
static const char play_moh[]
#define moh_unregister(a)
static int unload_module(void)
static int moh_class_hash(const void *obj, const int flags)
static const char start_moh[]
static const char stop_moh[]
static void local_ast_moh_cleanup(struct ast_channel *chan)
static struct mohclass * _get_mohbyname(const char *name, int warn, int flags, const char *file, int lineno, const char *funcname)
#define mohclass_unref(class, string)
static struct mohclass * get_mohbydigit(char digit)
static struct mohclass * _moh_class_malloc(const char *file, int line, const char *funcname)
static struct ast_vector_string * moh_file_vector_alloc(int initial_capacity)
static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
static struct ast_flags global_flags[1]
static char * handle_cli_moh_unregister_class(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int moh_classes_delete_marked(void *obj, void *arg, int flags)
static void * moh_alloc(struct ast_channel *chan, void *params)
Say numbers and dates (maybe words one day too)
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
void stasis_publish(struct stasis_topic *topic, struct stasis_message *message)
Publish a message to a topic's subscribers.
int ast_strings_equal(const char *str1, const char *str2)
Compare strings for equality checking for NULL.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int force_inline attribute_pure ast_begins_with(const char *str, const char *prefix)
Checks whether a string begins with another.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Blob of data associated with a channel.
Main Channel structure associated with a channel.
descriptor for a cli entry.
int args
This gets set in ast_cli_register()
Structure used to handle boolean flags.
struct ast_format * format
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
union ast_frame::@239 data
void *(* alloc)(struct ast_channel *chan, void *params)
Abstract JSON element (object, array, string, int, ...).
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
String vector definitions.
structure to hold extensions
char name[MAX_MUSICCLASS]
struct ast_format * mohwfmt
struct ast_format * origwfmt
char save_pos_filename[PATH_MAX]
struct mohclass::@476 list
char name[MAX_MUSICCLASS]
struct ast_vector_string * files
struct mohclass::@475 members
enum kill_methods kill_method
struct ast_format * format
struct ast_format * origwfmt
struct mohdata::@477 list
char name[TZ_STRLEN_MAX+1]
Time-related functions and macros.
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Timing source management.
void ast_timer_close(struct ast_timer *handle)
Close an opened timing handle.
int ast_timer_ack(const struct ast_timer *handle, unsigned int quantity)
Acknowledge a timer event.
int ast_timer_set_rate(const struct ast_timer *handle, unsigned int rate)
Set the timing tick rate.
struct ast_timer * ast_timer_open(void)
Open a timer.
int ast_timer_fd(const struct ast_timer *handle)
Get a poll()-able file descriptor for a timer.
Support for translation of data formats. translate.c.
#define ast_test_flag(p, flag)
#define ast_pthread_create_background(a, b, c, d)
int ast_wait_for_input(int fd, int ms)
#define ast_set2_flag(p, value, flag)
#define ast_clear_flag(p, flag)
long int ast_random(void)
#define ast_pipe_nonblock(filedes)
Create a non-blocking pipe.
#define ast_set_flag(p, flag)
#define AST_VECTOR_RESET(vec, cleanup)
Reset vector.
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
#define AST_VECTOR_SORT(vec, cmp)
Sort a vector in-place.
#define AST_VECTOR_FREE(vec)
Deallocates this vector.
#define AST_VECTOR_GET_CMP(vec, value, cmp)
Get an element from a vector that matches the given comparison.
#define AST_VECTOR_INIT(vec, size)
Initialize a vector.
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
#define AST_VECTOR_COMPACT(vec)
Resize a vector so that its capacity is the same as its size.
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.