<p>George Joseph <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19605">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:
Joshua Colp: Looks good to me, but someone else must approve
Benjamin Keith Ford: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved; Approved for Submit
N A: Looks good to me, but someone else must approve
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_monitor: Remove deprecated module.<br><br>ASTERISK-30303<br><br>Change-Id: I0462caefb4f9544e2e2baa23c498858310b52d50<br>---<br>M README-SERIOUSLY.bestpractices.md<br>M apps/Makefile<br>M apps/app_meetme.c<br>M apps/app_mixmonitor.c<br>M apps/app_queue.c<br>M bridges/bridge_builtin_features.c<br>M channels/Makefile<br>M configs/samples/features.conf.sample<br>M configs/samples/queues.conf.sample<br>M configs/samples/stasis.conf.sample<br>A doc/UPGRADE-staging/res_monitor_removal.txt<br>M include/asterisk/bridge_features.h<br>M include/asterisk/channel.h<br>M include/asterisk/doxygen/architecture.h<br>M include/asterisk/features_config.h<br>D include/asterisk/monitor.h<br>M include/asterisk/stasis_channels.h<br>M main/asterisk.dynamics<br>M main/bridge_basic.c<br>M main/bridge_channel.c<br>M main/channel.c<br>M main/channel_internal_api.c<br>M main/features.c<br>M main/features_config.c<br>M main/manager_channels.c<br>M main/stasis.c<br>M main/stasis_channels.c<br>M menuselect/example_menuselect-tree<br>M menuselect/test/menuselect-tree<br>M pbx/Makefile<br>M pbx/ael/ael-test/ael-test2/apptest.ael2<br>M pbx/ael/ael-test/ael-test4/apptest.ael2<br>M pbx/ael/ael-test/ael-test5/extensions.ael<br>M pbx/ael/ael-test/ael-test6/extensions.ael<br>D res/res_monitor.c<br>D res/res_monitor.exports.in<br>36 files changed, 61 insertions(+), 1,720 deletions(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/README-SERIOUSLY.bestpractices.md b/README-SERIOUSLY.bestpractices.md</span><br><span>index f021f9d..fa4b0a6 100644</span><br><span>--- a/README-SERIOUSLY.bestpractices.md</span><br><span>+++ b/README-SERIOUSLY.bestpractices.md</span><br><span>@@ -83,10 +83,10 @@</span><br><span> </span><br><span> The CALLERID(num) and CALLERID(name) values are other commonly used values that</span><br><span> are sources of data potentially supplied by outside sources. If you use these</span><br><span style="color: hsl(0, 100%, 40%);">-values as parameters to the System(), MixMonitor(), or Monitor() applications</span><br><span style="color: hsl(0, 100%, 40%);">-or the SHELL() dialplan function, you can allow injection of arbitrary operating</span><br><span style="color: hsl(0, 100%, 40%);">-system command execution. The FILTER() dialplan function is available to remove</span><br><span style="color: hsl(0, 100%, 40%);">-dangerous characters from untrusted strings to block the command injection.</span><br><span style="color: hsl(120, 100%, 40%);">+values as parameters to the System() or MixMonitor() applications or the SHELL()</span><br><span style="color: hsl(120, 100%, 40%);">+dialplan function, you can allow injection of arbitrary operating system command</span><br><span style="color: hsl(120, 100%, 40%);">+execution. The FILTER() dialplan function is available to remove dangerous</span><br><span style="color: hsl(120, 100%, 40%);">+characters from untrusted strings to block the command injection.</span><br><span> </span><br><span> </span><br><span> ### Strict Pattern Matching</span><br><span>diff --git a/apps/Makefile b/apps/Makefile</span><br><span>index 02b705d..50b3fcc 100644</span><br><span>--- a/apps/Makefile</span><br><span>+++ b/apps/Makefile</span><br><span>@@ -58,6 +58,6 @@</span><br><span> app_while.o: _ASTCFLAGS+=$(AST_NO_FORMAT_TRUNCATION)</span><br><span> </span><br><span> ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)</span><br><span style="color: hsl(0, 100%, 40%);">- LIBS+= -lres_ael_share.so -lres_monitor.so -lres_speech.so</span><br><span style="color: hsl(120, 100%, 40%);">+ LIBS+= -lres_ael_share.so -lres_speech.so</span><br><span> LIBS+= -lres_smdi.so</span><br><span> endif</span><br><span>diff --git a/apps/app_meetme.c b/apps/app_meetme.c</span><br><span>index 812b817..0d5bdc2 100644</span><br><span>--- a/apps/app_meetme.c</span><br><span>+++ b/apps/app_meetme.c</span><br><span>@@ -3678,7 +3678,7 @@</span><br><span> ast_func_write(chan, "DENOISE(rx)", "on");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- retrydahdi = (strcasecmp(ast_channel_tech(chan)->type, "DAHDI") || (ast_channel_audiohooks(chan) || ast_channel_monitor(chan)) ? 1 : 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ retrydahdi = (strcasecmp(ast_channel_tech(chan)->type, "DAHDI") || (ast_channel_audiohooks(chan)) ? 1 : 0);</span><br><span> user->dahdichannel = !retrydahdi;</span><br><span> </span><br><span> dahdiretry:</span><br><span>@@ -4196,14 +4196,14 @@</span><br><span> if (c) {</span><br><span> char dtmfstr[2] = "";</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_fd(c, 0) != origfd || (user->dahdichannel && (ast_channel_audiohooks(c) || ast_channel_monitor(c)))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_channel_fd(c, 0) != origfd || (user->dahdichannel && ast_channel_audiohooks(c))) {</span><br><span> if (using_pseudo) {</span><br><span> /* Kill old pseudo */</span><br><span> close(fd);</span><br><span> using_pseudo = 0;</span><br><span> }</span><br><span> ast_debug(1, "Ooh, something swapped out under us, starting over\n");</span><br><span style="color: hsl(0, 100%, 40%);">- retrydahdi = (strcasecmp(ast_channel_tech(c)->type, "DAHDI") || (ast_channel_audiohooks(c) || ast_channel_monitor(c)) ? 1 : 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ retrydahdi = (strcasecmp(ast_channel_tech(c)->type, "DAHDI") || ast_channel_audiohooks(c) ? 1 : 0);</span><br><span> user->dahdichannel = !retrydahdi;</span><br><span> goto dahdiretry;</span><br><span> }</span><br><span>diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c</span><br><span>index 3ce1a76..332e9b8 100644</span><br><span>--- a/apps/app_mixmonitor.c</span><br><span>+++ b/apps/app_mixmonitor.c</span><br><span>@@ -183,10 +183,7 @@</span><br><span> function <variable>FILTER()</variable>.</para></warning></span><br><span> </description></span><br><span> <see-also></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">Monitor</ref></span><br><span> <ref type="application">StopMixMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">PauseMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">UnpauseMonitor</ref></span><br><span> <ref type="function">AUDIOHOOK_INHERIT</ref></span><br><span> </see-also></span><br><span> </application></span><br><span>diff --git a/apps/app_queue.c b/apps/app_queue.c</span><br><span>index 4b6b72b..c5b7d10 100644</span><br><span>--- a/apps/app_queue.c</span><br><span>+++ b/apps/app_queue.c</span><br><span>@@ -41,7 +41,6 @@</span><br><span> * - Position announcement</span><br><span> * - Abandoned/completed call counters</span><br><span> * - Failout timer passed as optional app parameter</span><br><span style="color: hsl(0, 100%, 40%);">- * - Optional monitoring of calls, started when call is answered</span><br><span> *</span><br><span> * Patch Version 1.07 2003-12-24 01</span><br><span> *</span><br><span>@@ -63,7 +62,6 @@</span><br><span> */</span><br><span> </span><br><span> /*** MODULEINFO</span><br><span style="color: hsl(0, 100%, 40%);">- <use type="module">res_monitor</use></span><br><span> <support_level>core</support_level></span><br><span> ***/</span><br><span> </span><br><span>@@ -88,7 +86,6 @@</span><br><span> #include "asterisk/cli.h"</span><br><span> #include "asterisk/manager.h"</span><br><span> #include "asterisk/config.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/monitor.h"</span><br><span> #include "asterisk/utils.h"</span><br><span> #include "asterisk/causes.h"</span><br><span> #include "asterisk/astdb.h"</span><br><span>@@ -222,14 +219,6 @@</span><br><span> <option name="T"></span><br><span> <para>Allow the <emphasis>calling</emphasis> user to transfer the call.</para></span><br><span> </option></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="w"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Allow the <emphasis>called</emphasis> user to write the conversation to</span><br><span style="color: hsl(0, 100%, 40%);">- disk via Monitor.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="W"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Allow the <emphasis>calling</emphasis> user to write the conversation to</span><br><span style="color: hsl(0, 100%, 40%);">- disk via Monitor.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span> <option name="x"></span><br><span> <para>Allow the <emphasis>called</emphasis> user to write the conversation</span><br><span> to disk via MixMonitor.</para></span><br><span>@@ -1862,7 +1851,6 @@</span><br><span> int servicelevel; /*!< seconds setting for servicelevel*/</span><br><span> int callscompletedinsl; /*!< Number of calls answered with servicelevel*/</span><br><span> char monfmt[8]; /*!< Format to use when recording calls */</span><br><span style="color: hsl(0, 100%, 40%);">- int montype; /*!< Monitor type Monitor vs. MixMonitor */</span><br><span> int count; /*!< How many entries */</span><br><span> int maxlen; /*!< Max number of entries */</span><br><span> int wrapuptime; /*!< Wrapup Time */</span><br><span>@@ -2966,7 +2954,6 @@</span><br><span> q->setqueuevar = 0;</span><br><span> q->setqueueentryvar = 0;</span><br><span> q->autofill = autofill_default;</span><br><span style="color: hsl(0, 100%, 40%);">- q->montype = montype_default;</span><br><span> q->monfmt[0] = '\0';</span><br><span> q->reportholdtime = 0;</span><br><span> q->wrapuptime = 0;</span><br><span>@@ -3448,10 +3435,6 @@</span><br><span> }</span><br><span> } else if (!strcasecmp(param, "autofill")) {</span><br><span> q->autofill = ast_true(val);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!strcasecmp(param, "monitor-type")) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!strcasecmp(val, "mixmonitor")) {</span><br><span style="color: hsl(0, 100%, 40%);">- q->montype = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span> } else if (!strcasecmp(param, "autopause")) {</span><br><span> q->autopause = autopause2int(val);</span><br><span> } else if (!strcasecmp(param, "autopausedelay")) {</span><br><span>@@ -6907,7 +6890,6 @@</span><br><span> char oldcontext[AST_MAX_CONTEXT]="";</span><br><span> char queuename[256]="";</span><br><span> struct ast_channel *peer;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *which;</span><br><span> struct callattempt *lpeer;</span><br><span> struct member *member;</span><br><span> struct ast_app *application;</span><br><span>@@ -6922,7 +6904,6 @@</span><br><span> char *agiexec = NULL;</span><br><span> char *gosubexec = NULL;</span><br><span> const char *monitorfilename;</span><br><span style="color: hsl(0, 100%, 40%);">- char tmpid[256];</span><br><span> int forwardsallowed = 1;</span><br><span> int block_connected_line = 0;</span><br><span> struct ao2_iterator memi;</span><br><span>@@ -6931,7 +6912,6 @@</span><br><span> time_t starttime;</span><br><span> </span><br><span> memset(&bridge_config, 0, sizeof(bridge_config));</span><br><span style="color: hsl(0, 100%, 40%);">- tmpid[0] = 0;</span><br><span> time(&now);</span><br><span> </span><br><span> /* If we've already exceeded our timeout, then just stop</span><br><span>@@ -7252,32 +7232,7 @@</span><br><span> </span><br><span> /* Begin Monitoring */</span><br><span> if (*qe->parent->monfmt) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!qe->parent->montype) {</span><br><span style="color: hsl(0, 100%, 40%);">- const char *monexec;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1, "Starting Monitor as requested.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(qe->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- if ((monexec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC")) || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS")) {</span><br><span style="color: hsl(0, 100%, 40%);">- which = qe->chan;</span><br><span style="color: hsl(0, 100%, 40%);">- monexec = monexec ? ast_strdupa(monexec) : NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- which = peer;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(qe->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- if (monitorfilename) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (qe->chan) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_start(which, qe->parent->monfmt, ast_channel_uniqueid(qe->chan), 1, X_REC_IN | X_REC_OUT, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- /* Last ditch effort -- no channel, make up something */</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(tmpid, sizeof(tmpid), "chan-%lx", (unsigned long)ast_random());</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(monexec)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_setjoinfiles(which, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- setup_mixmonitor(qe, monitorfilename);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ setup_mixmonitor(qe, monitorfilename);</span><br><span> }</span><br><span> /* Drop out of the queue at this point, to prepare for next caller */</span><br><span> leave_queue(qe);</span><br><span>@@ -11802,5 +11757,4 @@</span><br><span> .unload = unload_module,</span><br><span> .reload = reload,</span><br><span> .load_pri = AST_MODPRI_DEVSTATE_CONSUMER,</span><br><span style="color: hsl(0, 100%, 40%);">- .optional_modules = "res_monitor",</span><br><span> );</span><br><span>diff --git a/bridges/bridge_builtin_features.c b/bridges/bridge_builtin_features.c</span><br><span>index 671cfb9..2aaa2e8 100644</span><br><span>--- a/bridges/bridge_builtin_features.c</span><br><span>+++ b/bridges/bridge_builtin_features.c</span><br><span>@@ -26,7 +26,6 @@</span><br><span> */</span><br><span> </span><br><span> /*** MODULEINFO</span><br><span style="color: hsl(0, 100%, 40%);">- <use type="module">res_monitor</use></span><br><span> <support_level>core</support_level></span><br><span> ***/</span><br><span> </span><br><span>@@ -49,7 +48,6 @@</span><br><span> #include "asterisk/pbx.h"</span><br><span> #include "asterisk/parking.h"</span><br><span> #include "asterisk/features_config.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/monitor.h"</span><br><span> #include "asterisk/mixmonitor.h"</span><br><span> #include "asterisk/audiohook.h"</span><br><span> #include "asterisk/causes.h"</span><br><span>@@ -78,7 +76,7 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static enum set_touch_variables_res set_touch_variables(struct ast_channel *chan, int is_mixmonitor, char **touch_format, char **touch_monitor, char **touch_monitor_prefix)</span><br><span style="color: hsl(120, 100%, 40%);">+static enum set_touch_variables_res set_touch_variables(struct ast_channel *chan, char **touch_format, char **touch_monitor, char **touch_monitor_prefix)</span><br><span> {</span><br><span> enum set_touch_variables_res res = SET_TOUCH_UNSET;</span><br><span> const char *var_format;</span><br><span>@@ -87,15 +85,10 @@</span><br><span> </span><br><span> SCOPED_CHANNELLOCK(lock, chan);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (is_mixmonitor) {</span><br><span style="color: hsl(0, 100%, 40%);">- var_format = "TOUCH_MIXMONITOR_FORMAT";</span><br><span style="color: hsl(0, 100%, 40%);">- var_monitor = "TOUCH_MIXMONITOR";</span><br><span style="color: hsl(0, 100%, 40%);">- var_prefix = "TOUCH_MIXMONITOR_PREFIX";</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- var_format = "TOUCH_MONITOR_FORMAT";</span><br><span style="color: hsl(0, 100%, 40%);">- var_monitor = "TOUCH_MONITOR";</span><br><span style="color: hsl(0, 100%, 40%);">- var_prefix = "TOUCH_MONITOR_PREFIX";</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(120, 100%, 40%);">+ var_format = "TOUCH_MIXMONITOR_FORMAT";</span><br><span style="color: hsl(120, 100%, 40%);">+ var_monitor = "TOUCH_MIXMONITOR";</span><br><span style="color: hsl(120, 100%, 40%);">+ var_prefix = "TOUCH_MIXMONITOR_PREFIX";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> set_touch_variable(&res, chan, var_format, touch_format);</span><br><span> set_touch_variable(&res, chan, var_monitor, touch_monitor);</span><br><span> set_touch_variable(&res, chan, var_prefix, touch_monitor_prefix);</span><br><span>@@ -103,199 +96,6 @@</span><br><span> return res;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void stop_automonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *stop_message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "AutoMonitor used to stop recording call.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(peer_chan);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(peer_chan)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(peer_chan)->stop(peer_chan, 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "Cannot stop AutoMonitor for %s\n", ast_channel_name(bridge_channel->chan));</span><br><span style="color: hsl(0, 100%, 40%);">- if (features_cfg && !(ast_strlen_zero(features_cfg->recordingfailsound))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(peer_chan);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- /* Something else removed the Monitor before we got to it. */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(peer_chan);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(peer_chan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (features_cfg && !(ast_strlen_zero(features_cfg->courtesytone))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_write_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(stop_message)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, stop_message, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_write_playfile(bridge_channel, NULL, stop_message, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void start_automonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *start_message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char *touch_filename;</span><br><span style="color: hsl(0, 100%, 40%);">- size_t len;</span><br><span style="color: hsl(0, 100%, 40%);">- int x;</span><br><span style="color: hsl(0, 100%, 40%);">- enum set_touch_variables_res set_touch_res;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(char *, touch_format, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(char *, touch_monitor, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(char *, touch_monitor_prefix, NULL, ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- set_touch_res = set_touch_variables(bridge_channel->chan, 0, &touch_format,</span><br><span style="color: hsl(0, 100%, 40%);">- &touch_monitor, &touch_monitor_prefix);</span><br><span style="color: hsl(0, 100%, 40%);">- switch (set_touch_res) {</span><br><span style="color: hsl(0, 100%, 40%);">- case SET_TOUCH_SUCCESS:</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SET_TOUCH_UNSET:</span><br><span style="color: hsl(0, 100%, 40%);">- set_touch_res = set_touch_variables(peer_chan, 0, &touch_format, &touch_monitor,</span><br><span style="color: hsl(0, 100%, 40%);">- &touch_monitor_prefix);</span><br><span style="color: hsl(0, 100%, 40%);">- if (set_touch_res == SET_TOUCH_ALLOC_FAILURE) {</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case SET_TOUCH_ALLOC_FAILURE:</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(touch_monitor)) {</span><br><span style="color: hsl(0, 100%, 40%);">- len = strlen(touch_monitor) + 50;</span><br><span style="color: hsl(0, 100%, 40%);">- touch_filename = ast_alloca(len);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(touch_filename, len, "%s-%ld-%s",</span><br><span style="color: hsl(0, 100%, 40%);">- S_OR(touch_monitor_prefix, "auto"),</span><br><span style="color: hsl(0, 100%, 40%);">- (long) time(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- touch_monitor);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- char *caller_chan_id;</span><br><span style="color: hsl(0, 100%, 40%);">- char *peer_chan_id;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- caller_chan_id = ast_strdupa(S_COR(ast_channel_caller(bridge_channel->chan)->id.number.valid,</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_caller(bridge_channel->chan)->id.number.str, ast_channel_name(bridge_channel->chan)));</span><br><span style="color: hsl(0, 100%, 40%);">- peer_chan_id = ast_strdupa(S_COR(ast_channel_caller(peer_chan)->id.number.valid,</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_caller(peer_chan)->id.number.str, ast_channel_name(peer_chan)));</span><br><span style="color: hsl(0, 100%, 40%);">- len = strlen(caller_chan_id) + strlen(peer_chan_id) + 50;</span><br><span style="color: hsl(0, 100%, 40%);">- touch_filename = ast_alloca(len);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(touch_filename, len, "%s-%ld-%s-%s",</span><br><span style="color: hsl(0, 100%, 40%);">- S_OR(touch_monitor_prefix, "auto"),</span><br><span style="color: hsl(0, 100%, 40%);">- (long) time(NULL),</span><br><span style="color: hsl(0, 100%, 40%);">- caller_chan_id,</span><br><span style="color: hsl(0, 100%, 40%);">- peer_chan_id);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for (x = 0; x < strlen(touch_filename); x++) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (touch_filename[x] == '/') {</span><br><span style="color: hsl(0, 100%, 40%);">- touch_filename[x] = '-';</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "AutoMonitor used to record call. Filename: %s\n", touch_filename);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_monitor_start(peer_chan, touch_format, touch_filename, 1, X_REC_IN | X_REC_OUT, NULL)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "AutoMonitor feature was tried by '%s' but monitor failed to start.\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_name(bridge_channel->chan));</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_setjoinfiles(peer_chan, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_write_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(start_message)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, start_message, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_write_playfile(bridge_channel, NULL, start_message, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(bridge_channel->chan, "TOUCH_MONITOR_OUTPUT", touch_filename);</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(peer_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int feature_automonitor(struct ast_bridge_channel *bridge_channel, void *hook_pvt)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- const char *start_message;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *stop_message;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_bridge_features_automonitor *options = hook_pvt;</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_bridge_features_monitor start_stop = options ? options->start_stop : AUTO_MONITOR_TOGGLE;</span><br><span style="color: hsl(0, 100%, 40%);">- int is_monitoring;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_channel *, peer_chan, NULL, ast_channel_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_features_general_config *, features_cfg, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- features_cfg = ast_get_chan_features_general_config(bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_lock_bridge(bridge_channel);</span><br><span style="color: hsl(0, 100%, 40%);">- peer_chan = ast_bridge_peer_nolock(bridge_channel->bridge, bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_unlock(bridge_channel->bridge);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!peer_chan) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "Cannot start AutoMonitor for %s - can not determine peer in bridge.\n",</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_name(bridge_channel->chan));</span><br><span style="color: hsl(0, 100%, 40%);">- if (features_cfg && !ast_strlen_zero(features_cfg->recordingfailsound)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->recordingfailsound, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">- start_message = pbx_builtin_getvar_helper(bridge_channel->chan,</span><br><span style="color: hsl(0, 100%, 40%);">- "TOUCH_MONITOR_MESSAGE_START");</span><br><span style="color: hsl(0, 100%, 40%);">- start_message = ast_strdupa(S_OR(start_message, ""));</span><br><span style="color: hsl(0, 100%, 40%);">- stop_message = pbx_builtin_getvar_helper(bridge_channel->chan,</span><br><span style="color: hsl(0, 100%, 40%);">- "TOUCH_MONITOR_MESSAGE_STOP");</span><br><span style="color: hsl(0, 100%, 40%);">- stop_message = ast_strdupa(S_OR(stop_message, ""));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(bridge_channel->chan);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- is_monitoring = ast_channel_monitor(peer_chan) != NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- switch (start_stop) {</span><br><span style="color: hsl(0, 100%, 40%);">- case AUTO_MONITOR_TOGGLE:</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_monitoring) {</span><br><span style="color: hsl(0, 100%, 40%);">- stop_automonitor(bridge_channel, peer_chan, features_cfg, stop_message);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- start_automonitor(bridge_channel, peer_chan, features_cfg, start_message);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- case AUTO_MONITOR_START:</span><br><span style="color: hsl(0, 100%, 40%);">- if (!is_monitoring) {</span><br><span style="color: hsl(0, 100%, 40%);">- start_automonitor(bridge_channel, peer_chan, features_cfg, start_message);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "AutoMonitor already recording call.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- case AUTO_MONITOR_STOP:</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_monitoring) {</span><br><span style="color: hsl(0, 100%, 40%);">- stop_automonitor(bridge_channel, peer_chan, features_cfg, stop_message);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_verb(4, "AutoMonitor already stopped on call.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- break;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /*</span><br><span style="color: hsl(0, 100%, 40%);">- * Fake start/stop to invoker so will think it did something but</span><br><span style="color: hsl(0, 100%, 40%);">- * was already in that mode.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- if (features_cfg && !ast_strlen_zero(features_cfg->courtesytone)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, features_cfg->courtesytone, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (is_monitoring) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(start_message)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, start_message, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(stop_message)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_channel_queue_playfile(bridge_channel, NULL, stop_message, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span> </span><br><span> static void stop_automixmonitor(struct ast_bridge_channel *bridge_channel, struct ast_channel *peer_chan, struct ast_features_general_config *features_cfg, const char *stop_message)</span><br><span> {</span><br><span>@@ -331,13 +131,13 @@</span><br><span> RAII_VAR(char *, touch_monitor, NULL, ast_free);</span><br><span> RAII_VAR(char *, touch_monitor_prefix, NULL, ast_free);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- set_touch_res = set_touch_variables(bridge_channel->chan, 1, &touch_format,</span><br><span style="color: hsl(120, 100%, 40%);">+ set_touch_res = set_touch_variables(bridge_channel->chan, &touch_format,</span><br><span> &touch_monitor, &touch_monitor_prefix);</span><br><span> switch (set_touch_res) {</span><br><span> case SET_TOUCH_SUCCESS:</span><br><span> break;</span><br><span> case SET_TOUCH_UNSET:</span><br><span style="color: hsl(0, 100%, 40%);">- set_touch_res = set_touch_variables(peer_chan, 1, &touch_format, &touch_monitor,</span><br><span style="color: hsl(120, 100%, 40%);">+ set_touch_res = set_touch_variables(peer_chan, &touch_format, &touch_monitor,</span><br><span> &touch_monitor_prefix);</span><br><span> if (set_touch_res == SET_TOUCH_ALLOC_FAILURE) {</span><br><span> return;</span><br><span>@@ -503,7 +303,6 @@</span><br><span> static int unload_module(void)</span><br><span> {</span><br><span> ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_HANGUP);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_AUTOMON);</span><br><span> ast_bridge_features_unregister(AST_BRIDGE_BUILTIN_AUTOMIXMON);</span><br><span> </span><br><span> return 0;</span><br><span>@@ -512,7 +311,6 @@</span><br><span> static int load_module(void)</span><br><span> {</span><br><span> ast_bridge_features_register(AST_BRIDGE_BUILTIN_HANGUP, feature_hangup, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_bridge_features_register(AST_BRIDGE_BUILTIN_AUTOMON, feature_automonitor, NULL);</span><br><span> ast_bridge_features_register(AST_BRIDGE_BUILTIN_AUTOMIXMON, feature_automixmonitor, NULL);</span><br><span> </span><br><span> /* This module cannot be unloaded until shutdown */</span><br><span>@@ -525,5 +323,4 @@</span><br><span> .support_level = AST_MODULE_SUPPORT_CORE,</span><br><span> .load = load_module,</span><br><span> .unload = unload_module,</span><br><span style="color: hsl(0, 100%, 40%);">- .optional_modules = "res_monitor",</span><br><span> );</span><br><span>diff --git a/channels/Makefile b/channels/Makefile</span><br><span>index 2d243d2..0f8d132 100644</span><br><span>--- a/channels/Makefile</span><br><span>+++ b/channels/Makefile</span><br><span>@@ -19,10 +19,6 @@</span><br><span> </span><br><span> include $(ASTTOPDIR)/Makefile.moddir_rules</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)</span><br><span style="color: hsl(0, 100%, 40%);">- LIBS+= -lres_monitor.so</span><br><span style="color: hsl(0, 100%, 40%);">-endif</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> $(call MOD_ADD_C,chan_iax2,$(wildcard iax2/*.c))</span><br><span> iax2/parser.o: _ASTCFLAGS+=$(call get_menuselect_cflags,MALLOC_DEBUG)</span><br><span> </span><br><span>diff --git a/configs/samples/features.conf.sample b/configs/samples/features.conf.sample</span><br><span>index 3284326..ba2f481 100644</span><br><span>--- a/configs/samples/features.conf.sample</span><br><span>+++ b/configs/samples/features.conf.sample</span><br><span>@@ -1,5 +1,5 @@</span><br><span> ;</span><br><span style="color: hsl(0, 100%, 40%);">-; Sample Call Features (transfer, monitor/mixmonitor, etc) configuration</span><br><span style="color: hsl(120, 100%, 40%);">+; Sample Call Features (transfer, mixmonitor, etc) configuration</span><br><span> ;</span><br><span> </span><br><span> ; Note: From Asterisk 12 - All parking lot configuration is now done in res_parking.conf</span><br><span>@@ -18,7 +18,7 @@</span><br><span> ;pickupfailsound = beeperr ; to indicate that the pickup failed (default: no sound)</span><br><span> ;featuredigittimeout = 1000 ; Max time (ms) between digits for</span><br><span> ; feature activation (default is 1000 ms)</span><br><span style="color: hsl(0, 100%, 40%);">-;recordingfailsound = beeperr ; indicates that a one-touch monitor or one-touch mixmonitor feature failed</span><br><span style="color: hsl(120, 100%, 40%);">+;recordingfailsound = beeperr ; indicates that a one-touch mixmonitor feature failed</span><br><span> ; to be applied to the call. (default: no sound)</span><br><span> ;atxfernoanswertimeout = 15 ; Timeout for answer on attended transfer default is 15 seconds.</span><br><span> ;atxferdropcall = no ; If someone does an attended transfer, then hangs up before the transfer</span><br><span>@@ -45,7 +45,6 @@</span><br><span> [featuremap]</span><br><span> ;blindxfer => #1 ; Blind transfer (default is #) -- Make sure to set the T and/or t option in the Dial() or Queue() app call!</span><br><span> ;disconnect => *0 ; Disconnect (default is *) -- Make sure to set the H and/or h option in the Dial() or Queue() app call!</span><br><span style="color: hsl(0, 100%, 40%);">-;automon => *1 ; One Touch Record a.k.a. Touch Monitor -- Make sure to set the W and/or w option in the Dial() or Queue() app call!</span><br><span> ;atxfer => *2 ; Attended transfer -- Make sure to set the T and/or t option in the Dial() or Queue() app call!</span><br><span> ;parkcall => #72 ; Park call (one step parking) -- Make sure to set the K and/or k option in the Dial() app call!</span><br><span> ;automixmon => *3 ; One Touch Record a.k.a. Touch MixMonitor -- Make sure to set the X and/or x option in the Dial() or Queue() app call!</span><br><span>@@ -109,11 +108,6 @@</span><br><span> ; Set arbitrary channel variables, based upon CALLERID number (Note that the application</span><br><span> ; argument contains commas)</span><br><span> ;retrieveinfo => #8,peer,Set(ARRAY(CDR(mark),CDR(name))=${ODBC_FOO(${CALLERID(num)})})</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-;pauseMonitor => #1,self/callee,Pausemonitor ;Allow the callee to pause monitoring</span><br><span style="color: hsl(0, 100%, 40%);">-; ;on their channel</span><br><span style="color: hsl(0, 100%, 40%);">-;unpauseMonitor => #3,self/callee,UnPauseMonitor ;Allow the callee to unpause monitoring</span><br><span style="color: hsl(0, 100%, 40%);">-; ;on their channel</span><br><span> </span><br><span> ; Dynamic Feature Groups:</span><br><span> ; Dynamic feature groups are groupings of features defined in [applicationmap]</span><br><span>@@ -123,5 +117,5 @@</span><br><span> ; example:</span><br><span> ; [myGroupName] ; defines the group named myGroupName</span><br><span> ; testfeature => #9 ; associates testfeature with the group and the keycode '#9'.</span><br><span style="color: hsl(0, 100%, 40%);">-; pauseMonitor => ; associates pauseMonitor with the group and uses the keycode specified</span><br><span style="color: hsl(120, 100%, 40%);">+; retrieveinfo => ; associates retrieveinfo with the group and uses the keycode specified</span><br><span> ; ; in the [applicationmap].</span><br><span>diff --git a/configs/samples/queues.conf.sample b/configs/samples/queues.conf.sample</span><br><span>index ab13084..3b2c18b 100644</span><br><span>--- a/configs/samples/queues.conf.sample</span><br><span>+++ b/configs/samples/queues.conf.sample</span><br><span>@@ -28,16 +28,9 @@</span><br><span> ;autofill = no</span><br><span> ;</span><br><span> ; Monitor Type</span><br><span style="color: hsl(0, 100%, 40%);">-; By setting monitor-type = MixMonitor, when specifying monitor-format</span><br><span style="color: hsl(0, 100%, 40%);">-; to enable recording of queue member conversations, app_queue will</span><br><span style="color: hsl(0, 100%, 40%);">-; now use the new MixMonitor application instead of Monitor so</span><br><span style="color: hsl(0, 100%, 40%);">-; the concept of "joining/mixing" the in/out files now goes away</span><br><span style="color: hsl(0, 100%, 40%);">-; when this is enabled. You can set the default type for all queues</span><br><span style="color: hsl(0, 100%, 40%);">-; here, and then also change monitor-type for individual queues within</span><br><span style="color: hsl(0, 100%, 40%);">-; queue by using the same configuration parameter within a queue</span><br><span style="color: hsl(0, 100%, 40%);">-; configuration block. If you do not specify or comment out this option,</span><br><span style="color: hsl(0, 100%, 40%);">-; it will default to the old 'Monitor' behavior to keep backward</span><br><span style="color: hsl(0, 100%, 40%);">-; compatibility.</span><br><span style="color: hsl(120, 100%, 40%);">+; monitor-type = MixMonitor is the only currently supported option.</span><br><span style="color: hsl(120, 100%, 40%);">+; As MixMonitor mixes the audio by default, "joining/mixing" the in/out</span><br><span style="color: hsl(120, 100%, 40%);">+; files is not necissary.</span><br><span> ;</span><br><span> monitor-type = MixMonitor</span><br><span> ;</span><br><span>@@ -370,7 +363,7 @@</span><br><span> ; The announcements will be played in the order in which they are defined. After</span><br><span> ; playing the last announcement, the announcements begin again from the beginning.</span><br><span> ;</span><br><span style="color: hsl(0, 100%, 40%);">-; Calls may be recorded using Asterisk's monitor/MixMonitor resource</span><br><span style="color: hsl(120, 100%, 40%);">+; Calls may be recorded using Asterisk's MixMonitor resource.</span><br><span> ; This can be enabled from within the Queue application, starting recording</span><br><span> ; when the call is actually picked up; thus, only successful calls are</span><br><span> ; recorded, and you are not recording while people are listening to MOH.</span><br><span>@@ -387,13 +380,9 @@</span><br><span> ; monitor-format = gsm|wav|wav49</span><br><span> ;</span><br><span> ; Monitor Type</span><br><span style="color: hsl(0, 100%, 40%);">-; By setting monitor-type = MixMonitor, when specifying monitor-format</span><br><span style="color: hsl(0, 100%, 40%);">-; to enable recording of queue member conversations, app_queue will</span><br><span style="color: hsl(0, 100%, 40%);">-; now use the new MixMonitor application instead of Monitor so</span><br><span style="color: hsl(0, 100%, 40%);">-; the concept of "joining/mixing" the in/out files now goes away</span><br><span style="color: hsl(0, 100%, 40%);">-; when this is enabled. If you do not specify or comment out this option,</span><br><span style="color: hsl(0, 100%, 40%);">-; it will default to the old 'Monitor' behavior to keep backward</span><br><span style="color: hsl(0, 100%, 40%);">-; compatibility.</span><br><span style="color: hsl(120, 100%, 40%);">+; monitor-type = MixMonitor is the only currently supported option.</span><br><span style="color: hsl(120, 100%, 40%);">+; As MixMonitor mixes the audio by default, "joining/mixing" the in/out</span><br><span style="color: hsl(120, 100%, 40%);">+; files is not necissary.</span><br><span> ;</span><br><span> ; monitor-type = MixMonitor</span><br><span> ;</span><br><span>@@ -408,21 +397,15 @@</span><br><span> ; You can specify a post recording command to be executed after the end of</span><br><span> ; recording by calling (from the dialplan)</span><br><span> ;</span><br><span style="color: hsl(0, 100%, 40%);">-; Set(MONITOR_EXEC=mv /var/spool/asterisk/monitor/^{MONITOR_FILENAME} /tmp/^{MONITOR_FILENAME})</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span style="color: hsl(0, 100%, 40%);">-; or</span><br><span style="color: hsl(0, 100%, 40%);">-;</span><br><span> ; Set(MONITOR_EXEC=mv /var/spool/asterisk/monitor/^{MIXMONITOR_FILENAME} /tmp/^{MIXMONITOR_FILENAME})</span><br><span> ;</span><br><span style="color: hsl(0, 100%, 40%);">-; If you choose to use the latter, you will not be able to switch the monitor-type back to Monitor</span><br><span style="color: hsl(0, 100%, 40%);">-; without changing this in the dialplan.</span><br><span> ;</span><br><span> ;</span><br><span> ; The command specified within the contents of MONITOR_EXEC will be executed when</span><br><span> ; the recording is over. Any strings matching ^{X} will be unescaped to ${X} and</span><br><span> ; all variables will be evaluated just prior to recording being started.</span><br><span> ;</span><br><span style="color: hsl(0, 100%, 40%);">-; The contents of MONITOR_FILENAME will also be unescaped from ^{X} to ${X} and</span><br><span style="color: hsl(120, 100%, 40%);">+; The contents of MIXMONITOR_FILENAME will also be unescaped from ^{X} to ${X} and</span><br><span> ; all variables will be evaluated just prior to recording being started.</span><br><span> ;</span><br><span> ; ---------------------- Queue Empty Options ----------------------------------</span><br><span>diff --git a/configs/samples/stasis.conf.sample b/configs/samples/stasis.conf.sample</span><br><span>index b62d1c6..508f7de 100644</span><br><span>--- a/configs/samples/stasis.conf.sample</span><br><span>+++ b/configs/samples/stasis.conf.sample</span><br><span>@@ -63,8 +63,6 @@</span><br><span> ; decline=ast_channel_hangup_handler_type</span><br><span> ; decline=ast_channel_moh_start_type</span><br><span> ; decline=ast_channel_moh_stop_type</span><br><span style="color: hsl(0, 100%, 40%);">-; decline=ast_channel_monitor_start_type</span><br><span style="color: hsl(0, 100%, 40%);">-; decline=ast_channel_monitor_stop_type</span><br><span> ; decline=ast_channel_mixmonitor_start_type</span><br><span> ; decline=ast_channel_mixmonitor_stop_type</span><br><span> ; decline=ast_channel_agent_login_type</span><br><span>diff --git a/doc/UPGRADE-staging/res_monitor_removal.txt b/doc/UPGRADE-staging/res_monitor_removal.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..b5c7eee</span><br><span>--- /dev/null</span><br><span>+++ b/doc/UPGRADE-staging/res_monitor_removal.txt</span><br><span>@@ -0,0 +1,13 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_monitor</span><br><span style="color: hsl(120, 100%, 40%);">+Master-Only: True</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This module was deprecated in Asterisk 16</span><br><span style="color: hsl(120, 100%, 40%);">+and is now being removed in accordance with</span><br><span style="color: hsl(120, 100%, 40%);">+the Asterisk Module Deprecation policy.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This also removes the 'w' and 'W' options</span><br><span style="color: hsl(120, 100%, 40%);">+for app_queue.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+MixMonitor should be default and only option</span><br><span style="color: hsl(120, 100%, 40%);">+for all settings that previously used either</span><br><span style="color: hsl(120, 100%, 40%);">+Monitor or MixMonitor.</span><br><span>diff --git a/include/asterisk/bridge_features.h b/include/asterisk/bridge_features.h</span><br><span>index 39fb80f..385a2b4 100644</span><br><span>--- a/include/asterisk/bridge_features.h</span><br><span>+++ b/include/asterisk/bridge_features.h</span><br><span>@@ -91,12 +91,6 @@</span><br><span> */</span><br><span> AST_BRIDGE_BUILTIN_PARKCALL,</span><br><span> /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * DTMF one-touch-record toggle using Monitor app.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \note Only valid on two party bridges.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- AST_BRIDGE_BUILTIN_AUTOMON,</span><br><span style="color: hsl(0, 100%, 40%);">- /*!</span><br><span> * DTMF one-touch-record toggle using MixMonitor app.</span><br><span> *</span><br><span> * \note Only valid on two party bridges.</span><br><span>@@ -305,19 +299,14 @@</span><br><span> };</span><br><span> </span><br><span> enum ast_bridge_features_monitor {</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Toggle start/stop of Monitor/MixMonitor. */</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Toggle start/stop of MixMonitor. */</span><br><span> AUTO_MONITOR_TOGGLE,</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Start Monitor/MixMonitor if not already started. */</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Start MixMonitor if not already started. */</span><br><span> AUTO_MONITOR_START,</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Stop Monitor/MixMonitor if not already stopped. */</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Stop MixMonitor if not already stopped. */</span><br><span> AUTO_MONITOR_STOP,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_bridge_features_automonitor {</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Start/Stop behavior. */</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_bridge_features_monitor start_stop;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> struct ast_bridge_features_automixmonitor {</span><br><span> /*! Start/Stop behavior. */</span><br><span> enum ast_bridge_features_monitor start_stop;</span><br><span>diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h</span><br><span>index 50f8e3a..2b67bc6 100644</span><br><span>--- a/include/asterisk/channel.h</span><br><span>+++ b/include/asterisk/channel.h</span><br><span>@@ -4033,21 +4033,6 @@</span><br><span> AST_MONITOR_PAUSED</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/*! Responsible for channel monitoring data */</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_channel_monitor {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_filestream *read_stream;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_filestream *write_stream;</span><br><span style="color: hsl(0, 100%, 40%);">- char read_filename[FILENAME_MAX];</span><br><span style="color: hsl(0, 100%, 40%);">- char write_filename[FILENAME_MAX];</span><br><span style="color: hsl(0, 100%, 40%);">- char filename_base[FILENAME_MAX];</span><br><span style="color: hsl(0, 100%, 40%);">- char beep_id[64];</span><br><span style="color: hsl(0, 100%, 40%);">- int filename_changed;</span><br><span style="color: hsl(0, 100%, 40%);">- char *format;</span><br><span style="color: hsl(0, 100%, 40%);">- int joinfiles;</span><br><span style="color: hsl(0, 100%, 40%);">- enum AST_MONITORING_STATE state;</span><br><span style="color: hsl(0, 100%, 40%);">- int (*stop)(struct ast_channel *chan, int need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* ACCESSOR FUNCTIONS */</span><br><span> </span><br><span> #define DECLARE_STRINGFIELD_SETTERS_FOR(field) \</span><br><span>@@ -4168,8 +4153,6 @@</span><br><span> void ast_channel_masq_set(struct ast_channel *chan, struct ast_channel *value);</span><br><span> struct ast_channel *ast_channel_masqr(const struct ast_channel *chan);</span><br><span> void ast_channel_masqr_set(struct ast_channel *chan, struct ast_channel *value);</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_channel_monitor *ast_channel_monitor(const struct ast_channel *chan);</span><br><span style="color: hsl(0, 100%, 40%);">-void ast_channel_monitor_set(struct ast_channel *chan, struct ast_channel_monitor *value);</span><br><span> struct ast_filestream *ast_channel_stream(const struct ast_channel *chan);</span><br><span> void ast_channel_stream_set(struct ast_channel *chan, struct ast_filestream *value);</span><br><span> struct ast_filestream *ast_channel_vstream(const struct ast_channel *chan);</span><br><span>diff --git a/include/asterisk/doxygen/architecture.h b/include/asterisk/doxygen/architecture.h</span><br><span>index 302edd8..5c01ae1 100644</span><br><span>--- a/include/asterisk/doxygen/architecture.h</span><br><span>+++ b/include/asterisk/doxygen/architecture.h</span><br><span>@@ -185,7 +185,6 @@</span><br><span> - res_crypto.c</span><br><span> - res_curl.c</span><br><span> - res_xmpp.c</span><br><span style="color: hsl(0, 100%, 40%);">- - res_monitor.c</span><br><span> - res_smdi.c</span><br><span> - res_speech.c</span><br><span> - provides a speech recognition engine interface.</span><br><span>diff --git a/include/asterisk/features_config.h b/include/asterisk/features_config.h</span><br><span>index 336454b..0aa0318 100644</span><br><span>--- a/include/asterisk/features_config.h</span><br><span>+++ b/include/asterisk/features_config.h</span><br><span>@@ -28,9 +28,9 @@</span><br><span> */</span><br><span> struct ast_features_general_config {</span><br><span> AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Sound played when automon or automixmon features are used */</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Sound played when automixmon features are used */</span><br><span> AST_STRING_FIELD(courtesytone);</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Sound played when automon or automixmon features fail when used */</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! Sound played when automixmon features fail when used */</span><br><span> AST_STRING_FIELD(recordingfailsound);</span><br><span> );</span><br><span> /*! Milliseconds allowed between digit presses when entering feature code */</span><br><span>@@ -170,8 +170,6 @@</span><br><span> AST_STRING_FIELD(blindxfer);</span><br><span> /*! Disconnect DTMF code */</span><br><span> AST_STRING_FIELD(disconnect);</span><br><span style="color: hsl(0, 100%, 40%);">- /*! Automon DTMF code */</span><br><span style="color: hsl(0, 100%, 40%);">- AST_STRING_FIELD(automon);</span><br><span> /*! Attended Transfer DTMF code */</span><br><span> AST_STRING_FIELD(atxfer);</span><br><span> /*! One-touch parking DTMF code */</span><br><span>diff --git a/include/asterisk/monitor.h b/include/asterisk/monitor.h</span><br><span>deleted file mode 100644</span><br><span>index 377cb62..0000000</span><br><span>--- a/include/asterisk/monitor.h</span><br><span>+++ /dev/null</span><br><span>@@ -1,66 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright (C) 1999 - 2005, Digium, Inc.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Mark Spencer <markster@digium.com></span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(0, 100%, 40%);">- * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(0, 100%, 40%);">- * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(0, 100%, 40%);">- * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(0, 100%, 40%);">- * channels for your use.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is free software, distributed under the terms of</span><br><span style="color: hsl(0, 100%, 40%);">- * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(0, 100%, 40%);">- * at the top of the source tree.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \file</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Channel monitoring</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#ifndef _ASTERISK_MONITOR_H</span><br><span style="color: hsl(0, 100%, 40%);">-#define _ASTERISK_MONITOR_H</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/channel.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/optional_api.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Streams recording control */</span><br><span style="color: hsl(0, 100%, 40%);">-#define X_REC_IN 1</span><br><span style="color: hsl(0, 100%, 40%);">-#define X_REC_OUT 2</span><br><span style="color: hsl(0, 100%, 40%);">-#define X_JOIN 4</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Start monitoring a channel */</span><br><span style="color: hsl(0, 100%, 40%);">-AST_OPTIONAL_API(int, ast_monitor_start,</span><br><span style="color: hsl(0, 100%, 40%);">- (struct ast_channel *chan, const char *format_spec,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *fname_base, int need_lock, int stream_action,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *beep_id),</span><br><span style="color: hsl(0, 100%, 40%);">- { return -1; });</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Stop monitoring a channel */</span><br><span style="color: hsl(0, 100%, 40%);">-AST_OPTIONAL_API(int, ast_monitor_stop,</span><br><span style="color: hsl(0, 100%, 40%);">- (struct ast_channel *chan, int need_lock),</span><br><span style="color: hsl(0, 100%, 40%);">- { return -1; });</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Change monitoring filename of a channel */</span><br><span style="color: hsl(0, 100%, 40%);">-AST_OPTIONAL_API(int, ast_monitor_change_fname,</span><br><span style="color: hsl(0, 100%, 40%);">- (struct ast_channel *chan, const char *fname_base,</span><br><span style="color: hsl(0, 100%, 40%);">- int need_lock),</span><br><span style="color: hsl(0, 100%, 40%);">- { return -1; });</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-AST_OPTIONAL_API(void, ast_monitor_setjoinfiles,</span><br><span style="color: hsl(0, 100%, 40%);">- (struct ast_channel *chan, int turnon),</span><br><span style="color: hsl(0, 100%, 40%);">- { return; });</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Pause monitoring of a channel */</span><br><span style="color: hsl(0, 100%, 40%);">-AST_OPTIONAL_API(int, ast_monitor_pause,</span><br><span style="color: hsl(0, 100%, 40%);">- (struct ast_channel *chan),</span><br><span style="color: hsl(0, 100%, 40%);">- { return -1; });</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Unpause monitoring of a channel */</span><br><span style="color: hsl(0, 100%, 40%);">-AST_OPTIONAL_API(int, ast_monitor_unpause,</span><br><span style="color: hsl(0, 100%, 40%);">- (struct ast_channel *chan),</span><br><span style="color: hsl(0, 100%, 40%);">- { return -1; });</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#endif /* _ASTERISK_MONITOR_H */</span><br><span>diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h</span><br><span>index d9ae9e8..728e0ff 100644</span><br><span>--- a/include/asterisk/stasis_channels.h</span><br><span>+++ b/include/asterisk/stasis_channels.h</span><br><span>@@ -585,22 +585,6 @@</span><br><span> struct stasis_message_type *ast_channel_hangup_handler_type(void);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Message type for starting monitor on a channel</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \return A stasis message type</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_message_type *ast_channel_monitor_start_type(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Message type for stopping monitor on a channel</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \return A stasis message type</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-struct stasis_message_type *ast_channel_monitor_stop_type(void);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span> * \since 18</span><br><span> * \brief Message type for starting mixmonitor on a channel</span><br><span> *</span><br><span>diff --git a/main/asterisk.dynamics b/main/asterisk.dynamics</span><br><span>index a134e2a..cfbff72 100644</span><br><span>--- a/main/asterisk.dynamics</span><br><span>+++ b/main/asterisk.dynamics</span><br><span>@@ -3,7 +3,6 @@</span><br><span> *ast_agi_*;</span><br><span> *ast_beep_*;</span><br><span> *ast_smdi_*;</span><br><span style="color: hsl(0, 100%, 40%);">- *ast_monitor_*;</span><br><span> *ast_key_get;</span><br><span> *ast_check_signature;</span><br><span> *ast_check_signature_bin;</span><br><span>diff --git a/main/bridge_basic.c b/main/bridge_basic.c</span><br><span>index 9f83f7d..115f6a3 100644</span><br><span>--- a/main/bridge_basic.c</span><br><span>+++ b/main/bridge_basic.c</span><br><span>@@ -414,7 +414,6 @@</span><br><span> res |= builtin_features_helper(features, chan, flags, AST_FEATURE_REDIRECT, "atxfer", AST_BRIDGE_BUILTIN_ATTENDEDTRANSFER);</span><br><span> res |= builtin_features_helper(features, chan, flags, AST_FEATURE_DISCONNECT, "disconnect", AST_BRIDGE_BUILTIN_HANGUP);</span><br><span> res |= builtin_features_helper(features, chan, flags, AST_FEATURE_PARKCALL, "parkcall", AST_BRIDGE_BUILTIN_PARKCALL);</span><br><span style="color: hsl(0, 100%, 40%);">- res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMON, "automon", AST_BRIDGE_BUILTIN_AUTOMON);</span><br><span> res |= builtin_features_helper(features, chan, flags, AST_FEATURE_AUTOMIXMON, "automixmon", AST_BRIDGE_BUILTIN_AUTOMIXMON);</span><br><span> </span><br><span> return res ? -1 : 0;</span><br><span>diff --git a/main/bridge_channel.c b/main/bridge_channel.c</span><br><span>index 7f00050..4aebb01 100644</span><br><span>--- a/main/bridge_channel.c</span><br><span>+++ b/main/bridge_channel.c</span><br><span>@@ -1626,8 +1626,6 @@</span><br><span> feature = "atxfer";</span><br><span> } else if (!strcmp(dtmf, featuremap->disconnect)) {</span><br><span> feature = "disconnect";</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!strcmp(dtmf, featuremap->automon)) {</span><br><span style="color: hsl(0, 100%, 40%);">- feature = "automon";</span><br><span> } else if (!strcmp(dtmf, featuremap->automixmon)) {</span><br><span> feature = "automixmon";</span><br><span> } else if (!strcmp(dtmf, featuremap->parkcall)) {</span><br><span>diff --git a/main/channel.c b/main/channel.c</span><br><span>index 7c2acd7..844cea8 100644</span><br><span>--- a/main/channel.c</span><br><span>+++ b/main/channel.c</span><br><span>@@ -2195,11 +2195,6 @@</span><br><span> </span><br><span> ast_debug(1, "Channel %p '%s' destroying\n", chan, ast_channel_name(chan));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Stop monitoring */</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor(chan)->stop(chan, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* If there is native format music-on-hold state, free it */</span><br><span> if (ast_channel_music_state(chan)) {</span><br><span> ast_moh_cleanup(chan);</span><br><span>@@ -2516,15 +2511,13 @@</span><br><span> </span><br><span> int ast_channel_has_audio_frame_or_monitor(struct ast_channel *chan)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_channel_monitor(chan)</span><br><span style="color: hsl(0, 100%, 40%);">- || !ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))</span><br><span style="color: hsl(120, 100%, 40%);">+ return !ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))</span><br><span> || !ast_framehook_list_contains_no_active(ast_channel_framehooks(chan));</span><br><span> }</span><br><span> </span><br><span> int ast_channel_has_hook_requiring_audio(struct ast_channel *chan)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_channel_monitor(chan)</span><br><span style="color: hsl(0, 100%, 40%);">- || !ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))</span><br><span style="color: hsl(120, 100%, 40%);">+ return !ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))</span><br><span> || !ast_framehook_list_contains_no_active_of_type(ast_channel_framehooks(chan), AST_FRAME_VOICE);</span><br><span> }</span><br><span> </span><br><span>@@ -4164,40 +4157,6 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan) && ast_channel_monitor(chan)->read_stream) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* XXX what does this do ? */</span><br><span style="color: hsl(0, 100%, 40%);">-#ifndef MONITOR_CONSTANT_DELAY</span><br><span style="color: hsl(0, 100%, 40%);">- int jump = ast_channel_outsmpl(chan) - ast_channel_insmpl(chan) - 4 * f->samples;</span><br><span style="color: hsl(0, 100%, 40%);">- if (jump >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(f->subclass.format),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump, SEEK_FORCECUR) == -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + (ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)) + f->samples);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + f->samples);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">- int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(f->subclass.format),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));</span><br><span style="color: hsl(0, 100%, 40%);">- if (jump - MONITOR_DELAY >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_insmpl(chan) += ast_channel_outsmpl(chan) - ast_channel_insmpl(chan);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_insmpl(chan) += f->samples;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)->state == AST_MONITOR_RUNNING) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_writestream(ast_channel_monitor(chan)->read_stream, f) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> if (ast_channel_readtrans(chan)</span><br><span> && ast_format_cmp(f->subclass.format, ast_channel_rawreadformat(chan)) == AST_FORMAT_CMP_EQUAL) {</span><br><span> f = ast_translate(ast_channel_readtrans(chan), f, 1);</span><br><span>@@ -5440,48 +5399,6 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* If Monitor is running on this channel, then we have to write frames out there too */</span><br><span style="color: hsl(0, 100%, 40%);">- /* the translator on chan->writetrans may have returned multiple frames</span><br><span style="color: hsl(0, 100%, 40%);">- from the single frame we passed in; if so, feed each one of them to the</span><br><span style="color: hsl(0, 100%, 40%);">- monitor */</span><br><span style="color: hsl(0, 100%, 40%);">- if ((stream == default_stream) && ast_channel_monitor(chan) && ast_channel_monitor(chan)->write_stream) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_frame *cur;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- for (cur = f; cur; cur = AST_LIST_NEXT(cur, frame_list)) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* XXX must explain this code */</span><br><span style="color: hsl(0, 100%, 40%);">-#ifndef MONITOR_CONSTANT_DELAY</span><br><span style="color: hsl(0, 100%, 40%);">- int jump = ast_channel_insmpl(chan) - ast_channel_outsmpl(chan) - 4 * cur->samples;</span><br><span style="color: hsl(0, 100%, 40%);">- if (jump >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(f->subclass.format),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(ast_channel_monitor(chan)->write_stream->fmt->format));</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_seekstream(ast_channel_monitor(chan)->write_stream, jump, SEEK_FORCECUR) == -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_outsmpl_set(chan, ast_channel_outsmpl(chan) + (ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)) + cur->samples);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_outsmpl_set(chan, ast_channel_outsmpl(chan) + cur->samples);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">- int jump = calc_monitor_jump((ast_channel_insmpl(chan) - ast_channel_outsmpl(chan)),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(f->subclass.format),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_format_get_sample_rate(ast_channel_monitor(chan)->write_stream->fmt->format));</span><br><span style="color: hsl(0, 100%, 40%);">- if (jump - MONITOR_DELAY >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_seekstream(ast_channel_monitor(chan)->write_stream, jump - cur->samples, SEEK_FORCECUR) == -1) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Failed to perform seek in monitoring write stream, synchronization between the files may be broken\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_outsmpl_set(chan, ast_channel_outsmpl(chan) + ast_channel_insmpl(chan) - ast_channel_outsmpl(chan));</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_outsmpl_set(chan, ast_channel_outsmpl(chan) + cur->samples);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)->state == AST_MONITOR_RUNNING) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_writestream(ast_channel_monitor(chan)->write_stream, cur) < 0)</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Failed to write data to channel monitor write stream\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* the translator on chan->writetrans may have returned multiple frames</span><br><span> from the single frame we passed in; if so, feed each one of them to the</span><br><span> channel, freeing each one after it has been written */</span><br><span>@@ -7130,11 +7047,6 @@</span><br><span> }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Update the type. */</span><br><span style="color: hsl(0, 100%, 40%);">- t_pvt = ast_channel_monitor(original);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_set(original, ast_channel_monitor(clonechan));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_set(clonechan, t_pvt);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* Keep the same language. */</span><br><span> ast_channel_language_set(original, ast_channel_language(clonechan));</span><br><span> </span><br><span>diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c</span><br><span>index 2a33001..8776696 100644</span><br><span>--- a/main/channel_internal_api.c</span><br><span>+++ b/main/channel_internal_api.c</span><br><span>@@ -94,7 +94,6 @@</span><br><span> struct ast_cdr *cdr; /*!< Call Detail Record */</span><br><span> struct ast_tone_zone *zone; /*!< Tone zone as set in indications.conf or</span><br><span> * in the CHANNEL dialplan function */</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel_monitor *monitor; /*!< Channel monitoring */</span><br><span> ast_callid callid; /*!< Bound call identifier pointer */</span><br><span> struct ao2_container *dialed_causes; /*!< Contains tech-specific and Asterisk cause data from dialed channels */</span><br><span> </span><br><span>@@ -604,14 +603,6 @@</span><br><span> {</span><br><span> chan->masqr = value;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_channel_monitor *ast_channel_monitor(const struct ast_channel *chan)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return chan->monitor;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-void ast_channel_monitor_set(struct ast_channel *chan, struct ast_channel_monitor *value)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- chan->monitor = value;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span> struct ast_filestream *ast_channel_stream(const struct ast_channel *chan)</span><br><span> {</span><br><span> return chan->stream;</span><br><span>diff --git a/main/features.c b/main/features.c</span><br><span>index edde702..466f602 100644</span><br><span>--- a/main/features.c</span><br><span>+++ b/main/features.c</span><br><span>@@ -480,41 +480,6 @@</span><br><span> </span><br><span> /*!</span><br><span> * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Check if Monitor needs to be started on a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- * \since 12.0.0</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param chan The bridge considers this channel the caller.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param peer The bridge considers this channel the callee.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static void bridge_check_monitor(struct ast_channel *chan, struct ast_channel *peer)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- const char *value;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *monitor_args = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *monitor_chan = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(chan);</span><br><span style="color: hsl(0, 100%, 40%);">- value = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(value)) {</span><br><span style="color: hsl(0, 100%, 40%);">- monitor_args = ast_strdupa(value);</span><br><span style="color: hsl(0, 100%, 40%);">- monitor_chan = chan;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(chan);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!monitor_chan) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(peer);</span><br><span style="color: hsl(0, 100%, 40%);">- value = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR");</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(value)) {</span><br><span style="color: hsl(0, 100%, 40%);">- monitor_args = ast_strdupa(value);</span><br><span style="color: hsl(0, 100%, 40%);">- monitor_chan = peer;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(peer);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (monitor_chan) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_pbx_exec_application(monitor_chan, "Monitor", monitor_args);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span> * \brief Send the peer channel on its way on bridge start failure.</span><br><span> * \since 12.0.0</span><br><span> *</span><br><span>@@ -550,8 +515,6 @@</span><br><span> ast_indicate(peer, AST_CONTROL_RINGING);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- bridge_check_monitor(chan, peer);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> set_config_flags(chan, config);</span><br><span> </span><br><span> /* Answer if need be */</span><br><span>diff --git a/main/features_config.c b/main/features_config.c</span><br><span>index ba2f905..2144999 100644</span><br><span>--- a/main/features_config.c</span><br><span>+++ b/main/features_config.c</span><br><span>@@ -39,10 +39,10 @@</span><br><span> <synopsis>Milliseconds allowed between digit presses when entering a feature code.</synopsis></span><br><span> </configOption></span><br><span> <configOption name="courtesytone"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>Sound to play when automon or automixmon is activated</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Sound to play when automixmon is activated</synopsis></span><br><span> </configOption></span><br><span> <configOption name="recordingfailsound"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>Sound to play when automon or automixmon is attempted but fails to start</synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis>Sound to play when automixmon is attempted but fails to start</synopsis></span><br><span> </configOption></span><br><span> <configOption name="transferdigittimeout" default="3"></span><br><span> <synopsis>Seconds allowed between digit presses when dialing a transfer destination</synopsis></span><br><span>@@ -186,22 +186,6 @@</span><br><span> is used. The call is parked in the next available space in the parking lot.</para></span><br><span> </description></span><br><span> </configOption></span><br><span style="color: hsl(0, 100%, 40%);">- <configOption name="automon"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>DTMF sequence to start or stop Monitor on a call</synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This will cause the channel that pressed the DTMF sequence</span><br><span style="color: hsl(0, 100%, 40%);">- to be monitored by the <literal>Monitor</literal> application. The</span><br><span style="color: hsl(0, 100%, 40%);">- format for the recording is determined by the <replaceable>TOUCH_MONITOR_FORMAT</replaceable></span><br><span style="color: hsl(0, 100%, 40%);">- channel variable. If this variable is not specified, then <literal>wav</literal> is the</span><br><span style="color: hsl(0, 100%, 40%);">- default. The filename is constructed in the following manner:</para></span><br><span style="color: hsl(0, 100%, 40%);">- <para> prefix-timestamp-suffix.fmt</para></span><br><span style="color: hsl(0, 100%, 40%);">- <para>where prefix is either the value of the <replaceable>TOUCH_MONITOR_PREFIX</replaceable></span><br><span style="color: hsl(0, 100%, 40%);">- channel variable or <literal>auto</literal> if the variable is not set. The timestamp</span><br><span style="color: hsl(0, 100%, 40%);">- is a UNIX timestamp. The suffix is either the value of the <replaceable>TOUCH_MONITOR</replaceable></span><br><span style="color: hsl(0, 100%, 40%);">- channel variable or the callerID of the channels if the variable is not set.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also><ref type="configOption">automixmon</ref></see-also></span><br><span style="color: hsl(0, 100%, 40%);">- </configOption></span><br><span> <configOption name="automixmon"></span><br><span> <synopsis>DTMF sequence to start or stop MixMonitor on a call</synopsis></span><br><span> <description></span><br><span>@@ -216,7 +200,6 @@</span><br><span> is a UNIX timestamp. The suffix is either the value of the <replaceable>TOUCH_MIXMONITOR</replaceable></span><br><span> channel variable or the callerID of the channels if the variable is not set.</para></span><br><span> </description></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also><ref type="configOption">automon</ref></see-also></span><br><span> </configOption></span><br><span> </configObject></span><br><span> <configObject name="applicationmap"></span><br><span>@@ -352,7 +335,6 @@</span><br><span> <enumlist></span><br><span> <enum name="atxfer"><para>Attended Transfer</para></enum></span><br><span> <enum name="blindxfer"><para>Blind Transfer</para></enum></span><br><span style="color: hsl(0, 100%, 40%);">- <enum name="automon"><para>Auto Monitor</para></enum></span><br><span> <enum name="disconnect"><para>Call Disconnect</para></enum></span><br><span> <enum name="parkcall"><para>Park Call</para></enum></span><br><span> <enum name="automixmon"><para>Auto MixMonitor</para></enum></span><br><span>@@ -1013,8 +995,6 @@</span><br><span> ast_string_field_set(featuremap, blindxfer, value);</span><br><span> } else if (!strcasecmp(name, "disconnect")) {</span><br><span> ast_string_field_set(featuremap, disconnect, value);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!strcasecmp(name, "automon")) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(featuremap, automon, value);</span><br><span> } else if (!strcasecmp(name, "atxfer")) {</span><br><span> ast_string_field_set(featuremap, atxfer, value);</span><br><span> } else if (!strcasecmp(name, "automixmon")) {</span><br><span>@@ -1038,8 +1018,6 @@</span><br><span> ast_copy_string(buf, featuremap->blindxfer, len);</span><br><span> } else if (!strcasecmp(field, "disconnect")) {</span><br><span> ast_copy_string(buf, featuremap->disconnect, len);</span><br><span style="color: hsl(0, 100%, 40%);">- } else if (!strcasecmp(field, "automon")) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(buf, featuremap->automon, len);</span><br><span> } else if (!strcasecmp(field, "atxfer")) {</span><br><span> ast_copy_string(buf, featuremap->atxfer, len);</span><br><span> } else if (!strcasecmp(field, "automixmon")) {</span><br><span>@@ -1857,8 +1835,6 @@</span><br><span> DEFAULT_FEATUREMAP_BLINDXFER, featuremap_handler, 0);</span><br><span> aco_option_register_custom(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,</span><br><span> DEFAULT_FEATUREMAP_DISCONNECT, featuremap_handler, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- aco_option_register_custom(&cfg_info, "automon", ACO_EXACT, featuremap_options,</span><br><span style="color: hsl(0, 100%, 40%);">- DEFAULT_FEATUREMAP_AUTOMON, featuremap_handler, 0);</span><br><span> aco_option_register_custom(&cfg_info, "atxfer", ACO_EXACT, featuremap_options,</span><br><span> DEFAULT_FEATUREMAP_ATXFER, featuremap_handler, 0);</span><br><span> aco_option_register_custom(&cfg_info, "parkcall", ACO_EXACT, featuremap_options,</span><br><span>@@ -1957,7 +1933,6 @@</span><br><span> ast_cli(a->fd, HFS_FORMAT, "Pickup", DEFAULT_PICKUPEXTEN, cfg->global->pickup->pickupexten);</span><br><span> ast_cli(a->fd, HFS_FORMAT, "Blind Transfer", DEFAULT_FEATUREMAP_BLINDXFER, cfg->featuremap->blindxfer);</span><br><span> ast_cli(a->fd, HFS_FORMAT, "Attended Transfer", DEFAULT_FEATUREMAP_ATXFER, cfg->featuremap->atxfer);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cli(a->fd, HFS_FORMAT, "One Touch Monitor", DEFAULT_FEATUREMAP_AUTOMON, cfg->featuremap->automon);</span><br><span> ast_cli(a->fd, HFS_FORMAT, "Disconnect Call", DEFAULT_FEATUREMAP_DISCONNECT, cfg->featuremap->disconnect);</span><br><span> ast_cli(a->fd, HFS_FORMAT, "Park Call", DEFAULT_FEATUREMAP_PARKCALL, cfg->featuremap->parkcall);</span><br><span> ast_cli(a->fd, HFS_FORMAT, "One Touch MixMonitor", DEFAULT_FEATUREMAP_AUTOMIXMON, cfg->featuremap->automixmon);</span><br><span>diff --git a/main/manager_channels.c b/main/manager_channels.c</span><br><span>index 8af3465..9aa980d 100644</span><br><span>--- a/main/manager_channels.c</span><br><span>+++ b/main/manager_channels.c</span><br><span>@@ -451,32 +451,6 @@</span><br><span> </see-also></span><br><span> </managerEventInstance></span><br><span> </managerEvent></span><br><span style="color: hsl(0, 100%, 40%);">- <managerEvent language="en_US" name="MonitorStart"></span><br><span style="color: hsl(0, 100%, 40%);">- <managerEventInstance class="EVENT_FLAG_CALL"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>Raised when monitoring has started on a channel.</synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <channel_snapshot/></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="managerEvent">MonitorStop</ref></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">Monitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="manager">Monitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- </see-also></span><br><span style="color: hsl(0, 100%, 40%);">- </managerEventInstance></span><br><span style="color: hsl(0, 100%, 40%);">- </managerEvent></span><br><span style="color: hsl(0, 100%, 40%);">- <managerEvent language="en_US" name="MonitorStop"></span><br><span style="color: hsl(0, 100%, 40%);">- <managerEventInstance class="EVENT_FLAG_CALL"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis>Raised when monitoring has stopped on a channel.</synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <channel_snapshot/></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="managerEvent">MonitorStart</ref></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">StopMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="manager">StopMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- </see-also></span><br><span style="color: hsl(0, 100%, 40%);">- </managerEventInstance></span><br><span style="color: hsl(0, 100%, 40%);">- </managerEvent></span><br><span> ***/</span><br><span> </span><br><span> /*! \brief The \ref stasis subscription returned by the forwarding of the channel topic</span><br><span>@@ -1160,22 +1134,6 @@</span><br><span> publish_basic_channel_event("MusicOnHoldStop", EVENT_FLAG_CALL, payload->snapshot);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void channel_monitor_start_cb(void *data, struct stasis_subscription *sub,</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_message *message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel_blob *payload = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- publish_basic_channel_event("MonitorStart", EVENT_FLAG_CALL, payload->snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static void channel_monitor_stop_cb(void *data, struct stasis_subscription *sub,</span><br><span style="color: hsl(0, 100%, 40%);">- struct stasis_message *message)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel_blob *payload = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- publish_basic_channel_event("MonitorStop", EVENT_FLAG_CALL, payload->snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> static void channel_mixmonitor_start_cb(void *data, struct stasis_subscription *sub,</span><br><span> struct stasis_message *message)</span><br><span> {</span><br><span>@@ -1427,13 +1385,6 @@</span><br><span> ast_channel_moh_stop_type(), channel_moh_stop_cb, NULL);</span><br><span> </span><br><span> ret |= stasis_message_router_add(message_router,</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_start_type(), channel_monitor_start_cb,</span><br><span style="color: hsl(0, 100%, 40%);">- NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret |= stasis_message_router_add(message_router,</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_stop_type(), channel_monitor_stop_cb, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret |= stasis_message_router_add(message_router,</span><br><span> ast_channel_mixmonitor_start_type(), channel_mixmonitor_start_cb, NULL);</span><br><span> </span><br><span> ret |= stasis_message_router_add(message_router,</span><br><span>diff --git a/main/stasis.c b/main/stasis.c</span><br><span>index a7cc7e2..0715e4a 100644</span><br><span>--- a/main/stasis.c</span><br><span>+++ b/main/stasis.c</span><br><span>@@ -130,8 +130,6 @@</span><br><span> <enum name="ast_channel_hangup_handler_type" /></span><br><span> <enum name="ast_channel_moh_start_type" /></span><br><span> <enum name="ast_channel_moh_stop_type" /></span><br><span style="color: hsl(0, 100%, 40%);">- <enum name="ast_channel_monitor_start_type" /></span><br><span style="color: hsl(0, 100%, 40%);">- <enum name="ast_channel_monitor_stop_type" /></span><br><span> <enum name="ast_channel_mixmonitor_start_type" /></span><br><span> <enum name="ast_channel_mixmonitor_stop_type" /></span><br><span> <enum name="ast_channel_mixmonitor_mute_type" /></span><br><span>diff --git a/main/stasis_channels.c b/main/stasis_channels.c</span><br><span>index d373f6a..f796c0a 100644</span><br><span>--- a/main/stasis_channels.c</span><br><span>+++ b/main/stasis_channels.c</span><br><span>@@ -1611,8 +1611,6 @@</span><br><span> STASIS_MESSAGE_TYPE_DEFN(ast_channel_hangup_handler_type);</span><br><span> STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_start_type);</span><br><span> STASIS_MESSAGE_TYPE_DEFN(ast_channel_moh_stop_type);</span><br><span style="color: hsl(0, 100%, 40%);">-STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_start_type);</span><br><span style="color: hsl(0, 100%, 40%);">-STASIS_MESSAGE_TYPE_DEFN(ast_channel_monitor_stop_type);</span><br><span> STASIS_MESSAGE_TYPE_DEFN(ast_channel_mixmonitor_start_type);</span><br><span> STASIS_MESSAGE_TYPE_DEFN(ast_channel_mixmonitor_stop_type);</span><br><span> STASIS_MESSAGE_TYPE_DEFN(ast_channel_mixmonitor_mute_type);</span><br><span>@@ -1659,8 +1657,6 @@</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_hangup_handler_type);</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_start_type);</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_moh_stop_type);</span><br><span style="color: hsl(0, 100%, 40%);">- STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_start_type);</span><br><span style="color: hsl(0, 100%, 40%);">- STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_monitor_stop_type);</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_mixmonitor_start_type);</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_mixmonitor_stop_type);</span><br><span> STASIS_MESSAGE_TYPE_CLEANUP(ast_channel_mixmonitor_mute_type);</span><br><span>@@ -1714,8 +1710,6 @@</span><br><span> res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_hangup_handler_type);</span><br><span> res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_start_type);</span><br><span> res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_moh_stop_type);</span><br><span style="color: hsl(0, 100%, 40%);">- res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_start_type);</span><br><span style="color: hsl(0, 100%, 40%);">- res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_monitor_stop_type);</span><br><span> res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_mixmonitor_start_type);</span><br><span> res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_mixmonitor_stop_type);</span><br><span> res |= STASIS_MESSAGE_TYPE_INIT(ast_channel_mixmonitor_mute_type);</span><br><span>diff --git a/menuselect/example_menuselect-tree b/menuselect/example_menuselect-tree</span><br><span>index 93a70f0..9bc389a 100644</span><br><span>--- a/menuselect/example_menuselect-tree</span><br><span>+++ b/menuselect/example_menuselect-tree</span><br><span>@@ -351,8 +351,6 @@</span><br><span> <member name="res_jabber" displayname="AJI - Asterisk JABBER Interface" remove_on_change="res/res_jabber.o res/res_jabber.so"></span><br><span> <depend>iksemel</depend></span><br><span> </member></span><br><span style="color: hsl(0, 100%, 40%);">- <member name="res_monitor" displayname="Call Monitoring Resource" remove_on_change="res/res_monitor.o res/res_monitor.so"></span><br><span style="color: hsl(0, 100%, 40%);">- </member></span><br><span> <member name="res_musiconhold" displayname="Music On Hold Resource" remove_on_change="res/res_musiconhold.o res/res_musiconhold.so"></span><br><span> <conflict>win32</conflict></span><br><span> </member></span><br><span>diff --git a/menuselect/test/menuselect-tree b/menuselect/test/menuselect-tree</span><br><span>index 7bbb73f..690bf66 100644</span><br><span>--- a/menuselect/test/menuselect-tree</span><br><span>+++ b/menuselect/test/menuselect-tree</span><br><span>@@ -97,7 +97,6 @@</span><br><span> <member name="app_privacy" displayname="Require phone number to be entered, if no CallerID sent" remove_on_change="apps/app_privacy.o apps/app_privacy.so"></span><br><span> </member></span><br><span> <member name="app_queue" displayname="True Call Queueing" remove_on_change="apps/app_queue.o apps/app_queue.so"></span><br><span style="color: hsl(0, 100%, 40%);">- <depend>res_monitor</depend></span><br><span> </member></span><br><span> <member name="app_read" displayname="Read Variable Application" remove_on_change="apps/app_read.o apps/app_read.so"></span><br><span> </member></span><br><span>@@ -449,8 +448,6 @@</span><br><span> </member></span><br><span> <member name="res_limit" displayname="Resource limits" remove_on_change="res/res_limit.o res/res_limit.so"></span><br><span> </member></span><br><span style="color: hsl(0, 100%, 40%);">-<member name="res_monitor" displayname="Call Monitoring Resource" remove_on_change="res/res_monitor.o res/res_monitor.so"></span><br><span style="color: hsl(0, 100%, 40%);">-</member></span><br><span> <member name="res_musiconhold" displayname="Music On Hold Resource" remove_on_change="res/res_musiconhold.o res/res_musiconhold.so"></span><br><span> <conflict>win32</conflict></span><br><span> <use>dahdi</use></span><br><span>diff --git a/pbx/Makefile b/pbx/Makefile</span><br><span>index 3ef49d1..9350ece 100644</span><br><span>--- a/pbx/Makefile</span><br><span>+++ b/pbx/Makefile</span><br><span>@@ -20,7 +20,7 @@</span><br><span> include $(ASTTOPDIR)/Makefile.moddir_rules</span><br><span> </span><br><span> ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)</span><br><span style="color: hsl(0, 100%, 40%);">- LIBS+= -lres_ael_share.so -lres_monitor.so</span><br><span style="color: hsl(120, 100%, 40%);">+ LIBS+= -lres_ael_share.so</span><br><span> endif</span><br><span> </span><br><span> $(call MOD_ADD_C,pbx_dundi,dundi-parser.c)</span><br><span>diff --git a/pbx/ael/ael-test/ael-test2/apptest.ael2 b/pbx/ael/ael-test/ael-test2/apptest.ael2</span><br><span>index 9114c5c..9645e76 100644</span><br><span>--- a/pbx/ael/ael-test/ael-test2/apptest.ael2</span><br><span>+++ b/pbx/ael/ael-test/ael-test2/apptest.ael2</span><br><span>@@ -65,7 +65,6 @@</span><br><span> MeetMeCount(5555,var);</span><br><span> Milliwatt();</span><br><span> MixMonitor(filename,abv()V()W(),command);</span><br><span style="color: hsl(0, 100%, 40%);">- Monitor(file.fmt,base,mb);</span><br><span> MP3Player(location);</span><br><span> MusicOnHold(class);</span><br><span> NBScat();</span><br><span>diff --git a/pbx/ael/ael-test/ael-test4/apptest.ael2 b/pbx/ael/ael-test/ael-test4/apptest.ael2</span><br><span>index 9114c5c..9645e76 100644</span><br><span>--- a/pbx/ael/ael-test/ael-test4/apptest.ael2</span><br><span>+++ b/pbx/ael/ael-test/ael-test4/apptest.ael2</span><br><span>@@ -65,7 +65,6 @@</span><br><span> MeetMeCount(5555,var);</span><br><span> Milliwatt();</span><br><span> MixMonitor(filename,abv()V()W(),command);</span><br><span style="color: hsl(0, 100%, 40%);">- Monitor(file.fmt,base,mb);</span><br><span> MP3Player(location);</span><br><span> MusicOnHold(class);</span><br><span> NBScat();</span><br><span>diff --git a/pbx/ael/ael-test/ael-test5/extensions.ael b/pbx/ael/ael-test/ael-test5/extensions.ael</span><br><span>index 6057957..927e2db 100644</span><br><span>--- a/pbx/ael/ael-test/ael-test5/extensions.ael</span><br><span>+++ b/pbx/ael/ael-test/ael-test5/extensions.ael</span><br><span>@@ -425,7 +425,6 @@</span><br><span> app-idblock;</span><br><span> app-helpdesk;</span><br><span> app-dictate;</span><br><span style="color: hsl(0, 100%, 40%);">- app-set-monitor;</span><br><span> };</span><br><span> };</span><br><span> </span><br><span>@@ -485,21 +484,6 @@</span><br><span> };</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-context app-set-monitor {</span><br><span style="color: hsl(0, 100%, 40%);">- *50 => {</span><br><span style="color: hsl(0, 100%, 40%);">- Realtime(call_info,exten,${CALLERIDNUM:5},mon_set_);</span><br><span style="color: hsl(0, 100%, 40%);">- if ("${mon_set_monitor}" = "YES") {</span><br><span style="color: hsl(0, 100%, 40%);">- RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor|);</span><br><span style="color: hsl(0, 100%, 40%);">- System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- RealtimeUpdate(call_info,exten,${CALLERIDNUM:5},monitor,YES);</span><br><span style="color: hsl(0, 100%, 40%);">- System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &);</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">- NoOp(${mon_set_monitor});</span><br><span style="color: hsl(0, 100%, 40%);">- Hangup;</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> context app-dnd {</span><br><span> *78 => {</span><br><span> Answer;</span><br><span>diff --git a/pbx/ael/ael-test/ael-test6/extensions.ael b/pbx/ael/ael-test/ael-test6/extensions.ael</span><br><span>index 7f759f2..797fe33 100644</span><br><span>--- a/pbx/ael/ael-test/ael-test6/extensions.ael</span><br><span>+++ b/pbx/ael/ael-test/ael-test6/extensions.ael</span><br><span>@@ -421,7 +421,6 @@</span><br><span> app-idblock;</span><br><span> app-helpdesk;</span><br><span> app-dictate;</span><br><span style="color: hsl(0, 100%, 40%);">- app-set-monitor;</span><br><span> };</span><br><span> };</span><br><span> </span><br><span>@@ -481,21 +480,6 @@</span><br><span> };</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-context app-set-monitor {</span><br><span style="color: hsl(0, 100%, 40%);">- *50 => {</span><br><span style="color: hsl(0, 100%, 40%);">- Realtime(call_info|exten|${CALLERIDNUM:5}|mon_set_);</span><br><span style="color: hsl(0, 100%, 40%);">- if ("${mon_set_monitor}" = "YES") {</span><br><span style="color: hsl(0, 100%, 40%);">- RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|);</span><br><span style="color: hsl(0, 100%, 40%);">- System(/usr/local/bin/db_update.sh call_info monitor '' exten ${CALLERIDNUM:5} &);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- RealtimeUpdate(call_info|exten|${CALLERIDNUM:5}|monitor|YES);</span><br><span style="color: hsl(0, 100%, 40%);">- System(/usr/local/bin/db_update.sh call_info monitor YES exten ${CALLERIDNUM:5} &);</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">- NoOp(${mon_set_monitor});</span><br><span style="color: hsl(0, 100%, 40%);">- Hangup;</span><br><span style="color: hsl(0, 100%, 40%);">- };</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> context app-dnd {</span><br><span> *78 => {</span><br><span> Answer;</span><br><span>diff --git a/res/res_monitor.c b/res/res_monitor.c</span><br><span>deleted file mode 100644</span><br><span>index 1264ad0..0000000</span><br><span>--- a/res/res_monitor.c</span><br><span>+++ /dev/null</span><br><span>@@ -1,1019 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/*</span><br><span style="color: hsl(0, 100%, 40%);">- * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Copyright (C) 1999 - 2005, Digium, Inc.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Mark Spencer <markster@digium.com></span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(0, 100%, 40%);">- * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(0, 100%, 40%);">- * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(0, 100%, 40%);">- * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(0, 100%, 40%);">- * channels for your use.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * This program is free software, distributed under the terms of</span><br><span style="color: hsl(0, 100%, 40%);">- * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(0, 100%, 40%);">- * at the top of the source tree.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \file</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief PBX channel monitoring</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * \author Mark Spencer <markster@digium.com></span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*** MODULEINFO</span><br><span style="color: hsl(0, 100%, 40%);">- <use type="module">func_periodic_hook</use></span><br><span style="color: hsl(0, 100%, 40%);">- <defaultenabled>no</defaultenabled></span><br><span style="color: hsl(0, 100%, 40%);">- <support_level>deprecated</support_level></span><br><span style="color: hsl(0, 100%, 40%);">- <replacement>app_mixmonitor</replacement></span><br><span style="color: hsl(0, 100%, 40%);">- <deprecated_in>16</deprecated_in></span><br><span style="color: hsl(0, 100%, 40%);">- <removed_in>21</removed_in></span><br><span style="color: hsl(0, 100%, 40%);">- ***/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include <sys/stat.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <libgen.h></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/paths.h" /* use ast_config_AST_MONITOR_DIR */</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/lock.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/channel.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/file.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/pbx.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/module.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/cli.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/manager.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/stasis.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/stasis_channels.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#define AST_API_MODULE</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/monitor.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#undef AST_API_MODULE</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/app.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/utils.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/config.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/options.h"</span><br><span style="color: hsl(0, 100%, 40%);">-#include "asterisk/beep.h"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*** DOCUMENTATION</span><br><span style="color: hsl(0, 100%, 40%);">- <application name="Monitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Monitor a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="file_format" argsep=":"></span><br><span style="color: hsl(0, 100%, 40%);">- <argument name="file_format" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Optional. If not set, defaults to <literal>wav</literal></para></span><br><span style="color: hsl(0, 100%, 40%);">- </argument></span><br><span style="color: hsl(0, 100%, 40%);">- <argument name="urlbase" /></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="fname_base"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>If set, changes the filename used to the one specified.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="options"></span><br><span style="color: hsl(0, 100%, 40%);">- <optionlist></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="m"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>When the recording ends mix the two leg files into one and</span><br><span style="color: hsl(0, 100%, 40%);">- delete the two leg files. If the variable <variable>MONITOR_EXEC</variable></span><br><span style="color: hsl(0, 100%, 40%);">- is set, the application referenced in it will be executed instead of</span><br><span style="color: hsl(0, 100%, 40%);">- soxmix/sox and the raw leg files will NOT be deleted automatically.</span><br><span style="color: hsl(0, 100%, 40%);">- soxmix/sox or <variable>MONITOR_EXEC</variable> is handed 3 arguments,</span><br><span style="color: hsl(0, 100%, 40%);">- the two leg files and a target mixed file name which is the same as</span><br><span style="color: hsl(0, 100%, 40%);">- the leg file names only without the in/out designator.</para></span><br><span style="color: hsl(0, 100%, 40%);">- <para>If <variable>MONITOR_EXEC_ARGS</variable> is set, the contents</span><br><span style="color: hsl(0, 100%, 40%);">- will be passed on as additional arguments to <variable>MONITOR_EXEC</variable>.</span><br><span style="color: hsl(0, 100%, 40%);">- Both <variable>MONITOR_EXEC</variable> and the Mix flag can be set from the</span><br><span style="color: hsl(0, 100%, 40%);">- administrator interface.</para></span><br><span style="color: hsl(0, 100%, 40%);">- <warning><para>Do not use untrusted strings such as</span><br><span style="color: hsl(0, 100%, 40%);">- <variable>CALLERID(num)</variable> or <variable>CALLERID(name)</variable></span><br><span style="color: hsl(0, 100%, 40%);">- as part of <variable>MONITOR_EXEC</variable> or</span><br><span style="color: hsl(0, 100%, 40%);">- <variable>MONITOR_EXEC_ARGS</variable>. You risk a command injection</span><br><span style="color: hsl(0, 100%, 40%);">- attack executing arbitrary commands if the untrusted strings aren't</span><br><span style="color: hsl(0, 100%, 40%);">- filtered to remove dangerous characters. See function</span><br><span style="color: hsl(0, 100%, 40%);">- <variable>FILTER()</variable>.</para></warning></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="b"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Don't begin recording unless a call is bridged to another channel.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="B"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Play a periodic beep while this call is being recorded.</para></span><br><span style="color: hsl(0, 100%, 40%);">- <argument name="interval"><para>Interval, in seconds. Default is 15.</para></argument></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="i"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Skip recording of input stream (disables <literal>m</literal> option).</para></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span style="color: hsl(0, 100%, 40%);">- <option name="o"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Skip recording of output stream (disables <literal>m</literal> option).</para></span><br><span style="color: hsl(0, 100%, 40%);">- </option></span><br><span style="color: hsl(0, 100%, 40%);">- </optionlist></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Used to start monitoring a channel. The channel's input and output</span><br><span style="color: hsl(0, 100%, 40%);">- voice packets are logged to files until the channel hangs up or</span><br><span style="color: hsl(0, 100%, 40%);">- monitoring is stopped by the StopMonitor application.</para></span><br><span style="color: hsl(0, 100%, 40%);">- <para>By default, files are stored to <filename>/var/spool/asterisk/monitor/</filename>.</span><br><span style="color: hsl(0, 100%, 40%);">- Returns <literal>-1</literal> if monitor files can't be opened or if the channel is</span><br><span style="color: hsl(0, 100%, 40%);">- already monitored, otherwise <literal>0</literal>.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">StopMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- </see-also></span><br><span style="color: hsl(0, 100%, 40%);">- </application></span><br><span style="color: hsl(0, 100%, 40%);">- <application name="StopMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Stop monitoring a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax /></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Stops monitoring a channel. Has no effect if the channel is not monitored.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </application></span><br><span style="color: hsl(0, 100%, 40%);">- <application name="ChangeMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Change monitoring filename of a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="filename_base" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>The new filename base to use for monitoring this channel.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Changes monitoring filename of a channel. Has no effect if the</span><br><span style="color: hsl(0, 100%, 40%);">- channel is not monitored.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </application></span><br><span style="color: hsl(0, 100%, 40%);">- <application name="PauseMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Pause monitoring of a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax /></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">UnpauseMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- </see-also></span><br><span style="color: hsl(0, 100%, 40%);">- </application></span><br><span style="color: hsl(0, 100%, 40%);">- <application name="UnpauseMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Unpause monitoring of a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax /></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Unpauses monitoring of a channel on which monitoring had</span><br><span style="color: hsl(0, 100%, 40%);">- previously been paused with PauseMonitor.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- <see-also></span><br><span style="color: hsl(0, 100%, 40%);">- <ref type="application">PauseMonitor</ref></span><br><span style="color: hsl(0, 100%, 40%);">- </see-also></span><br><span style="color: hsl(0, 100%, 40%);">- </application></span><br><span style="color: hsl(0, 100%, 40%);">- <manager name="Monitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Monitor a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Channel" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Used to specify the channel to record.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="File"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Is the name of the file created in the monitor spool directory.</span><br><span style="color: hsl(0, 100%, 40%);">- Defaults to the same name as the channel (with slashes replaced with dashes).</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Format"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Is the audio recording format. Defaults to <literal>wav</literal>.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Mix"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Boolean parameter as to whether to mix the input and output channels</span><br><span style="color: hsl(0, 100%, 40%);">- together after the recording is finished.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This action may be used to record the audio on a</span><br><span style="color: hsl(0, 100%, 40%);">- specified channel.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </manager></span><br><span style="color: hsl(0, 100%, 40%);">- <manager name="StopMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Stop monitoring a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Channel" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>The name of the channel monitored.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This action may be used to end a previously started 'Monitor' action.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </manager></span><br><span style="color: hsl(0, 100%, 40%);">- <manager name="ChangeMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Change monitoring filename of a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Channel" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Used to specify the channel to record.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="File" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Is the new name of the file created in the</span><br><span style="color: hsl(0, 100%, 40%);">- monitor spool directory.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This action may be used to change the file</span><br><span style="color: hsl(0, 100%, 40%);">- started by a previous 'Monitor' action.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </manager></span><br><span style="color: hsl(0, 100%, 40%);">- <manager name="PauseMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Pause monitoring of a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Channel" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Used to specify the channel to record.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This action may be used to temporarily stop the</span><br><span style="color: hsl(0, 100%, 40%);">- recording of a channel.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </manager></span><br><span style="color: hsl(0, 100%, 40%);">- <manager name="UnpauseMonitor" language="en_US"></span><br><span style="color: hsl(0, 100%, 40%);">- <synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- Unpause monitoring of a channel.</span><br><span style="color: hsl(0, 100%, 40%);">- </synopsis></span><br><span style="color: hsl(0, 100%, 40%);">- <syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" /></span><br><span style="color: hsl(0, 100%, 40%);">- <parameter name="Channel" required="true"></span><br><span style="color: hsl(0, 100%, 40%);">- <para>Used to specify the channel to record.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </parameter></span><br><span style="color: hsl(0, 100%, 40%);">- </syntax></span><br><span style="color: hsl(0, 100%, 40%);">- <description></span><br><span style="color: hsl(0, 100%, 40%);">- <para>This action may be used to re-enable recording</span><br><span style="color: hsl(0, 100%, 40%);">- of a channel after calling PauseMonitor.</para></span><br><span style="color: hsl(0, 100%, 40%);">- </description></span><br><span style="color: hsl(0, 100%, 40%);">- </manager></span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ***/</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-AST_MUTEX_DEFINE_STATIC(monitorlock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define LOCK_IF_NEEDED(lock, needed) do { \</span><br><span style="color: hsl(0, 100%, 40%);">- if (needed) \</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(lock); \</span><br><span style="color: hsl(0, 100%, 40%);">- } while(0)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-#define UNLOCK_IF_NEEDED(lock, needed) do { \</span><br><span style="color: hsl(0, 100%, 40%);">- if (needed) \</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(lock); \</span><br><span style="color: hsl(0, 100%, 40%);">- } while (0)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static unsigned long seq = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Change state of monitored channel</span><br><span style="color: hsl(0, 100%, 40%);">- * \param chan</span><br><span style="color: hsl(0, 100%, 40%);">- * \param state monitor state</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on failure.</span><br><span style="color: hsl(0, 100%, 40%);">-*/</span><br><span style="color: hsl(0, 100%, 40%);">-static int ast_monitor_set_state(struct ast_channel *chan, int state)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- LOCK_IF_NEEDED(chan, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_channel_monitor(chan)) {</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor(chan)->state = state;</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Start monitoring a channel</span><br><span style="color: hsl(0, 100%, 40%);">- * \param chan ast_channel struct to record</span><br><span style="color: hsl(0, 100%, 40%);">- * \param format_spec file format to use for recording</span><br><span style="color: hsl(0, 100%, 40%);">- * \param fname_base filename base to record to</span><br><span style="color: hsl(0, 100%, 40%);">- * \param need_lock whether to lock the channel mutex</span><br><span style="color: hsl(0, 100%, 40%);">- * \param stream_action whether to record the input and/or output streams. X_REC_IN | X_REC_OUT is most often used</span><br><span style="color: hsl(0, 100%, 40%);">- * \param beep_id</span><br><span style="color: hsl(0, 100%, 40%);">- * Creates the file to record, if no format is specified it assumes WAV</span><br><span style="color: hsl(0, 100%, 40%);">- * It also sets channel variable __MONITORED=yes</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on failure</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const char *format_spec,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *fname_base, int need_lock, int stream_action,</span><br><span style="color: hsl(0, 100%, 40%);">- const char *beep_id)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(ast_channel_monitor(chan))) {</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel_monitor *monitor;</span><br><span style="color: hsl(0, 100%, 40%);">- char *channel_name, *p;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Create monitoring directory if needed */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_mkdir(ast_config_AST_MONITOR_DIR, 0777);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(beep_id)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(monitor->beep_id, beep_id, sizeof(monitor->beep_id));</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Determine file names */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(fname_base)) {</span><br><span style="color: hsl(0, 100%, 40%);">- int directory = strchr(fname_base, '/') ? 1 : 0;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *absolute_suffix = *fname_base == '/' ? "" : "/";</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in",</span><br><span style="color: hsl(0, 100%, 40%);">- absolute, absolute_suffix, fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",</span><br><span style="color: hsl(0, 100%, 40%);">- absolute, absolute_suffix, fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s",</span><br><span style="color: hsl(0, 100%, 40%);">- absolute, absolute_suffix, fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* try creating the directory just in case it doesn't exist */</span><br><span style="color: hsl(0, 100%, 40%);">- if (directory) {</span><br><span style="color: hsl(0, 100%, 40%);">- char *name = ast_strdupa(monitor->filename_base);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_mkdir(dirname(name), 0777);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_mutex_lock(&monitorlock);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%lu",</span><br><span style="color: hsl(0, 100%, 40%);">- ast_config_AST_MONITOR_DIR, seq);</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%lu",</span><br><span style="color: hsl(0, 100%, 40%);">- ast_config_AST_MONITOR_DIR, seq);</span><br><span style="color: hsl(0, 100%, 40%);">- seq++;</span><br><span style="color: hsl(0, 100%, 40%);">- ast_mutex_unlock(&monitorlock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Replace all '/' chars from the channel name with '-' chars. */</span><br><span style="color: hsl(0, 100%, 40%);">- channel_name = ast_strdupa(ast_channel_name(chan));</span><br><span style="color: hsl(0, 100%, 40%);">- for (p = channel_name; (p = strchr(p, '/')); ) {</span><br><span style="color: hsl(0, 100%, 40%);">- *p = '-';</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",</span><br><span style="color: hsl(0, 100%, 40%);">- ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->filename_changed = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->stop = ast_monitor_stop;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Determine file format */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(format_spec)) {</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->format = ast_strdup(format_spec);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->format = ast_strdup("wav");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* open files */</span><br><span style="color: hsl(0, 100%, 40%);">- if (stream_action & X_REC_IN) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0)</span><br><span style="color: hsl(0, 100%, 40%);">- ast_filedelete(monitor->read_filename, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(monitor->read_stream = ast_writefile(monitor->read_filename,</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->format, NULL,</span><br><span style="color: hsl(0, 100%, 40%);">- O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Could not create file %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->read_filename);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(monitor);</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->read_stream = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (stream_action & X_REC_OUT) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_filedelete(monitor->write_filename, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(monitor->write_stream = ast_writefile(monitor->write_filename,</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->format, NULL,</span><br><span style="color: hsl(0, 100%, 40%);">- O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Could not create file %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->write_filename);</span><br><span style="color: hsl(0, 100%, 40%);">- if (monitor->read_stream) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_closestream(monitor->read_stream);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(monitor);</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else</span><br><span style="color: hsl(0, 100%, 40%);">- monitor->write_stream = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_insmpl_set(chan, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_outsmpl_set(chan, 0);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_set(chan, monitor);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_set_state(chan, AST_MONITOR_RUNNING);</span><br><span style="color: hsl(0, 100%, 40%);">- /* so we know this call has been monitored in case we need to bill for it or something */</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(chan, "__MONITORED","true");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_start_type(),</span><br><span style="color: hsl(0, 100%, 40%);">- NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- if (message) {</span><br><span style="color: hsl(0, 100%, 40%);">- stasis_publish(ast_channel_topic(chan), message);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1,"Cannot start monitoring %s, already monitored\n", ast_channel_name(chan));</span><br><span style="color: hsl(0, 100%, 40%);">- res = -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Get audio format.</span><br><span style="color: hsl(0, 100%, 40%);">- * \param format recording format.</span><br><span style="color: hsl(0, 100%, 40%);">- * The file format extensions that Asterisk uses are not all the same as that</span><br><span style="color: hsl(0, 100%, 40%);">- * which soxmix expects. This function ensures that the format used as the</span><br><span style="color: hsl(0, 100%, 40%);">- * extension on the filename is something soxmix will understand.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static const char *get_soxmix_format(const char *format)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- const char *res = format;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!strcasecmp(format,"ulaw"))</span><br><span style="color: hsl(0, 100%, 40%);">- res = "ul";</span><br><span style="color: hsl(0, 100%, 40%);">- if (!strcasecmp(format,"alaw"))</span><br><span style="color: hsl(0, 100%, 40%);">- res = "al";</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Stop monitoring channel</span><br><span style="color: hsl(0, 100%, 40%);">- * \param chan</span><br><span style="color: hsl(0, 100%, 40%);">- * \param need_lock</span><br><span style="color: hsl(0, 100%, 40%);">- * Stop the recording, close any open streams, mix in/out channels if required</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 Always</span><br><span style="color: hsl(0, 100%, 40%);">-*/</span><br><span style="color: hsl(0, 100%, 40%);">-int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- int delfiles = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)) {</span><br><span style="color: hsl(0, 100%, 40%);">- RAII_VAR(struct ast_str *, tmp, ast_str_create(1024), ast_free);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)->read_stream) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_closestream(ast_channel_monitor(chan)->read_stream);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)->write_stream) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_closestream(ast_channel_monitor(chan)->write_stream);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tmp && ast_channel_monitor(chan)->filename_changed && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_fileexists(ast_channel_monitor(chan)->read_filename,NULL,NULL) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_str_set(&tmp, 0, "%s-in", ast_channel_monitor(chan)->filename_base);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_fileexists(ast_str_buffer(tmp), NULL, NULL) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_filedelete(ast_str_buffer(tmp), NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_filerename(ast_channel_monitor(chan)->read_filename, ast_str_buffer(tmp), ast_channel_monitor(chan)->format);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->read_filename);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tmp && ast_fileexists(ast_channel_monitor(chan)->write_filename,NULL,NULL) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_str_set(&tmp, 0, "%s-out", ast_channel_monitor(chan)->filename_base);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_fileexists(ast_str_buffer(tmp), NULL, NULL) > 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_filedelete(ast_str_buffer(tmp), NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_filerename(ast_channel_monitor(chan)->write_filename, ast_str_buffer(tmp), ast_channel_monitor(chan)->format);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "File %s not found\n", ast_channel_monitor(chan)->write_filename);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (tmp && ast_channel_monitor(chan)->joinfiles && !ast_strlen_zero(ast_channel_monitor(chan)->filename_base)) {</span><br><span style="color: hsl(0, 100%, 40%);">- const char *format = !strcasecmp(ast_channel_monitor(chan)->format,"wav49") ? "WAV" : ast_channel_monitor(chan)->format;</span><br><span style="color: hsl(0, 100%, 40%);">- char *fname_base = ast_channel_monitor(chan)->filename_base;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *execute, *execute_args;</span><br><span style="color: hsl(0, 100%, 40%);">- /* at this point, fname_base really is the full path */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Set the execute application */</span><br><span style="color: hsl(0, 100%, 40%);">- execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(execute)) {</span><br><span style="color: hsl(0, 100%, 40%);">-#ifdef HAVE_SOXMIX</span><br><span style="color: hsl(0, 100%, 40%);">- execute = "nice -n 19 soxmix";</span><br><span style="color: hsl(0, 100%, 40%);">-#else</span><br><span style="color: hsl(0, 100%, 40%);">- execute = "nice -n 19 sox -m";</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(0, 100%, 40%);">- format = get_soxmix_format(format);</span><br><span style="color: hsl(0, 100%, 40%);">- delfiles = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(execute_args)) {</span><br><span style="color: hsl(0, 100%, 40%);">- execute_args = "";</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_str_set(&tmp, 0, delfiles ? "( " : "");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_str_append(&tmp, 0, "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &",</span><br><span style="color: hsl(0, 100%, 40%);">- execute, fname_base, format, fname_base, format, fname_base, format,execute_args);</span><br><span style="color: hsl(0, 100%, 40%);">- if (delfiles) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* remove legs when done mixing */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_str_append(&tmp, 0, "& rm -f \"%s-\"* ) &", fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(1,"monitor executing %s\n", ast_str_buffer(tmp));</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_safe_system(ast_str_buffer(tmp)) == -1)</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Execute of %s failed.\n", ast_str_buffer(tmp));</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(ast_channel_monitor(chan)->beep_id)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_beep_stop(chan, ast_channel_monitor(chan)->beep_id);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(ast_channel_monitor(chan)->format);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_free(ast_channel_monitor(chan));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_set(chan, NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- message = ast_channel_blob_create_from_cache(ast_channel_uniqueid(chan),</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor_stop_type(),</span><br><span style="color: hsl(0, 100%, 40%);">- NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- if (message) {</span><br><span style="color: hsl(0, 100%, 40%);">- stasis_publish(ast_channel_topic(chan), message);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(chan, "MONITORED", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Pause monitoring of channel */</span><br><span style="color: hsl(0, 100%, 40%);">-int AST_OPTIONAL_API_NAME(ast_monitor_pause)(struct ast_channel *chan)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Unpause monitoring of channel */</span><br><span style="color: hsl(0, 100%, 40%);">-int AST_OPTIONAL_API_NAME(ast_monitor_unpause)(struct ast_channel *chan)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Wrapper for ast_monitor_pause */</span><br><span style="color: hsl(0, 100%, 40%);">-static int pause_monitor_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_monitor_pause(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Wrapper for ast_monitor_unpause */</span><br><span style="color: hsl(0, 100%, 40%);">-static int unpause_monitor_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_monitor_unpause(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Change monitored filename of channel</span><br><span style="color: hsl(0, 100%, 40%);">- * \param chan</span><br><span style="color: hsl(0, 100%, 40%);">- * \param fname_base new filename</span><br><span style="color: hsl(0, 100%, 40%);">- * \param need_lock</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on failure.</span><br><span style="color: hsl(0, 100%, 40%);">-*/</span><br><span style="color: hsl(0, 100%, 40%);">-int AST_OPTIONAL_API_NAME(ast_monitor_change_fname)(struct ast_channel *chan, const char *fname_base, int need_lock)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(fname_base)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", ast_channel_name(chan));</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan)) {</span><br><span style="color: hsl(0, 100%, 40%);">- int directory = strchr(fname_base, '/') ? 1 : 0;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *absolute_suffix = *fname_base == '/' ? "" : "/";</span><br><span style="color: hsl(0, 100%, 40%);">- char tmpstring[sizeof(ast_channel_monitor(chan)->filename_base)] = "";</span><br><span style="color: hsl(0, 100%, 40%);">- int i, fd[2] = { -1, -1 }, doexit = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* before continuing, see if we're trying to rename the file to itself... */</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* try creating the directory just in case it doesn't exist */</span><br><span style="color: hsl(0, 100%, 40%);">- if (directory) {</span><br><span style="color: hsl(0, 100%, 40%);">- char *name = ast_strdupa(tmpstring);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_mkdir(dirname(name), 0777);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \note We cannot just compare filenames, due to symlinks, relative</span><br><span style="color: hsl(0, 100%, 40%);">- * paths, and other possible filesystem issues. We could use</span><br><span style="color: hsl(0, 100%, 40%);">- * realpath(3), but its use is discouraged. However, if we try to</span><br><span style="color: hsl(0, 100%, 40%);">- * create the same file from two different paths, the second will</span><br><span style="color: hsl(0, 100%, 40%);">- * fail, and so we have our notification that the filenames point to</span><br><span style="color: hsl(0, 100%, 40%);">- * the same path.</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Remember, also, that we're using the basename of the file (i.e.</span><br><span style="color: hsl(0, 100%, 40%);">- * the file without the format suffix), so it does not already exist</span><br><span style="color: hsl(0, 100%, 40%);">- * and we aren't interfering with the recording itself.</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, ast_channel_monitor(chan)->filename_base);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||</span><br><span style="color: hsl(0, 100%, 40%);">- (fd[1] = open(ast_channel_monitor(chan)->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (fd[0] < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_debug(2, "No need to rename monitor filename to itself\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- doexit = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Cleanup temporary files */</span><br><span style="color: hsl(0, 100%, 40%);">- for (i = 0; i < 2; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (fd[i] >= 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- while (close(fd[i]) < 0 && errno == EINTR);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- unlink(tmpstring);</span><br><span style="color: hsl(0, 100%, 40%);">- /* if previous monitor file existed in a subdirectory, the directory will not be removed */</span><br><span style="color: hsl(0, 100%, 40%);">- unlink(ast_channel_monitor(chan)->filename_base);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (doexit) {</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ast_copy_string(ast_channel_monitor(chan)->filename_base, tmpstring, sizeof(ast_channel_monitor(chan)->filename_base));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor(chan)->filename_changed = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", ast_channel_name(chan), fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- UNLOCK_IF_NEEDED(chan, need_lock);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum {</span><br><span style="color: hsl(0, 100%, 40%);">- MON_FLAG_BRIDGED = (1 << 0),</span><br><span style="color: hsl(0, 100%, 40%);">- MON_FLAG_MIX = (1 << 1),</span><br><span style="color: hsl(0, 100%, 40%);">- MON_FLAG_DROP_IN = (1 << 2),</span><br><span style="color: hsl(0, 100%, 40%);">- MON_FLAG_DROP_OUT = (1 << 3),</span><br><span style="color: hsl(0, 100%, 40%);">- MON_FLAG_BEEP = (1 << 4),</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum {</span><br><span style="color: hsl(0, 100%, 40%);">- OPT_ARG_BEEP_INTERVAL,</span><br><span style="color: hsl(0, 100%, 40%);">- OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-AST_APP_OPTIONS(monitor_opts, {</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_OPTION('b', MON_FLAG_BRIDGED),</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_OPTION('m', MON_FLAG_MIX),</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_OPTION('i', MON_FLAG_DROP_IN),</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_OPTION('o', MON_FLAG_DROP_OUT),</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_OPTION_ARG('B', MON_FLAG_BEEP, OPT_ARG_BEEP_INTERVAL),</span><br><span style="color: hsl(0, 100%, 40%);">-});</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Start monitor</span><br><span style="color: hsl(0, 100%, 40%);">- * \param chan</span><br><span style="color: hsl(0, 100%, 40%);">- * \param data arguments passed fname|options</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval 0 on success.</span><br><span style="color: hsl(0, 100%, 40%);">- * \retval -1 on failure.</span><br><span style="color: hsl(0, 100%, 40%);">-*/</span><br><span style="color: hsl(0, 100%, 40%);">-static int start_monitor_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- char *arg;</span><br><span style="color: hsl(0, 100%, 40%);">- char *options;</span><br><span style="color: hsl(0, 100%, 40%);">- char *delay;</span><br><span style="color: hsl(0, 100%, 40%);">- char *urlprefix = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- char tmp[256];</span><br><span style="color: hsl(0, 100%, 40%);">- int stream_action = X_REC_IN | X_REC_OUT;</span><br><span style="color: hsl(0, 100%, 40%);">- int joinfiles = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- int res = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- char *parse;</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_flags flags = { 0 };</span><br><span style="color: hsl(0, 100%, 40%);">- char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };</span><br><span style="color: hsl(0, 100%, 40%);">- char beep_id[64] = "";</span><br><span style="color: hsl(0, 100%, 40%);">- AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_ARG(format);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_ARG(fname_base);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_APP_ARG(options);</span><br><span style="color: hsl(0, 100%, 40%);">- );</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Parse arguments. */</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(data)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_ERROR, "Monitor requires an argument\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- parse = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">- AST_STANDARD_APP_ARGS(args, parse);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(args.options)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_app_parse_options(monitor_opts, &flags, opts, args.options);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_test_flag(&flags, MON_FLAG_MIX)) {</span><br><span style="color: hsl(0, 100%, 40%);">- stream_action |= X_JOIN;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_test_flag(&flags, MON_FLAG_DROP_IN)) {</span><br><span style="color: hsl(0, 100%, 40%);">- stream_action &= ~X_REC_IN;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_test_flag(&flags, MON_FLAG_DROP_OUT)) {</span><br><span style="color: hsl(0, 100%, 40%);">- stream_action &= ~X_REC_OUT;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_test_flag(&flags, MON_FLAG_BEEP)) {</span><br><span style="color: hsl(0, 100%, 40%);">- const char *interval_str = S_OR(opts[OPT_ARG_BEEP_INTERVAL], "15");</span><br><span style="color: hsl(0, 100%, 40%);">- unsigned int interval = 15;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (sscanf(interval_str, "%30u", &interval) != 1) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Invalid interval '%s' for periodic beep. Using default of %u\n",</span><br><span style="color: hsl(0, 100%, 40%);">- interval_str, interval);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_beep_start(chan, interval, beep_id, sizeof(beep_id))) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Unable to enable periodic beep, please ensure func_periodic_hook is loaded.\n");</span><br><span style="color: hsl(0, 100%, 40%);">- return -1;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- arg = strchr(args.format, ':');</span><br><span style="color: hsl(0, 100%, 40%);">- if (arg) {</span><br><span style="color: hsl(0, 100%, 40%);">- *arg++ = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- urlprefix = arg;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(urlprefix) && !ast_strlen_zero(args.fname_base)) {</span><br><span style="color: hsl(0, 100%, 40%);">- snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base,</span><br><span style="color: hsl(0, 100%, 40%);">- ((strcmp(args.format, "gsm")) ? "wav" : "gsm"));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(chan);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_cdr_setuserfield(ast_channel_name(chan), tmp);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(chan);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_test_flag(&flags, MON_FLAG_BRIDGED)) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* We must remove the "b" option if listed. In principle none of</span><br><span style="color: hsl(0, 100%, 40%);">- the following could give NULL results, but we check just to</span><br><span style="color: hsl(0, 100%, 40%);">- be pedantic. Reconstructing with checks for 'm' option does not</span><br><span style="color: hsl(0, 100%, 40%);">- work if we end up adding more options than 'm' in the future. */</span><br><span style="color: hsl(0, 100%, 40%);">- delay = ast_strdupa(data);</span><br><span style="color: hsl(0, 100%, 40%);">- options = strrchr(delay, ',');</span><br><span style="color: hsl(0, 100%, 40%);">- if (options) {</span><br><span style="color: hsl(0, 100%, 40%);">- arg = strchr(options, 'b');</span><br><span style="color: hsl(0, 100%, 40%);">- if (arg) {</span><br><span style="color: hsl(0, 100%, 40%);">- *arg = 'X';</span><br><span style="color: hsl(0, 100%, 40%);">- pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action, beep_id);</span><br><span style="color: hsl(0, 100%, 40%);">- if (res < 0)</span><br><span style="color: hsl(0, 100%, 40%);">- res = ast_monitor_change_fname(chan, args.fname_base, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (stream_action & X_JOIN) {</span><br><span style="color: hsl(0, 100%, 40%);">- if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))</span><br><span style="color: hsl(0, 100%, 40%);">- joinfiles = 1;</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_setjoinfiles(chan, joinfiles);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return res;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Wrapper function \see ast_monitor_stop */</span><br><span style="color: hsl(0, 100%, 40%);">-static int stop_monitor_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_monitor_stop(chan, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Wrapper function \see ast_monitor_change_fname */</span><br><span style="color: hsl(0, 100%, 40%);">-static int change_monitor_exec(struct ast_channel *chan, const char *data)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return ast_monitor_change_fname(chan, data, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Start monitoring a channel by manager connection */</span><br><span style="color: hsl(0, 100%, 40%);">-static int start_monitor_action(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *c = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *name = astman_get_header(m, "Channel");</span><br><span style="color: hsl(0, 100%, 40%);">- const char *fname = astman_get_header(m, "File");</span><br><span style="color: hsl(0, 100%, 40%);">- const char *format = astman_get_header(m, "Format");</span><br><span style="color: hsl(0, 100%, 40%);">- const char *mix = astman_get_header(m, "Mix");</span><br><span style="color: hsl(0, 100%, 40%);">- char *d;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(name)) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No channel specified");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(c = ast_channel_get_by_name(name))) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No such channel");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(fname)) {</span><br><span style="color: hsl(0, 100%, 40%);">- /* No filename specified, default to the channel name. */</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(c);</span><br><span style="color: hsl(0, 100%, 40%);">- fname = ast_strdupa(ast_channel_name(c));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(c);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Replace all '/' chars from the channel name with '-' chars. */</span><br><span style="color: hsl(0, 100%, 40%);">- for (d = (char *) fname; (d = strchr(d, '/')); ) {</span><br><span style="color: hsl(0, 100%, 40%);">- *d = '-';</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT, NULL)) {</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_monitor_change_fname(c, fname, 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Could not start monitoring channel");</span><br><span style="color: hsl(0, 100%, 40%);">- c = ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_true(mix)) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_lock(c);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_setjoinfiles(c, 1);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_unlock(c);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- c = ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, "Started monitoring channel");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Stop monitoring a channel by manager connection */</span><br><span style="color: hsl(0, 100%, 40%);">-static int stop_monitor_action(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *c = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *name = astman_get_header(m, "Channel");</span><br><span style="color: hsl(0, 100%, 40%);">- int res;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(name)) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No channel specified");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(c = ast_channel_get_by_name(name))) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No such channel");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- res = ast_monitor_stop(c, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- c = ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (res) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Could not stop monitoring channel");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, "Stopped monitoring channel");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*! \brief Change filename of a monitored channel by manager connection */</span><br><span style="color: hsl(0, 100%, 40%);">-static int change_monitor_action(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *c = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *name = astman_get_header(m, "Channel");</span><br><span style="color: hsl(0, 100%, 40%);">- const char *fname = astman_get_header(m, "File");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(name)) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No channel specified");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(fname)) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No filename specified");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(c = ast_channel_get_by_name(name))) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No such channel");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_monitor_change_fname(c, fname, 1)) {</span><br><span style="color: hsl(0, 100%, 40%);">- c = ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "Could not change monitored filename of channel");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- c = ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, "Changed monitor filename");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-void AST_OPTIONAL_API_NAME(ast_monitor_setjoinfiles)(struct ast_channel *chan, int turnon)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_channel_monitor(chan))</span><br><span style="color: hsl(0, 100%, 40%);">- ast_channel_monitor(chan)->joinfiles = turnon;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum MONITOR_PAUSING_ACTION</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- MONITOR_ACTION_PAUSE,</span><br><span style="color: hsl(0, 100%, 40%);">- MONITOR_ACTION_UNPAUSE</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- struct ast_channel *c = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- const char *name = astman_get_header(m, "Channel");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(name)) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No channel specified");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (!(c = ast_channel_get_by_name(name))) {</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_error(s, m, "No such channel");</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if (action == MONITOR_ACTION_PAUSE) {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_pause(c);</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- ast_monitor_unpause(c);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- c = ast_channel_unref(c);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return AMI_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int pause_monitor_action(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int unpause_monitor_action(struct mansession *s, const struct message *m)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int load_module(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- ast_register_application_xml("Monitor", start_monitor_exec);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_register_application_xml("StopMonitor", stop_monitor_exec);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_register_application_xml("ChangeMonitor", change_monitor_exec);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_register_application_xml("PauseMonitor", pause_monitor_exec);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static int unload_module(void)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- ast_unregister_application("Monitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_unregister_application("StopMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_unregister_application("ChangeMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_unregister_application("PauseMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_unregister_application("UnpauseMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_unregister("Monitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_unregister("StopMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_unregister("ChangeMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_unregister("PauseMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">- ast_manager_unregister("UnpauseMonitor");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* usecount semantics need to be defined */</span><br><span style="color: hsl(0, 100%, 40%);">-AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Call Monitoring Resource",</span><br><span style="color: hsl(0, 100%, 40%);">- .support_level = AST_MODULE_SUPPORT_DEPRECATED,</span><br><span style="color: hsl(0, 100%, 40%);">- .load = load_module,</span><br><span style="color: hsl(0, 100%, 40%);">- .unload = unload_module,</span><br><span style="color: hsl(0, 100%, 40%);">- .load_pri = AST_MODPRI_CHANNEL_DEPEND,</span><br><span style="color: hsl(0, 100%, 40%);">- .optional_modules = "func_periodic_hook",</span><br><span style="color: hsl(0, 100%, 40%);">-);</span><br><span>diff --git a/res/res_monitor.exports.in b/res/res_monitor.exports.in</span><br><span>deleted file mode 100644</span><br><span>index 4a40724..0000000</span><br><span>--- a/res/res_monitor.exports.in</span><br><span>+++ /dev/null</span><br><span>@@ -1,11 +0,0 @@</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">- global:</span><br><span style="color: hsl(0, 100%, 40%);">- LINKER_SYMBOL_PREFIX*ast_monitor_change_fname;</span><br><span style="color: hsl(0, 100%, 40%);">- LINKER_SYMBOL_PREFIX*ast_monitor_pause;</span><br><span style="color: hsl(0, 100%, 40%);">- LINKER_SYMBOL_PREFIX*ast_monitor_setjoinfiles;</span><br><span style="color: hsl(0, 100%, 40%);">- LINKER_SYMBOL_PREFIX*ast_monitor_start;</span><br><span style="color: hsl(0, 100%, 40%);">- LINKER_SYMBOL_PREFIX*ast_monitor_stop;</span><br><span style="color: hsl(0, 100%, 40%);">- LINKER_SYMBOL_PREFIX*ast_monitor_unpause;</span><br><span style="color: hsl(0, 100%, 40%);">- local:</span><br><span style="color: hsl(0, 100%, 40%);">- *;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19605">change 19605</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/+/19605"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I0462caefb4f9544e2e2baa23c498858310b52d50 </div>
<div style="display:none"> Gerrit-Change-Number: 19605 </div>
<div style="display:none"> Gerrit-PatchSet: 9 </div>
<div style="display:none"> Gerrit-Owner: Michael Bradeen <mbradeen@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.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-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: N A <asterisk@phreaknet.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>