<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19995">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_mixmonitor: MixMonitorMute by MixMonitor ID<br><br>While it is possible to create multiple mixmonitor instances<br>on a channel, it was not previously possible to mute individual<br>instances.<br><br>This change includes the ability to specify the MixMonitorID<br>when calling the manager action: MixMonitorMute.  This will<br>allow an individual MixMonitor instance to be muted via id.<br>This id can be stored as a channel variable using the 'i'<br>MixMonitor option.<br><br>As part of this change, if no MixMonitorID is specified in<br>the manager action MixMonitorMute, Asterisk will set the mute<br>flag on all MixMonitor spy-type audiohooks on the channel.<br>This is done via the new audiohook function:<br>ast_audiohook_set_mute_all.<br><br>ASTERISK-30464<br><br>Change-Id: Ibba8c7e750577aa1595a24b23316ef445245be98<br>---<br>M apps/app_mixmonitor.c<br>A doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt<br>M include/asterisk/audiohook.h<br>M main/audiohook.c<br>4 files changed, 150 insertions(+), 8 deletions(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c</span><br><span>index a0eb1db..95ecd71 100644</span><br><span>--- a/apps/app_mixmonitor.c</span><br><span>+++ b/apps/app_mixmonitor.c</span><br><span>@@ -1403,6 +1403,50 @@</span><br><span>    return CLI_SUCCESS;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief  Mute / unmute  an individual MixMonitor by id */</span><br><span style="color: hsl(120, 100%, 40%);">+static int mute_mixmonitor_instance(struct ast_channel *chan, const char *data,</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                   enum ast_audiohook_flags flag, int clearmute)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_datastore *datastore = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       char *parse = "";</span><br><span style="color: hsl(120, 100%, 40%);">+   struct mixmonitor_ds *mixmonitor_ds;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_APP_ARG(mixmonid);</span><br><span style="color: hsl(120, 100%, 40%);">+        );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!ast_strlen_zero(data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         parse = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_STANDARD_APP_ARGS(args, parse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info,</span><br><span style="color: hsl(120, 100%, 40%);">+         S_OR(args.mixmonid, NULL));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!datastore) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+             return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     mixmonitor_ds = datastore->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_mutex_lock(&mixmonitor_ds->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (mixmonitor_ds->audiohook) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (clearmute) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_clear_flag(mixmonitor_ds->audiohook, flag);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_set_flag(mixmonitor_ds->audiohook, flag);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_mutex_unlock(&mixmonitor_ds->lock);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief  Mute / unmute  a MixMonitor channel */</span><br><span> static int manager_mute_mixmonitor(struct mansession *s, const struct message *m)</span><br><span> {</span><br><span>@@ -1411,7 +1455,8 @@</span><br><span>       const char *id = astman_get_header(m, "ActionID");</span><br><span>         const char *state = astman_get_header(m, "State");</span><br><span>         const char *direction = astman_get_header(m,"Direction");</span><br><span style="color: hsl(0, 100%, 40%);">-     int clearmute = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    const char *mixmonitor_id = astman_get_header(m, "MixMonitorID");</span><br><span style="color: hsl(120, 100%, 40%);">+   int clearmute = 1, mutedcount = 0;</span><br><span>   enum ast_audiohook_flags flag;</span><br><span>       RAII_VAR(struct stasis_message *, stasis_message, NULL, ao2_cleanup);</span><br><span>        RAII_VAR(struct ast_json *, stasis_message_blob, NULL, ast_json_unref);</span><br><span>@@ -1450,15 +1495,28 @@</span><br><span>            return AMI_SUCCESS;</span><br><span>  }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_audiohook_set_mute(c, mixmonitor_spy_type, flag, clearmute)) {</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">-           astman_send_error(s, m, "Cannot set mute flag");</span><br><span style="color: hsl(0, 100%, 40%);">-              return AMI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_strlen_zero(mixmonitor_id)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         mutedcount = ast_audiohook_set_mute_all(c, mixmonitor_spy_type, flag, clearmute);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (mutedcount < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_channel_unref(c);</span><br><span style="color: hsl(120, 100%, 40%);">+                 astman_send_error(s, m, "Cannot set mute flag");</span><br><span style="color: hsl(120, 100%, 40%);">+                    return AMI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (mute_mixmonitor_instance(c, mixmonitor_id, flag, clearmute)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_channel_unref(c);</span><br><span style="color: hsl(120, 100%, 40%);">+                 astman_send_error(s, m, "Cannot set mute flag");</span><br><span style="color: hsl(120, 100%, 40%);">+                    return AMI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+           }</span><br><span style="color: hsl(120, 100%, 40%);">+             mutedcount = 1;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   stasis_message_blob = ast_json_pack("{s: s, s: b}",</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       stasis_message_blob = ast_json_pack("{s: s, s: b, s: s, s: i}",</span><br><span>            "direction", direction,</span><br><span style="color: hsl(0, 100%, 40%);">-               "state", ast_true(state));</span><br><span style="color: hsl(120, 100%, 40%);">+          "state", ast_true(state),</span><br><span style="color: hsl(120, 100%, 40%);">+           "mixmonitorid", mixmonitor_id,</span><br><span style="color: hsl(120, 100%, 40%);">+              "count", mutedcount);</span><br><span> </span><br><span>  stasis_message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(c),</span><br><span>                 ast_channel_mixmonitor_mute_type(), stasis_message_blob);</span><br><span>diff --git a/doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt b/doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..958a914</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/app_mixmonitor_mute_by_id.txt</span><br><span>@@ -0,0 +1,17 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: app_mixmonitor</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: audiohook</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: manager</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+It is now possible to specify the MixMonitorID when calling</span><br><span style="color: hsl(120, 100%, 40%);">+the manager action: MixMonitorMute.  This will allow an</span><br><span style="color: hsl(120, 100%, 40%);">+individual MixMonitor instance to be muted via ID.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The MixMonitorID can be stored as a channel variable using</span><br><span style="color: hsl(120, 100%, 40%);">+the 'i' MixMonitor option and is returned upon creation if</span><br><span style="color: hsl(120, 100%, 40%);">+this option is used.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+As part of this change, if no MixMonitorID is specified in</span><br><span style="color: hsl(120, 100%, 40%);">+the manager action MixMonitorMute, Asterisk will set the mute</span><br><span style="color: hsl(120, 100%, 40%);">+flag on all MixMonitor audiohooks on the channel.  Previous</span><br><span style="color: hsl(120, 100%, 40%);">+behavior would set the flag on the first MixMonitor audiohook</span><br><span style="color: hsl(120, 100%, 40%);">+found.</span><br><span>diff --git a/include/asterisk/audiohook.h b/include/asterisk/audiohook.h</span><br><span>index a5d7e0c..e19c833 100644</span><br><span>--- a/include/asterisk/audiohook.h</span><br><span>+++ b/include/asterisk/audiohook.h</span><br><span>@@ -358,6 +358,16 @@</span><br><span>  */</span><br><span> int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Mute frames read from or written for all audiohooks on a channel</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan Channel to muck with</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param source Type of audiohooks</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param flag which direction to set / clear</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param clear set or clear muted frames on direction based on flag parameter</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval >=0 number of muted audiohooks</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_audiohook_set_mute_all(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #if defined(__cplusplus) || defined(c_plusplus)</span><br><span> }</span><br><span> #endif</span><br><span>diff --git a/main/audiohook.c b/main/audiohook.c</span><br><span>index 59ea0fa..321a94d 100644</span><br><span>--- a/main/audiohook.c</span><br><span>+++ b/main/audiohook.c</span><br><span>@@ -34,12 +34,12 @@</span><br><span> #include "asterisk/channel.h"</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/lock.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/linkedlists.h"</span><br><span> #include "asterisk/audiohook.h"</span><br><span> #include "asterisk/slinfactory.h"</span><br><span> #include "asterisk/frame.h"</span><br><span> #include "asterisk/translate.h"</span><br><span> #include "asterisk/format_cache.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/test.h"</span><br><span> </span><br><span> #define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*!< Tolerance in milliseconds for audiohooks synchronization */</span><br><span> #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. */</span><br><span>@@ -1376,3 +1376,33 @@</span><br><span> </span><br><span>       return (audiohook ? 0 : -1);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_audiohook_set_mute_all(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clearmute)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_audiohook *audiohook = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       int count = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!ast_channel_audiohooks(chan)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_LIST_TRAVERSE(&ast_channel_audiohooks(chan)->spy_list, audiohook, list) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!strcasecmp(audiohook->source, source)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      count++;</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (clearmute) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_clear_flag(audiohook, flag);</span><br><span style="color: hsl(120, 100%, 40%);">+                      } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_set_flag(audiohook, flag);</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_test_suite_event_notify("AUDIOHOOK_GROUP_MUTE_TOGGLE", "Channel: %s\r\nSource: %s\r\nCount: %d\r\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                                                  ast_channel_name(chan), source, count);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_channel_unlock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return count;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19995">change 19995</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/19995"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: certified/18.9 </div>
<div style="display:none"> Gerrit-Change-Id: Ibba8c7e750577aa1595a24b23316ef445245be98 </div>
<div style="display:none"> Gerrit-Change-Number: 19995 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Michael Bradeen <mbradeen@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>