From d5a285c8f2c7d070658ad2c945fcf773d28bf8ba Mon Sep 17 00:00:00 2001 From: George Joseph Date: Mon, 11 Sep 2023 08:27:41 -0600 Subject: [PATCH] file.c: Add ability to search custom dir for sounds To better co-exist with sounds files that may be managed by packages, custom sound files may now be placed in AST_DATA_DIR/sounds/custom instead of the standard AST_DATA_DIR/sounds/ directory. If the new "sounds_search_custom_dir" option in asterisk.conf is set to "true", asterisk will search the custom directory for sounds files before searching the standard directory. For performance reasons, the "sounds_search_custom_dir" defaults to "false". Resolves: #315 UserNote: A new option "sounds_search_custom_dir" has been added to asterisk.conf that allows asterisk to search AST_DATA_DIR/sounds/custom for sounds files before searching the standard AST_DATA_DIR/sounds/ directory. (cherry picked from commit 4493d2b2fc53ebf69226d7b8cbf1cb5e762c5beb) --- configs/samples/asterisk.conf.sample | 4 +++ include/asterisk/options.h | 3 ++ main/asterisk.c | 1 + main/file.c | 51 ++++++++++++++++++++-------- main/manager.c | 4 ++- main/options.c | 2 ++ 6 files changed, 49 insertions(+), 16 deletions(-) diff --git a/configs/samples/asterisk.conf.sample b/configs/samples/asterisk.conf.sample index 0d0d2a0550..f7b5bae980 100644 --- a/configs/samples/asterisk.conf.sample +++ b/configs/samples/asterisk.conf.sample @@ -128,6 +128,10 @@ documentation_language = en_US ; Set the language you want documentation ; housekeeping AMI and ARI channel events. This can ; reduce the load on the manager and ARI applications ; when the Digium Phone Module for Asterisk is in use. +;sounds_search_custom_dir = no; This option, if enabled, will + ; cause Asterisk to search for sounds files in + ; AST_DATA_DIR/sounds/custom before searching the + ; normal directories like AST_DATA_DIR/sounds/. ; Changing the following lines may compromise your security. ;[files] diff --git a/include/asterisk/options.h b/include/asterisk/options.h index 570100b724..315788386d 100644 --- a/include/asterisk/options.h +++ b/include/asterisk/options.h @@ -74,6 +74,8 @@ enum ast_option_flags { AST_OPT_FLAG_TRANSMIT_SILENCE = (1 << 17), /*! Suppress some warnings */ AST_OPT_FLAG_DONT_WARN = (1 << 18), + /*! Search custom directory for sounds first */ + AST_OPT_FLAG_SOUNDS_SEARCH_CUSTOM = (1 << 19), /*! Reference Debugging */ AST_OPT_FLAG_REF_DEBUG = (1 << 20), /*! Always fork, even if verbose or debug settings are non-zero */ @@ -135,6 +137,7 @@ enum ast_option_flags { #define ast_opt_ref_debug ast_test_flag(&ast_options, AST_OPT_FLAG_REF_DEBUG) #define ast_opt_generic_plc_on_equal_codecs ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS) #define ast_opt_hide_messaging_ami_events ast_test_flag(&ast_options, AST_OPT_FLAG_HIDE_MESSAGING_AMI_EVENTS) +#define ast_opt_sounds_search_custom ast_test_flag(&ast_options, AST_OPT_FLAG_SOUNDS_SEARCH_CUSTOM) /*! Maximum log level defined by PJPROJECT. */ #define MAX_PJ_LOG_MAX_LEVEL 6 diff --git a/main/asterisk.c b/main/asterisk.c index b7fca20145..51dfa9cc23 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -553,6 +553,7 @@ static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_c ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled"); ast_cli(a->fd, " Generic PLC on equal codecs: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS) ? "Enabled" : "Disabled"); ast_cli(a->fd, " Hide Msg Chan AMI events: %s\n", ast_opt_hide_messaging_ami_events ? "Enabled" : "Disabled"); + ast_cli(a->fd, " Sounds search custom dir: %s\n", ast_opt_sounds_search_custom ? "Enabled" : "Disabled"); ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration); #if !defined(LOW_MEMORY) ast_cli(a->fd, " Cache media frames: %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled"); diff --git a/main/file.c b/main/file.c index d7c75430bb..3a96220950 100644 --- a/main/file.c +++ b/main/file.c @@ -792,7 +792,8 @@ struct ast_filestream *ast_openstream(struct ast_channel *chan, const char *file return ast_openstream_full(chan, filename, preflang, 0); } -struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char *filename, const char *preflang, int asis) +struct ast_filestream *ast_openstream_full(struct ast_channel *chan, + const char *filename, const char *preflang, int asis) { /* * Use fileexists_core() to find a file in a compatible @@ -844,7 +845,8 @@ struct ast_filestream *ast_openstream_full(struct ast_channel *chan, const char return NULL; } -struct ast_filestream *ast_openvstream(struct ast_channel *chan, const char *filename, const char *preflang) +struct ast_filestream *ast_openvstream(struct ast_channel *chan, + const char *filename, const char *preflang) { /* As above, but for video. But here we don't have translators * so we must enforce a format. @@ -1288,22 +1290,41 @@ int ast_file_read_dirs(const char *dir_name, ast_file_on_file on_file, void *obj return res; } -int ast_streamfile(struct ast_channel *chan, const char *filename, const char *preflang) +int ast_streamfile(struct ast_channel *chan, const char *filename, + const char *preflang) { - struct ast_filestream *fs; - struct ast_filestream *vfs=NULL; + struct ast_filestream *fs = NULL; + struct ast_filestream *vfs = NULL; off_t pos; int seekattempt; int res; + char custom_filename[256]; + char *tmp_filename; + + /* If file with the same name exists in /var/lib/asterisk/sounds/custom directory, use that file. + * Otherwise, use the original file*/ + + if (ast_opt_sounds_search_custom && !is_absolute_path(filename)) { + memset(custom_filename, 0, sizeof(custom_filename)); + snprintf(custom_filename, sizeof(custom_filename), "custom/%s", filename); + fs = ast_openstream(chan, custom_filename, preflang); + if (fs) { + tmp_filename = custom_filename; + ast_debug(3, "Found file %s in custom directory\n", filename); + } + } - fs = ast_openstream(chan, filename, preflang); if (!fs) { - struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN); - ast_channel_lock(chan); - ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", - filename, ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf), strerror(errno)); - ast_channel_unlock(chan); - return -1; + fs = ast_openstream(chan, filename, preflang); + if (!fs) { + struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN); + ast_channel_lock(chan); + ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", + filename, ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf), strerror(errno)); + ast_channel_unlock(chan); + return -1; + } + tmp_filename = (char *)filename; } /* check to see if there is any data present (not a zero length file), @@ -1322,7 +1343,7 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p fseeko(fs->f, pos, SEEK_SET); } - vfs = ast_openvstream(chan, filename, preflang); + vfs = ast_openvstream(chan, tmp_filename, preflang); if (vfs) { ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_format_get_name(vfs->fmt->format)); } @@ -1333,14 +1354,14 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p return -1; if (vfs && ast_applystream(chan, vfs)) return -1; - ast_test_suite_event_notify("PLAYBACK", "Message: %s\r\nChannel: %s", filename, ast_channel_name(chan)); + ast_test_suite_event_notify("PLAYBACK", "Message: %s\r\nChannel: %s", tmp_filename, ast_channel_name(chan)); res = ast_playstream(fs); if (!res && vfs) res = ast_playstream(vfs); if (VERBOSITY_ATLEAST(3)) { ast_channel_lock(chan); - ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), filename, ast_format_get_name(ast_channel_writeformat(chan)), preflang ? preflang : "default"); + ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", ast_channel_name(chan), tmp_filename, ast_format_get_name(ast_channel_writeformat(chan)), preflang ? preflang : "default"); ast_channel_unlock(chan); } diff --git a/main/manager.c b/main/manager.c index 52c0631972..47ccaa6e8f 100644 --- a/main/manager.c +++ b/main/manager.c @@ -6781,6 +6781,7 @@ static int action_coresettings(struct mansession *s, const struct message *m) "CoreRealTimeEnabled: %s\r\n" "CoreCDRenabled: %s\r\n" "CoreHTTPenabled: %s\r\n" + "SoundsSearchCustomDir: %s\r\n" "\r\n", idText, AMI_VERSION, @@ -6793,7 +6794,8 @@ static int action_coresettings(struct mansession *s, const struct message *m) ast_option_maxfiles, AST_CLI_YESNO(ast_realtime_enabled()), AST_CLI_YESNO(ast_cdr_is_enabled()), - AST_CLI_YESNO(ast_webmanager_check_enabled()) + AST_CLI_YESNO(ast_webmanager_check_enabled()), + AST_CLI_YESNO(ast_opt_sounds_search_custom) ); return 0; } diff --git a/main/options.c b/main/options.c index 1507bc6ba5..6787d1b3cd 100644 --- a/main/options.c +++ b/main/options.c @@ -472,6 +472,8 @@ void load_asterisk_conf(void) live_dangerously = ast_true(v->value); } else if (!strcasecmp(v->name, "hide_messaging_ami_events")) { ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_MESSAGING_AMI_EVENTS); + } else if (!strcasecmp(v->name, "sounds_search_custom_dir")) { + ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_SOUNDS_SEARCH_CUSTOM); } } if (!ast_opt_remote) {