<p>Michael Bradeen has uploaded this change for <strong>review</strong>.</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;">res_monitor: Remove deprecated module.<br><br>ASTERISK-30303<br><br>Change-Id: I0462caefb4f9544e2e2baa23c498858310b52d50<br>---<br>M apps/Makefile<br>M apps/app_queue.c<br>M bridges/bridge_builtin_features.c<br>M channels/Makefile<br>A doc/UPGRADE-staging/res_monitor_removal.txt<br>M include/asterisk/bridge_features.h<br>M include/asterisk/doxygen/architecture.h<br>D include/asterisk/monitor.h<br>M main/asterisk.dynamics<br>M menuselect/example_menuselect-tree<br>M menuselect/test/menuselect-tree<br>M pbx/Makefile<br>D res/res_monitor.c<br>D res/res_monitor.exports.in<br>14 files changed, 20 insertions(+), 1,359 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/05/19605/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><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_queue.c b/apps/app_queue.c</span><br><span>index 288c0ff..7030166 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>@@ -1868,7 +1857,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>@@ -2972,7 +2960,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>@@ -3456,10 +3443,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>@@ -6934,7 +6917,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>@@ -6950,7 +6932,6 @@</span><br><span> char *macroexec = 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>@@ -6959,7 +6940,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>@@ -7280,32 +7260,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>@@ -11847,5 +11802,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..e6c84ab 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>@@ -103,199 +101,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>@@ -503,7 +308,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 +316,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 +328,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 0af82d9..706aa51 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/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..81b39a7</span><br><span>--- /dev/null</span><br><span>+++ b/doc/UPGRADE-staging/res_monitor_removal.txt</span><br><span>@@ -0,0 +1,6 @@</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>diff --git a/include/asterisk/bridge_features.h b/include/asterisk/bridge_features.h</span><br><span>index 39fb80f..b167d9d 100644</span><br><span>--- a/include/asterisk/bridge_features.h</span><br><span>+++ b/include/asterisk/bridge_features.h</span><br><span>@@ -313,11 +313,6 @@</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/doxygen/architecture.h b/include/asterisk/doxygen/architecture.h</span><br><span>index 780b64f..64a6e2e 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/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/main/asterisk.dynamics b/main/asterisk.dynamics</span><br><span>index 1c4b1b1..b03e272 100644</span><br><span>--- a/main/asterisk.dynamics</span><br><span>+++ b/main/asterisk.dynamics</span><br><span>@@ -4,7 +4,6 @@</span><br><span> *ast_beep_*;</span><br><span> *ast_pktccops_*;</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/menuselect/example_menuselect-tree b/menuselect/example_menuselect-tree</span><br><span>index 0b703e6..8837d77 100644</span><br><span>--- a/menuselect/example_menuselect-tree</span><br><span>+++ b/menuselect/example_menuselect-tree</span><br><span>@@ -366,8 +366,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 3710278..f24334e 100644</span><br><span>--- a/menuselect/test/menuselect-tree</span><br><span>+++ b/menuselect/test/menuselect-tree</span><br><span>@@ -103,7 +103,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>@@ -465,8 +464,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/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: 1 </div>
<div style="display:none"> Gerrit-Owner: Michael Bradeen <mbradeen@sangoma.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>