Add a new feature for Music on Hold. If you set the "digit" option for a

class in musiconhold.conf, a caller on hold may press this digit to switch
to listening to that music class.
  This involved adding a new callback for generators, which allow generators
to get notified of DTMF from the channel they are running on.  Then, a callback
was implemented for the music on hold generators.
(patch from bbryant)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@65505 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2007-05-22 18:52:59 +00:00
parent d3ee017682
commit 90d6885701
5 changed files with 57 additions and 4 deletions

View File

@@ -135,6 +135,13 @@ MeetMe Changes
except it does operations on a channel by name, instead of number in a conference. 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. 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 Miscellaneous
------------- -------------

View File

@@ -40,6 +40,9 @@ directory=/var/lib/asterisk/moh
;mode=files ;mode=files
;directory=/var/lib/asterisk/moh ;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.
; ========= ; =========

View File

@@ -182,6 +182,8 @@ struct ast_generator {
void *(*alloc)(struct ast_channel *chan, void *params); void *(*alloc)(struct ast_channel *chan, void *params);
void (*release)(struct ast_channel *chan, void *data); void (*release)(struct ast_channel *chan, void *data);
int (*generate)(struct ast_channel *chan, void *data, int len, int samples); 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 */ /*! \brief Structure for a data store type */

View File

@@ -2420,6 +2420,9 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
chan->fin = FRAMECOUNT_INC(chan->fin); chan->fin = FRAMECOUNT_INC(chan->fin);
done: 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); ast_channel_unlock(chan);
return f; return f;
} }

View File

@@ -36,6 +36,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <ctype.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
@@ -130,6 +131,7 @@ struct mohclass {
char dir[256]; char dir[256];
char args[256]; char args[256];
char mode[80]; char mode[80];
char digit;
/*! A dynamically sized array to hold the list of filenames in "files" mode */ /*! A dynamically sized array to hold the list of filenames in "files" mode */
char **filearray; char **filearray;
/*! The current size of the 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; 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 = static struct ast_generator moh_file_stream =
{ {
alloc: moh_files_alloc, alloc: moh_files_alloc,
release: moh_files_release, release: moh_files_release,
generate: moh_files_generator, generate: moh_files_generator,
digit: moh_handle_digit,
}; };
static int spawn_mp3(struct mohclass *class) static int spawn_mp3(struct mohclass *class)
@@ -742,6 +775,7 @@ static struct ast_generator mohgen =
alloc: moh_alloc, alloc: moh_alloc,
release: moh_release, release: moh_release,
generate: moh_generate, generate: moh_generate,
digit: moh_handle_digit
}; };
static int moh_add_file(struct mohclass *class, const char *filepath) 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)) { 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. */ /* 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 (strcasecmp(cat, "classes") && strcasecmp(cat, "moh_files")) {
if (!(class = moh_class_malloc())) { if (!(class = moh_class_malloc()))
break; break;
}
ast_copy_string(class->name, cat, sizeof(class->name)); ast_copy_string(class->name, cat, sizeof(class->name));
var = ast_variable_browse(cfg, cat); var = ast_variable_browse(cfg, cat);
while (var) { while (var) {
@@ -1008,6 +1042,8 @@ static int load_moh_classes(int reload)
ast_copy_string(class->dir, var->value, sizeof(class->dir)); ast_copy_string(class->dir, var->value, sizeof(class->dir));
else if (!strcasecmp(var->name, "application")) else if (!strcasecmp(var->name, "application"))
ast_copy_string(class->args, var->value, sizeof(class->args)); 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")) else if (!strcasecmp(var->name, "random"))
ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE); ast_set2_flag(class, ast_true(var->value), MOH_RANDOMIZE);
else if (!strcasecmp(var->name, "format")) { 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, "Class: %s\n", class->name);
ast_cli(fd, "\tMode: %s\n", S_OR(class->mode, "<none>")); ast_cli(fd, "\tMode: %s\n", S_OR(class->mode, "<none>"));
ast_cli(fd, "\tDirectory: %s\n", S_OR(class->dir, "<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)) if (ast_test_flag(class, MOH_CUSTOM))
ast_cli(fd, "\tApplication: %s\n", S_OR(class->args, "<none>")); ast_cli(fd, "\tApplication: %s\n", S_OR(class->args, "<none>"));
if (strcasecmp(class->mode, "files")) if (strcasecmp(class->mode, "files"))