[Asterisk-code-review] res_monitor: Remove deprecated module. (asterisk[master])

George Joseph asteriskteam at digium.com
Fri Jan 13 08:32:36 CST 2023


George Joseph has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/19605 )

Change subject: res_monitor: Remove deprecated module.
......................................................................

res_monitor: Remove deprecated module.

ASTERISK-30303

Change-Id: I0462caefb4f9544e2e2baa23c498858310b52d50
---
M README-SERIOUSLY.bestpractices.md
M apps/Makefile
M apps/app_meetme.c
M apps/app_mixmonitor.c
M apps/app_queue.c
M bridges/bridge_builtin_features.c
M channels/Makefile
M configs/samples/features.conf.sample
M configs/samples/queues.conf.sample
M configs/samples/stasis.conf.sample
A doc/UPGRADE-staging/res_monitor_removal.txt
M include/asterisk/bridge_features.h
M include/asterisk/channel.h
M include/asterisk/doxygen/architecture.h
M include/asterisk/features_config.h
D include/asterisk/monitor.h
M include/asterisk/stasis_channels.h
M main/asterisk.dynamics
M main/bridge_basic.c
M main/bridge_channel.c
M main/channel.c
M main/channel_internal_api.c
M main/features.c
M main/features_config.c
M main/manager_channels.c
M main/stasis.c
M main/stasis_channels.c
M menuselect/example_menuselect-tree
M menuselect/test/menuselect-tree
M pbx/Makefile
M pbx/ael/ael-test/ael-test2/apptest.ael2
M pbx/ael/ael-test/ael-test4/apptest.ael2
M pbx/ael/ael-test/ael-test5/extensions.ael
M pbx/ael/ael-test/ael-test6/extensions.ael
D res/res_monitor.c
D res/res_monitor.exports.in
36 files changed, 61 insertions(+), 1,720 deletions(-)

Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Benjamin Keith Ford: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved; Approved for Submit
  N A: Looks good to me, but someone else must approve




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

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/19605
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I0462caefb4f9544e2e2baa23c498858310b52d50
Gerrit-Change-Number: 19605
Gerrit-PatchSet: 9
Gerrit-Owner: Michael Bradeen <mbradeen at sangoma.com>
Gerrit-Reviewer: Benjamin Keith Ford <bford at digium.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at sangoma.com>
Gerrit-Reviewer: N A <asterisk at phreaknet.org>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20230113/a79acac3/attachment-0001.html>


More information about the asterisk-code-review mailing list