diff --git a/CHANGES b/CHANGES index de7ea567590e998ea615041cfb36df9e764f6127..9c301f3c977386a4aadfb3164a142de3a4ce46f6 100644 --- a/CHANGES +++ b/CHANGES @@ -82,7 +82,7 @@ ENUM changes * Added two new dialplan functions, ENUMQUERY and ENUMRESULT. These functions will allow you to initiate an ENUM lookup from the dialplan, and Asterisk will cache the results. ENUMRESULT can be used to access - the results without doing multiple DNS queries. + the results without doing multiple DNS queries. Voicemail Changes ----------------- @@ -135,6 +135,13 @@ MeetMe Changes except it does operations on a channel by name, instead of number in a conference. This is a very useful feature in combination with the 'X' option to ChanSpy. +Music On Hold Changes +--------------------- + * A new option, "digit", has been added for music on hold classes in + musiconhold.conf. If this is set for a music on hold class, a caller + listening to music on hold can press this digit to switch to listening + to this music on hold class. + Miscellaneous ------------- diff --git a/configs/musiconhold.conf.sample b/configs/musiconhold.conf.sample index e485552c18396339d033b58c6a4da5810a107d81..239f4c0ad0e1f334468e84adad1e07bd9af0de31 100644 --- a/configs/musiconhold.conf.sample +++ b/configs/musiconhold.conf.sample @@ -39,7 +39,10 @@ directory=/var/lib/asterisk/moh ;[native-random] ;mode=files ;directory=/var/lib/asterisk/moh -;random=yes ; Play the files in a random order +;random=yes ; Play the files in a random order +;digit=# ; If this option is set for a class, then when callers are +; ; listening to music on hold, they can press this digit, and +; ; they will switch to listening to this music class. ; ========= diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index 6b1ab4a833ad0400d6be7646699fda1d1a963752..1cbf6741069f22494a6bdcd57f4dabd916f28773 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -182,6 +182,8 @@ struct ast_generator { void *(*alloc)(struct ast_channel *chan, void *params); void (*release)(struct ast_channel *chan, void *data); int (*generate)(struct ast_channel *chan, void *data, int len, int samples); + /*! This gets called when DTMF_END frames are read from the channel */ + void (*digit)(struct ast_channel *chan, char digit); }; /*! \brief Structure for a data store type */ diff --git a/main/channel.c b/main/channel.c index 6ada607986cf06fece0eb992aab275d523707f91..8303ce8c6949083d87dfbb5816bef84985a965ee 100644 --- a/main/channel.c +++ b/main/channel.c @@ -2420,6 +2420,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio) chan->fin = FRAMECOUNT_INC(chan->fin); done: + if (chan->music_state && chan->generator && chan->generator->digit && f && f->frametype == AST_FRAME_DTMF_END) + chan->generator->digit(chan, f->subclass); + ast_channel_unlock(chan); return f; } diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index 42c171c43d4058df0adf8076f6e1e1d8a0b29ab3..6b27a084bbcb485a1bb091e4056f8a5c75af7f17 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include <stdlib.h> #include <errno.h> +#include <ctype.h> #include <unistd.h> #include <string.h> #include <signal.h> @@ -130,6 +131,7 @@ struct mohclass { char dir[256]; char args[256]; char mode[80]; + char digit; /*! A dynamically sized array to hold the list of filenames in "files" mode */ char **filearray; /*! The current size of the filearray */ @@ -324,11 +326,42 @@ static void *moh_files_alloc(struct ast_channel *chan, void *params) return chan->music_state; } +/*! \note This function should be called with the mohclasses list locked */ +static struct mohclass *get_mohbydigit(char digit) +{ + struct mohclass *moh = NULL; + + AST_RWLIST_TRAVERSE(&mohclasses, moh, list) { + if (digit == moh->digit) + break; + } + + return moh; +} + +static void moh_handle_digit(struct ast_channel *chan, char digit) +{ + struct mohclass *moh; + const char *classname; + + AST_RWLIST_RDLOCK(&mohclasses); + if ((moh = get_mohbydigit(digit))) + classname = ast_strdupa(moh->name); + AST_RWLIST_UNLOCK(&mohclasses); + + if (!moh) + return; + + ast_moh_stop(chan); + ast_moh_start(chan, classname, NULL); +} + static struct ast_generator moh_file_stream = { alloc: moh_files_alloc, release: moh_files_release, generate: moh_files_generator, + digit: moh_handle_digit, }; static int spawn_mp3(struct mohclass *class) @@ -742,6 +775,7 @@ static struct ast_generator mohgen = alloc: moh_alloc, release: moh_release, generate: moh_generate, + digit: moh_handle_digit }; static int moh_add_file(struct mohclass *class, const char *filepath) @@ -996,9 +1030,9 @@ static int load_moh_classes(int reload) for (; cat; cat = ast_category_browse(cfg, cat)) { /* These names were deprecated in 1.4 and should not be used until after the next major release. */ if (strcasecmp(cat, "classes") && strcasecmp(cat, "moh_files")) { - if (!(class = moh_class_malloc())) { + if (!(class = moh_class_malloc())) break; - } + ast_copy_string(class->name, cat, sizeof(class->name)); var = ast_variable_browse(cfg, cat); while (var) { @@ -1008,6 +1042,8 @@ static int load_moh_classes(int reload) ast_copy_string(class->dir, var->value, sizeof(class->dir)); else if (!strcasecmp(var->name, "application")) ast_copy_string(class->args, var->value, sizeof(class->args)); + else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value))) + class->digit = *var->value; else if (!strcasecmp(var->name, "random")) ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE); else if (!strcasecmp(var->name, "format")) { @@ -1143,6 +1179,8 @@ static int moh_classes_show(int fd, int argc, char *argv[]) ast_cli(fd, "Class: %s\n", class->name); ast_cli(fd, "\tMode: %s\n", S_OR(class->mode, "<none>")); ast_cli(fd, "\tDirectory: %s\n", S_OR(class->dir, "<none>")); + if (class->digit) + ast_cli(fd, "\tDigit: %c\n", class->digit); if (ast_test_flag(class, MOH_CUSTOM)) ast_cli(fd, "\tApplication: %s\n", S_OR(class->args, "<none>")); if (strcasecmp(class->mode, "files"))