diff --git a/CHANGES b/CHANGES index 07bce9ffe0105fd5d9716ba4cb7cc58ed910bf43..3a491ce8e4308512c20896e08be8d0351e44afc0 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ chan_sip ipaddress to bind the rtpengine too. For example, chan_sip might bind to eth0 (10.0.0.2) but rtpengine to eth1 (192.168.1.10). + Functions ------------------ @@ -29,6 +30,16 @@ CHANNEL * Added CHANNEL(onhold) item that returns 1 (onhold) and 0 (not-onhold) for the hold status of a channel. + +Resources +------------------ + +res_musiconhold +------------------ + * Added sort=randstart to the sort options. It sorts the files by name and + then chooses the first file to play at random. + + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 12 to Asterisk 13 -------------------- ------------------------------------------------------------------------------ diff --git a/configs/samples/musiconhold.conf.sample b/configs/samples/musiconhold.conf.sample index 1211c8a6da662db9ead1e5dc427ad4f1564f9294..5987b36a8d69cdddc5525e8bf4c84ed572d7200b 100644 --- a/configs/samples/musiconhold.conf.sample +++ b/configs/samples/musiconhold.conf.sample @@ -57,13 +57,16 @@ directory=moh ; ; be played to them. Also, if using modes that Asterisk ; ; controls the playlist for (files, mp3, etc), the same ; ; sound will also be played between MOH songs. -;sort=random ; Sort the files in random order +;sort=random ; Sort the files in random order. Other sort options are: +; ; 'alpha' and 'randstart'. If 'alpha', the files are sorted +; ; in alphabetical order. If 'randstart', the files are sorted +; ; in alphabetical order as well, but the first file is chosen +; ; at random. If unspecified, the sort order is undefined. ;[native-alphabetical] ;mode=files ;directory=moh -;sort=alpha ; Sort the files in alphabetical order. If this option is -; ; not specified, the sort order is undefined. +;sort=alpha ; Sort the files in alphabetical order. ; ========= ; Other (non-native) playback methods diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index cbeaab535ce224419723b799429df5fdc6e8495c..17b34c58e58c5a718423b362b6f683d69b9ab2da 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -148,6 +148,8 @@ struct moh_files_state { #define MOH_CUSTOM (1 << 2) #define MOH_RANDOMIZE (1 << 3) #define MOH_SORTALPHA (1 << 4) +#define MOH_RANDSTART (MOH_RANDOMIZE | MOH_SORTALPHA) /*!< Sorted but start at random position */ +#define MOH_SORTMODE (3 << 3) #define MOH_CACHERTCLASSES (1 << 5) /*!< Should we use a separate instance of MOH for each user or not */ #define MOH_ANNOUNCEMENT (1 << 6) /*!< Do we play announcement files between songs on this channel? */ @@ -202,6 +204,7 @@ static struct ao2_container *mohclasses; #define MPG_123 "/usr/bin/mpg123" #define MAX_MP3S 256 +static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclass); static int reload(void); #define mohclass_ref(class,string) (ao2_t_ref((class), +1, (string)), class) @@ -335,7 +338,7 @@ static int ast_moh_files_next(struct ast_channel *chan) /* If a specific file has been saved confirm it still exists and that it is still valid */ state->pos = state->save_pos; state->save_pos = -1; - } else if (ast_test_flag(state->class, MOH_RANDOMIZE)) { + } else if (ast_test_flag(state->class, MOH_SORTMODE) == MOH_RANDOMIZE) { /* Get a random file and ensure we can open it */ for (tries = 0; tries < 20; tries++) { state->pos = ast_random() % state->class->total_files; @@ -1031,6 +1034,44 @@ static struct ast_generator mohgen = { .digit = moh_handle_digit, }; +static void moh_parse_options(struct ast_variable *var, struct mohclass *mohclass) +{ + for (; var; var = var->next) { + if (!strcasecmp(var->name, "name")) { + ast_copy_string(mohclass->name, var->value, sizeof(mohclass->name)); + } else if (!strcasecmp(var->name, "mode")) { + ast_copy_string(mohclass->mode, var->value, sizeof(mohclass->mode)); + } else if (!strcasecmp(var->name, "directory")) { + ast_copy_string(mohclass->dir, var->value, sizeof(mohclass->dir)); + } else if (!strcasecmp(var->name, "application")) { + ast_copy_string(mohclass->args, var->value, sizeof(mohclass->args)); + } else if (!strcasecmp(var->name, "digit") && (isdigit(*var->value) || strchr("*#", *var->value))) { + mohclass->digit = *var->value; + } else if (!strcasecmp(var->name, "random")) { + static int deprecation_warning = 0; + if (!deprecation_warning) { + ast_log(LOG_WARNING, "Music on hold 'random' setting is deprecated in 14. Please use 'sort=random' instead.\n"); + deprecation_warning = 1; + } + ast_set2_flag(mohclass, ast_true(var->value), MOH_RANDOMIZE); + } else if (!strcasecmp(var->name, "sort")) { + if (!strcasecmp(var->value, "random")) { + ast_set_flag(mohclass, MOH_RANDOMIZE); + } else if (!strcasecmp(var->value, "alpha")) { + ast_set_flag(mohclass, MOH_SORTALPHA); + } else if (!strcasecmp(var->value, "randstart")) { + ast_set_flag(mohclass, MOH_RANDSTART); + } + } else if (!strcasecmp(var->name, "format")) { + mohclass->format = ast_format_cache_get(var->value); + if (!mohclass->format) { + ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value); + mohclass->format = ao2_bump(ast_format_slin); + } + } + } +} + static int moh_add_file(struct mohclass *class, const char *filepath) { if (!class->allowed_files) { @@ -1398,36 +1439,12 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con * above guarantees that if var is non-NULL, then mohclass must be NULL. */ if (var) { - struct ast_variable *tmp = NULL; - if ((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_format_cache_get(tmp->value); - if (!mohclass->format) { - ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", tmp->value); - mohclass->format = ao2_bump(ast_format_slin); - } - } - } + + moh_parse_options(var, mohclass); ast_variables_destroy(var); + if (ast_strlen_zero(mohclass->dir)) { if (!strcasecmp(mohclass->mode, "custom")) { strcpy(mohclass->dir, "nodir"); @@ -1475,8 +1492,14 @@ static int local_ast_moh_start(struct ast_channel *chan, const char *mclass, con mohclass = mohclass_unref(mohclass, "unreffing potential mohclass (moh_scan_files failed)"); return -1; } - if (strchr(mohclass->args, 'r')) + if (strchr(mohclass->args, 'r')) { + static int deprecation_warning = 0; + if (!deprecation_warning) { + ast_log(LOG_WARNING, "Music on hold 'application=r' setting is deprecated in 14. Please use 'sort=random' instead.\n"); + deprecation_warning = 1; + } 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")) @@ -1722,43 +1745,15 @@ static int load_moh_classes(int reload) } } } - /* 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") || - !strcasecmp(cat, "general")) { - continue; - } if (!(class = moh_class_malloc())) { break; } + moh_parse_options(ast_variable_browse(cfg, cat), class); + /* For compatibility with the past, we overwrite any name=name + * with the context [name]. */ ast_copy_string(class->name, cat, sizeof(class->name)); - for (var = ast_variable_browse(cfg, cat); var; var = var->next) { - if (!strcasecmp(var->name, "mode")) { - ast_copy_string(class->mode, var->value, sizeof(class->mode)); - } else if (!strcasecmp(var->name, "directory")) { - 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, "announcement")) { - ast_copy_string(class->announcement, var->value, sizeof(class->announcement)); - ast_set_flag(class, MOH_ANNOUNCEMENT); - } 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, "sort") && !strcasecmp(var->value, "random")) { - ast_set_flag(class, MOH_RANDOMIZE); - } else if (!strcasecmp(var->name, "sort") && !strcasecmp(var->value, "alpha")) { - ast_set_flag(class, MOH_SORTALPHA); - } else if (!strcasecmp(var->name, "format")) { - class->format = ast_format_cache_get(var->value); - if (!class->format) { - ast_log(LOG_WARNING, "Unknown format '%s' -- defaulting to SLIN\n", var->value); - class->format = ao2_bump(ast_format_slin); - } - } - } if (ast_strlen_zero(class->dir)) { if (!strcasecmp(class->mode, "custom")) {