diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index a0eb1dbf5d..95ecd71a86 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -1403,6 +1403,50 @@ static char *handle_cli_mixmonitor(struct ast_cli_entry *e, int cmd, struct ast_ return CLI_SUCCESS; } +/*! \brief Mute / unmute an individual MixMonitor by id */ +static int mute_mixmonitor_instance(struct ast_channel *chan, const char *data, + enum ast_audiohook_flags flag, int clearmute) +{ + struct ast_datastore *datastore = NULL; + char *parse = ""; + struct mixmonitor_ds *mixmonitor_ds; + + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(mixmonid); + ); + + if (!ast_strlen_zero(data)) { + parse = ast_strdupa(data); + } + + AST_STANDARD_APP_ARGS(args, parse); + + ast_channel_lock(chan); + + datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, + S_OR(args.mixmonid, NULL)); + if (!datastore) { + ast_channel_unlock(chan); + return -1; + } + mixmonitor_ds = datastore->data; + + ast_mutex_lock(&mixmonitor_ds->lock); + + if (mixmonitor_ds->audiohook) { + if (clearmute) { + ast_clear_flag(mixmonitor_ds->audiohook, flag); + } else { + ast_set_flag(mixmonitor_ds->audiohook, flag); + } + } + + ast_mutex_unlock(&mixmonitor_ds->lock); + ast_channel_unlock(chan); + + return 0; +} + /*! \brief Mute / unmute a MixMonitor channel */ static int manager_mute_mixmonitor(struct mansession *s, const struct message *m) { @@ -1411,7 +1455,8 @@ static int manager_mute_mixmonitor(struct mansession *s, const struct message *m const char *id = astman_get_header(m, "ActionID"); const char *state = astman_get_header(m, "State"); const char *direction = astman_get_header(m,"Direction"); - int clearmute = 1; + const char *mixmonitor_id = astman_get_header(m, "MixMonitorID"); + int clearmute = 1, mutedcount = 0; enum ast_audiohook_flags flag; RAII_VAR(struct stasis_message *, stasis_message, NULL, ao2_cleanup); RAII_VAR(struct ast_json *, stasis_message_blob, NULL, ast_json_unref); @@ -1450,15 +1495,28 @@ static int manager_mute_mixmonitor(struct mansession *s, const struct message *m return AMI_SUCCESS; } - if (ast_audiohook_set_mute(c, mixmonitor_spy_type, flag, clearmute)) { - ast_channel_unref(c); - astman_send_error(s, m, "Cannot set mute flag"); - return AMI_SUCCESS; + if (ast_strlen_zero(mixmonitor_id)) { + mutedcount = ast_audiohook_set_mute_all(c, mixmonitor_spy_type, flag, clearmute); + if (mutedcount < 0) { + ast_channel_unref(c); + astman_send_error(s, m, "Cannot set mute flag"); + return AMI_SUCCESS; + } + } else { + if (mute_mixmonitor_instance(c, mixmonitor_id, flag, clearmute)) { + ast_channel_unref(c); + astman_send_error(s, m, "Cannot set mute flag"); + return AMI_SUCCESS; + } + mutedcount = 1; } - stasis_message_blob = ast_json_pack("{s: s, s: b}", + + stasis_message_blob = ast_json_pack("{s: s, s: b, s: s, s: i}", "direction", direction, - "state", ast_true(state)); + "state", ast_true(state), + "mixmonitorid", mixmonitor_id, + "count", mutedcount); stasis_message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(c), ast_channel_mixmonitor_mute_type(), stasis_message_blob); diff --git a/doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt b/doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt new file mode 100644 index 0000000000..958a914ba9 --- /dev/null +++ b/doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt @@ -0,0 +1,17 @@ +Subject: app_mixmonitor +Subject: audiohook +Subject: manager + +It is now possible to specify the MixMonitorID when calling +the manager action: MixMonitorMute. This will allow an +individual MixMonitor instance to be muted via ID. + +The MixMonitorID can be stored as a channel variable using +the 'i' MixMonitor option and is returned upon creation if +this option is used. + +As part of this change, if no MixMonitorID is specified in +the manager action MixMonitorMute, Asterisk will set the mute +flag on all MixMonitor audiohooks on the channel. Previous +behavior would set the flag on the first MixMonitor audiohook +found. diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h index a5d7e0c766..e19c8339f5 100644 --- a/include/asterisk/audiohook.h +++ b/include/asterisk/audiohook.h @@ -358,6 +358,16 @@ int ast_audiohook_volume_adjust(struct ast_channel *chan, enum ast_audiohook_dir */ int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear); +/*! \brief Mute frames read from or written for all audiohooks on a channel + * \param chan Channel to muck with + * \param source Type of audiohooks + * \param flag which direction to set / clear + * \param clear set or clear muted frames on direction based on flag parameter + * \retval >=0 number of muted audiohooks + * \retval -1 failure + */ +int ast_audiohook_set_mute_all(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/main/audiohook.c b/main/audiohook.c index 59ea0fa02d..321a94d52c 100644 --- a/main/audiohook.c +++ b/main/audiohook.c @@ -34,12 +34,12 @@ #include "asterisk/channel.h" #include "asterisk/utils.h" #include "asterisk/lock.h" -#include "asterisk/linkedlists.h" #include "asterisk/audiohook.h" #include "asterisk/slinfactory.h" #include "asterisk/frame.h" #include "asterisk/translate.h" #include "asterisk/format_cache.h" +#include "asterisk/test.h" #define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*!< Tolerance in milliseconds for audiohooks synchronization */ #define AST_AUDIOHOOK_SMALL_QUEUE_TOLERANCE 100 /*!< When small queue is enabled, this is the maximum amount of audio that can remain queued at a time. */ @@ -1376,3 +1376,33 @@ int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum as return (audiohook ? 0 : -1); } + +int ast_audiohook_set_mute_all(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clearmute) +{ + struct ast_audiohook *audiohook = NULL; + int count = 0; + + ast_channel_lock(chan); + + if (!ast_channel_audiohooks(chan)) { + return -1; + } + + AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list) { + if (!strcasecmp(audiohook->source, source)) { + count++; + if (clearmute) { + ast_clear_flag(audiohook, flag); + } else { + ast_set_flag(audiohook, flag); + } + } + } + + ast_test_suite_event_notify("AUDIOHOOK_GROUP_MUTE_TOGGLE", "Channel: %s\r\nSource: %s\r\nCount: %d\r\n", + ast_channel_name(chan), source, count); + + ast_channel_unlock(chan); + + return count; +}