[asterisk-commits] russell: branch russell/chan_refcount r89948 - in /team/russell/chan_refcount...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Nov 27 18:51:27 CST 2007
Author: russell
Date: Tue Nov 27 18:51:26 2007
New Revision: 89948
URL: http://svn.digium.com/view/asterisk?view=rev&rev=89948
Log:
sync with trunk
Modified:
team/russell/chan_refcount/ (props changed)
team/russell/chan_refcount/CHANGES
team/russell/chan_refcount/apps/app_voicemail.c
team/russell/chan_refcount/configs/extconfig.conf.sample
team/russell/chan_refcount/configs/musiconhold.conf.sample
team/russell/chan_refcount/res/res_musiconhold.c
Propchange: team/russell/chan_refcount/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Nov 27 18:51:26 2007
@@ -1,1 +1,1 @@
-/trunk:1-89921
+/trunk:1-89947
Modified: team/russell/chan_refcount/CHANGES
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/CHANGES?view=diff&rev=89948&r1=89947&r2=89948
==============================================================================
--- team/russell/chan_refcount/CHANGES (original)
+++ team/russell/chan_refcount/CHANGES Tue Nov 27 18:51:26 2007
@@ -234,6 +234,10 @@
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.
+ * Support for realtime music on hold has been added.
+ * In conjunction with the realtime music on hold, a general section has
+ been added to musiconhold.conf, its sole variable is cachertclasses. If this
+ is set, then music on hold classes found in realtime will be cached in memory.
AEL Changes
-----------
Modified: team/russell/chan_refcount/apps/app_voicemail.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/apps/app_voicemail.c?view=diff&rev=89948&r1=89947&r2=89948
==============================================================================
--- team/russell/chan_refcount/apps/app_voicemail.c (original)
+++ team/russell/chan_refcount/apps/app_voicemail.c Tue Nov 27 18:51:26 2007
@@ -1975,8 +1975,8 @@
memset(passdata, 0, vmlen);
ast_channel_lock(ast);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+ ast_channel_unlock(ast);
pbx_substitute_variables_helper(ast, fromstring, passdata, vmlen);
- ast_channel_unlock(ast);
len_passdata = strlen(passdata) * 2 + 3;
passdata2 = alloca(len_passdata);
fprintf(p, "From: %s <%s>" ENDL, quote(passdata, passdata2, len_passdata), who);
@@ -1997,8 +1997,8 @@
memset(passdata, 0, vmlen);
ast_channel_lock(ast);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+ ast_channel_unlock(ast);
pbx_substitute_variables_helper(ast, emailsubject, passdata, vmlen);
- ast_channel_unlock(ast);
fprintf(p, "Subject: %s" ENDL, passdata);
ast = ast_channel_release(ast);
} else
@@ -2052,8 +2052,8 @@
memset(passdata, 0, vmlen);
ast_channel_lock(ast);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+ ast_channel_unlock(ast);
pbx_substitute_variables_helper(ast, emailbody, passdata, vmlen);
- ast_channel_unlock(ast);
fprintf(p, "%s" ENDL, passdata);
ast = ast_channel_release(ast);
} else
@@ -2171,8 +2171,8 @@
memset(passdata, 0, vmlen);
ast_channel_lock(ast);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+ ast_channel_unlock(ast);
pbx_substitute_variables_helper(ast, pagerfromstring, passdata, vmlen);
- ast_channel_unlock(ast);
fprintf(p, "From: %s <%s>\n", passdata, who);
ast = ast_channel_release(ast);
} else
@@ -2189,8 +2189,8 @@
memset(passdata, 0, vmlen);
ast_channel_lock(ast);
prep_email_sub_vars(ast, vmu, msgnum + 1, context, mailbox, cidnum, cidname, dur, date, passdata, vmlen, category);
+ ast_channel_unlock(ast);
pbx_substitute_variables_helper(ast, pagersubject, passdata, vmlen);
- ast_channel_unlock(ast);
fprintf(p, "Subject: %s\n\n", passdata);
ast = ast_channel_release(ast);
} else
Modified: team/russell/chan_refcount/configs/extconfig.conf.sample
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/configs/extconfig.conf.sample?view=diff&rev=89948&r1=89947&r2=89948
==============================================================================
--- team/russell/chan_refcount/configs/extconfig.conf.sample (original)
+++ team/russell/chan_refcount/configs/extconfig.conf.sample Tue Nov 27 18:51:26 2007
@@ -58,4 +58,5 @@
;extensions => odbc,asterisk
;queues => odbc,asterisk
;queue_members => odbc,asterisk
+;musiconhold => mysql,asterisk
Modified: team/russell/chan_refcount/configs/musiconhold.conf.sample
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/configs/musiconhold.conf.sample?view=diff&rev=89948&r1=89947&r2=89948
==============================================================================
--- team/russell/chan_refcount/configs/musiconhold.conf.sample (original)
+++ team/russell/chan_refcount/configs/musiconhold.conf.sample Tue Nov 27 18:51:26 2007
@@ -1,6 +1,11 @@
;
; Music on Hold -- Sample Configuration
;
+[general]
+;cachertclasses=yes ; use 1 instance of moh class for all users who are using it,
+ ; decrease consumable cpu cycles and memory
+ ; disabled by default
+
; valid mode options:
; files -- read files from a directory in any Asterisk supported
Modified: team/russell/chan_refcount/res/res_musiconhold.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/res/res_musiconhold.c?view=diff&rev=89948&r1=89947&r2=89948
==============================================================================
--- team/russell/chan_refcount/res/res_musiconhold.c (original)
+++ team/russell/chan_refcount/res/res_musiconhold.c Tue Nov 27 18:51:26 2007
@@ -117,6 +117,10 @@
#define MOH_CUSTOM (1 << 2)
#define MOH_RANDOMIZE (1 << 3)
#define MOH_SORTALPHA (1 << 4)
+
+#define MOH_CACHERTCLASSES (1 << 5) /*!< Should we use a separate instance of MOH for each user or not */
+
+static struct ast_flags global_flags[1] = {{0}}; /*!< global MOH_ flags */
struct mohclass {
char name[MAX_MUSICCLASS];
@@ -143,6 +147,8 @@
int pseudofd;
/*! Number of users */
int inuse;
+ /*! Created on the fly, from RT engine */
+ int realtime;
unsigned int delete:1;
AST_LIST_HEAD_NOLOCK(, mohdata) members;
AST_LIST_ENTRY(mohclass) list;
@@ -668,7 +674,7 @@
}
if (!moh && warn)
- ast_log(LOG_WARNING, "Music on Hold class '%s' not found\n", name);
+ ast_log(LOG_DEBUG, "Music on Hold class '%s' not found in memory\n", name);
return moh;
}
@@ -710,6 +716,7 @@
{
struct mohdata *moh = data;
int oldwfmt;
+ struct moh_files_state *state;
AST_RWLIST_WRLOCK(&mohclasses);
AST_RWLIST_REMOVE(&moh->parent->members, moh, list);
@@ -718,8 +725,12 @@
close(moh->pipe[0]);
close(moh->pipe[1]);
oldwfmt = moh->origwfmt;
+ state = chan->music_state;
if (moh->parent->delete && ast_atomic_dec_and_test(&moh->parent->inuse))
ast_moh_destroy_one(moh->parent);
+ if (ast_atomic_dec_and_test(&state->class->inuse) && state->class->delete)
+ ast_moh_destroy_one(state->class);
+
ast_free(moh);
if (chan) {
if (oldwfmt && ast_set_write_format(chan, oldwfmt))
@@ -732,6 +743,19 @@
{
struct mohdata *res;
struct mohclass *class = params;
+ struct moh_files_state *state;
+
+ /* Initiating music_state for current channel. Channel should know name of moh class */
+ if (!chan->music_state && (state = ast_calloc(1, sizeof(*state)))) {
+ chan->music_state = state;
+ memset(state, 0, sizeof(*state));
+ state->class = class;
+ } else
+ state = chan->music_state;
+ if (state && state->class != class) {
+ memset(state, 0, sizeof(*state));
+ state->class = class;
+ }
if ((res = mohalloc(class))) {
res->origwfmt = chan->writeformat;
@@ -827,7 +851,7 @@
struct stat statbuf;
int dirnamelen;
int i;
-
+
files_DIR = opendir(class->dir);
if (!files_DIR) {
ast_log(LOG_WARNING, "Cannot open dir %s or dir does not exist\n", class->dir);
@@ -978,15 +1002,51 @@
static void local_ast_moh_cleanup(struct ast_channel *chan)
{
- if (chan->music_state) {
+ struct moh_files_state *state = chan->music_state;
+
+ if (state) {
+ if (state->class->realtime) {
+ if (ast_test_flag(global_flags, MOH_CACHERTCLASSES)) {
+ /* We are cleaning out cached RT class, we should remove it from list, if no one else using it */
+ if (!(state->class->inuse)) {
+ /* Remove this class from list */
+ AST_RWLIST_WRLOCK(&mohclasses);
+ AST_RWLIST_REMOVE(&mohclasses, state->class, list);
+ AST_RWLIST_UNLOCK(&mohclasses);
+
+ /* Free some memory */
+ ast_moh_destroy_one(state->class);
+ }
+ } else {
+ ast_moh_destroy_one(state->class);
+ }
+ }
ast_free(chan->music_state);
chan->music_state = NULL;
}
}
+static struct mohclass *moh_class_malloc(void)
+{
+ struct mohclass *class;
+
+ if ((class = ast_calloc(1, sizeof(*class)))) {
+ class->format = AST_FORMAT_SLINEAR;
+ class->realtime = 0;
+ }
+
+ return class;
+}
+
static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
{
struct mohclass *mohclass = NULL;
+ struct ast_variable *var = NULL;
+ struct ast_variable *tmp = NULL;
+ struct moh_files_state *state = chan->music_state;
+#ifdef HAVE_ZAPTEL
+ int x;
+#endif
/* The following is the order of preference for which class to use:
* 1) The channels explicitly set musicclass, which should *only* be
@@ -999,6 +1059,8 @@
* option.
* 4) The default class.
*/
+
+ /* First, let's check in memory for static and cached RT classes */
AST_RWLIST_RDLOCK(&mohclasses);
if (!ast_strlen_zero(chan->musicclass))
mohclass = get_mohbyname(chan->musicclass, 1);
@@ -1006,11 +1068,161 @@
mohclass = get_mohbyname(mclass, 1);
if (!mohclass && !ast_strlen_zero(interpclass))
mohclass = get_mohbyname(interpclass, 1);
- if (!mohclass)
+ AST_RWLIST_UNLOCK(&mohclasses);
+
+ /* If no moh class found in memory, then check RT */
+ if (!mohclass && ast_check_realtime("musiconhold")) {
+ if (!ast_strlen_zero(chan->musicclass)) {
+ var = ast_load_realtime("musiconhold", "name", chan->musicclass, NULL);
+ }
+ if (!var && !ast_strlen_zero(mclass))
+ var = ast_load_realtime("musiconhold", "name", mclass, NULL);
+ if (!var && !ast_strlen_zero(interpclass))
+ var = ast_load_realtime("musiconhold", "name", interpclass, NULL);
+ if (!var)
+ var = ast_load_realtime("musiconhold", "name", "default", NULL);
+ if (var && (mohclass = moh_class_malloc())) {
+ mohclass->realtime = 1;
+ for (tmp = var; tmp; tmp = tmp->next) {
+ if (!strcasecmp(tmp->name, "name"))
+ ast_copy_string(mohclass->name, tmp->value, sizeof(mohclass->name));
+ else if (!strcasecmp(tmp->name, "mode"))
+ ast_copy_string(mohclass->mode, tmp->value, sizeof(mohclass->mode));
+ else if (!strcasecmp(tmp->name, "directory"))
+ ast_copy_string(mohclass->dir, tmp->value, sizeof(mohclass->dir));
+ else if (!strcasecmp(tmp->name, "application"))
+ ast_copy_string(mohclass->args, tmp->value, sizeof(mohclass->args));
+ else if (!strcasecmp(tmp->name, "digit") && (isdigit(*tmp->value) || strchr("*#", *tmp->value)))
+ mohclass->digit = *tmp->value;
+ else if (!strcasecmp(tmp->name, "random"))
+ ast_set2_flag(mohclass, ast_true(tmp->value), MOH_RANDOMIZE);
+ else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "random"))
+ ast_set_flag(mohclass, MOH_RANDOMIZE);
+ else if (!strcasecmp(tmp->name, "sort") && !strcasecmp(tmp->value, "alpha"))
+ ast_set_flag(mohclass, MOH_SORTALPHA);
+ else if (!strcasecmp(tmp->name, "format")) {
+ mohclass->format = ast_getformatbyname(tmp->value);
+ if (!mohclass->format) {
+ ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value);
+ mohclass->format = AST_FORMAT_SLINEAR;
+ }
+ }
+ }
+ if (ast_strlen_zero(mohclass->dir)) {
+ if (!strcasecmp(mohclass->mode, "custom")) {
+ strcpy(mohclass->dir, "nodir");
+ } else {
+ ast_log(LOG_WARNING, "A directory must be specified for class '%s'!\n", mohclass->name);
+ ast_free(mohclass);
+ return -1;
+ }
+ }
+ if (ast_strlen_zero(mohclass->mode)) {
+ ast_log(LOG_WARNING, "A mode must be specified for class '%s'!\n", mohclass->name);
+ ast_free(mohclass);
+ return -1;
+ }
+ if (ast_strlen_zero(mohclass->args) && !strcasecmp(mohclass->mode, "custom")) {
+ ast_log(LOG_WARNING, "An application must be specified for class '%s'!\n", mohclass->name);
+ ast_free(mohclass);
+ return -1;
+ }
+
+ if (ast_test_flag(global_flags, MOH_CACHERTCLASSES)) {
+ /* CACHERTCLASSES enabled, let's add this class to default tree */
+ if (state && state->class) {
+ /* Class already exist for this channel */
+ ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
+ if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
+ /* we found RT class with the same name, seems like we should continue playing existing one */
+ ast_moh_free_class(&mohclass);
+ mohclass = state->class;
+ }
+ }
+ moh_register(mohclass, 0);
+ } else {
+
+ /* We don't register RT moh class, so let's init it manualy */
+
+ time(&mohclass->start);
+ mohclass->start -= respawn_time;
+
+ if (!strcasecmp(mohclass->mode, "files")) {
+ if (!moh_scan_files(mohclass)) {
+ ast_moh_free_class(&mohclass);
+ return -1;
+ }
+ if (strchr(mohclass->args, 'r'))
+ ast_set_flag(mohclass, MOH_RANDOMIZE);
+ } else if (!strcasecmp(mohclass->mode, "mp3") || !strcasecmp(mohclass->mode, "mp3nb") || !strcasecmp(mohclass->mode, "quietmp3") || !strcasecmp(mohclass->mode, "quietmp3nb") || !strcasecmp(mohclass->mode, "httpmp3") || !strcasecmp(mohclass->mode, "custom")) {
+
+ if (!strcasecmp(mohclass->mode, "custom"))
+ ast_set_flag(mohclass, MOH_CUSTOM);
+ else if (!strcasecmp(mohclass->mode, "mp3nb"))
+ ast_set_flag(mohclass, MOH_SINGLE);
+ else if (!strcasecmp(mohclass->mode, "quietmp3nb"))
+ ast_set_flag(mohclass, MOH_SINGLE | MOH_QUIET);
+ else if (!strcasecmp(mohclass->mode, "quietmp3"))
+ ast_set_flag(mohclass, MOH_QUIET);
+
+ mohclass->srcfd = -1;
+#ifdef HAVE_ZAPTEL
+ /* Open /dev/zap/pseudo for timing... Is
+ there a better, yet reliable way to do this? */
+ mohclass->pseudofd = open("/dev/zap/pseudo", O_RDONLY);
+ if (mohclass->pseudofd < 0) {
+ ast_log(LOG_WARNING, "Unable to open pseudo channel for timing... Sound may be choppy.\n");
+ } else {
+ x = 320;
+ ioctl(mohclass->pseudofd, ZT_SET_BLOCKSIZE, &x);
+ }
+#else
+ mohclass->pseudofd = -1;
+#endif
+ /* Let's check if this channel already had a moh class before */
+ if (state && state->class) {
+ /* Class already exist for this channel */
+ ast_log(LOG_NOTICE, "This channel already has a MOH class attached (%s)!\n", state->class->name);
+ if (state->class->realtime && !ast_test_flag(global_flags, MOH_CACHERTCLASSES) && !strcasecmp(mohclass->name, state->class->name)) {
+ /* we found RT class with the same name, seems like we should continue playing existing one */
+ ast_moh_free_class(&mohclass);
+ mohclass = state->class;
+
+ }
+ } else {
+ if (ast_pthread_create_background(&mohclass->thread, NULL, monmp3thread, mohclass)) {
+ ast_log(LOG_WARNING, "Unable to create moh...\n");
+ if (mohclass->pseudofd > -1)
+ close(mohclass->pseudofd);
+ ast_moh_free_class(&mohclass);
+ return -1;
+ }
+ }
+ } else {
+ ast_log(LOG_WARNING, "Don't know how to do a mode '%s' music on hold\n", mohclass->mode);
+ ast_moh_free_class(&mohclass);
+ return -1;
+ }
+
+ }
+
+ }
+ }
+
+
+
+ /* Requested MOH class not found, check for 'default' class in musiconhold.conf */
+ if (!mohclass) {
+ AST_RWLIST_RDLOCK(&mohclasses);
mohclass = get_mohbyname("default", 1);
- if (mohclass)
+ if (mohclass)
+ ast_atomic_fetchadd_int(&mohclass->inuse, +1);
+ AST_RWLIST_UNLOCK(&mohclasses);
+ } else {
+ AST_RWLIST_RDLOCK(&mohclasses);
ast_atomic_fetchadd_int(&mohclass->inuse, +1);
- AST_RWLIST_UNLOCK(&mohclasses);
+ AST_RWLIST_UNLOCK(&mohclasses);
+ }
if (!mohclass)
return -1;
@@ -1024,25 +1236,16 @@
static void local_ast_moh_stop(struct ast_channel *chan)
{
+ struct moh_files_state *state = chan->music_state;
ast_clear_flag(chan, AST_FLAG_MOH);
ast_deactivate_generator(chan);
- if (chan->music_state) {
+ if (state) {
if (chan->stream) {
ast_closestream(chan->stream);
chan->stream = NULL;
}
}
-}
-
-static struct mohclass *moh_class_malloc(void)
-{
- struct mohclass *class;
-
- if ((class = ast_calloc(1, sizeof(*class))))
- class->format = AST_FORMAT_SLINEAR;
-
- return class;
}
static int load_moh_classes(int reload)
@@ -1066,11 +1269,25 @@
}
AST_RWLIST_UNLOCK(&mohclasses);
}
+
+ ast_clear_flag(global_flags, AST_FLAGS_ALL);
cat = ast_category_browse(cfg, NULL);
for (; cat; cat = ast_category_browse(cfg, cat)) {
+ /* Setup common options from [general] section */
+ if (!strcasecmp(cat, "general")) {
+ var = ast_variable_browse(cfg, cat);
+ while (var) {
+ if (!strcasecmp(var->name, "cachertclasses")) {
+ ast_set2_flag(global_flags, ast_true(var->value), MOH_CACHERTCLASSES);
+ } else {
+ ast_log(LOG_WARNING, "Unknown option '%s' in [general] section of musiconhold.conf\n", var->name);
+ }
+ var = var->next;
+ }
+ }
/* 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") && strcasecmp(cat, "general")) {
if (!(class = moh_class_malloc()))
break;
More information about the asterisk-commits
mailing list