mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
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:
9
CHANGES
9
CHANGES
@@ -82,7 +82,7 @@ ENUM changes
|
|||||||
* Added two new dialplan functions, ENUMQUERY and ENUMRESULT. These
|
* Added two new dialplan functions, ENUMQUERY and ENUMRESULT. These
|
||||||
functions will allow you to initiate an ENUM lookup from the dialplan,
|
functions will allow you to initiate an ENUM lookup from the dialplan,
|
||||||
and Asterisk will cache the results. ENUMRESULT can be used to access
|
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
|
Voicemail Changes
|
||||||
-----------------
|
-----------------
|
||||||
@@ -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
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
@@ -39,7 +39,10 @@ directory=/var/lib/asterisk/moh
|
|||||||
;[native-random]
|
;[native-random]
|
||||||
;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.
|
||||||
|
|
||||||
|
|
||||||
; =========
|
; =========
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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"))
|
||||||
|
Reference in New Issue
Block a user