Index: apps/app_mixmonitor.c
===================================================================
--- apps/app_mixmonitor.c	(revision 244059)
+++ apps/app_mixmonitor.c	(working copy)
@@ -54,6 +54,7 @@
 #include "asterisk/app.h"
 #include "asterisk/linkedlists.h"
 #include "asterisk/utils.h"
+#include "asterisk/manager.h"
 
 #define get_volfactor(x) x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
 
@@ -585,6 +586,87 @@
 	return ast_complete_channels(line, word, pos, state, 2);
 }
 
+/*! \brief  Mute / unmute  a MixMonitor channel */
+static int mute_mixmonitor(struct mansession *s, const struct message *m, int muteflag)
+{
+        struct ast_channel *c = NULL;
+
+        const char *name = astman_get_header(m, "Channel");
+        const char *id = astman_get_header(m,"ActionID");
+        const char *direction = astman_get_header(m,"Direction");
+
+        enum ast_audiohook_flags flag;
+
+        if (ast_strlen_zero(direction)) {
+                astman_send_error(s, m, "No direction specified Must be read|write");
+                return 0;
+        }
+
+        if (!strcmp(direction, "read")) {
+                flag = AST_AUDIOHOOK_MUTE_READ;
+
+        } else  if (!strcmp(direction, "write")) {
+                                flag = AST_AUDIOHOOK_MUTE_WRITE;
+
+        	} else  if (!strcmp(direction, "both")) {
+                                flag = AST_AUDIOHOOK_MUTE_BOTH;
+                
+		        } else {
+                                        astman_send_error(s, m, "Invalid direction specified. Must be read|write|both");
+                                        return 0;
+                                }
+
+        if (ast_strlen_zero(name)) {
+                astman_send_error(s, m, "No channel specified");
+                return 0;
+
+        } else {
+                        c = ast_get_channel_by_name_locked(name);
+                        if (!c) {
+                                astman_send_error(s, m, "No such channel");
+                                return 0;
+                        }
+        }
+
+        ast_audiohook_set_mute(c, mixmonitor_spy_type, flag, muteflag);
+
+        ast_channel_unlock(c);
+
+        astman_append(s, "Response: Success\r\n");
+
+        if (!ast_strlen_zero(id))
+                astman_append(s, "ActionID: %s\r\n",id);
+
+        astman_append(s, "\r\n");
+
+        return 0;
+}
+
+/*! \brief  unMute a MixMonitor channel */
+static int manager_unmute_mixmonitor(struct mansession *s, const struct message *m)
+{
+	return mute_mixmonitor(s,m,1);
+}
+
+/*! \brief  Mute a MixMonitor channel */
+static int manager_mute_mixmonitor(struct mansession *s, const struct message *m)
+{
+	return mute_mixmonitor(s,m,0);
+}
+
+static char mandescr_mute_mixmonitor[] =
+"Description: Mutes a Mixmonitor Channel.\n"
+"Variables: \n"
+"  Channel: Channel to mute.\n"
+"  Direction: Which part to mute. read|write|both (from channel|to channel|both channels).\n";
+
+
+static char mandescr_unmute_mixmonitor[] =
+"Description: unMutes a Mixmonitor Channel.\n"
+"Variables: \n"
+"  Channel: Channel to unmute.\n"
+"  Direction: Which part to unmute. read|write|both (from channel|to channel|both channels).\n";
+
 static struct ast_cli_entry cli_mixmonitor[] = {
 	{ { "mixmonitor", NULL, NULL },
 	mixmonitor_cli, "Execute a MixMonitor command.",
@@ -602,6 +684,9 @@
 	res = ast_unregister_application(stop_app);
 	res |= ast_unregister_application(app);
 	
+	ast_manager_unregister("MuteMixMonitor");
+	ast_manager_unregister("unMuteMixMonitor");
+		
 	ast_module_user_hangup_all();
 
 	return res;
@@ -614,6 +699,10 @@
 	ast_cli_register_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
 	res = ast_register_application(app, mixmonitor_exec, synopsis, desc);
 	res |= ast_register_application(stop_app, stop_mixmonitor_exec, stop_synopsis, stop_desc);
+	res |= ast_manager_register2("unMuteMixMonitor", 0, manager_unmute_mixmonitor,
+				"unMute a channel in MixMonitor", mandescr_unmute_mixmonitor);
+	res |= ast_manager_register2("MuteMixMonitor", 0, manager_mute_mixmonitor,
+				"Mute a channel in MixMonitor", mandescr_mute_mixmonitor);
 
 	return res;
 }
Index: main/audiohook.c
===================================================================
--- main/audiohook.c	(revision 244059)
+++ main/audiohook.c	(working copy)
@@ -134,10 +134,15 @@
 	int our_factory_ms;
 	int other_factory_samples;
 	int other_factory_ms;
+	int muteme = 0;
 
 	/* Update last feeding time to be current */
 	*time = ast_tvnow();
 
+	/* define buffer for zero data, and buffer to store original data in */
+	void *mutedbuf = NULL;
+	void *originalbuf = NULL;
+
 	our_factory_samples = ast_slinfactory_available(factory);
 	our_factory_ms = ast_tvdiff_ms(*time, previous_time) + (our_factory_samples / 8);
 	other_factory_samples = ast_slinfactory_available(other_factory);
@@ -159,9 +164,28 @@
 		ast_slinfactory_flush(other_factory);
 	}
 
+	 /* swap frame data for zeros if mute is required */
+	if ((ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) ||
+ 	    (ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) ||
+ 	     ast_test_flag(audiohook, AST_AUDIOHOOK_MUTE_BOTH)) {
+		muteme = 1;
+	}
+
+	if (muteme) {
+		mutedbuf = alloca(frame->datalen);
+		memset(mutedbuf, 0, frame->datalen);
+		originalbuf = frame->data;
+		frame->data = mutedbuf;
+	}
+
 	/* Write frame out to respective factory */
 	ast_slinfactory_feed(factory, frame);
 
+	/* swap frame data back to original */
+	if (muteme) {
+		frame->data = originalbuf;
+	}
+
 	/* If we need to notify the respective handler of this audiohook, do so */
 	if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
 		ast_cond_signal(&audiohook->trigger);
@@ -190,7 +214,7 @@
 	/* Ensure the factory is able to give us the samples we want */
 	if (samples > ast_slinfactory_available(factory))
 		return NULL;
-	
+
 	/* Read data in from factory */
 	if (!ast_slinfactory_read(factory, buf, samples))
 		return NULL;
@@ -432,7 +456,7 @@
 		if (audiohook_list->out_translate[i].trans_pvt)
 			ast_translator_free_path(audiohook_list->out_translate[i].trans_pvt);
 	}
-	
+
 	/* Free ourselves */
 	ast_free(audiohook_list);
 
@@ -720,8 +744,8 @@
 	else
 		return frame;
 }
-			
 
+
 /*! \brief Wait for audiohook trigger to be triggered
  * \param audiohook Audiohook to wait on
  */
@@ -733,8 +757,38 @@
 	tv = ast_tvadd(ast_tvnow(), ast_samp2tv(50000, 1000));
 	ts.tv_sec = tv.tv_sec;
 	ts.tv_nsec = tv.tv_usec * 1000;
-	
+
 	ast_cond_timedwait(&audiohook->trigger, &audiohook->lock, &ts);
-	
+
 	return;
 }
+
+/* generic mute/unmute on audiohook */
+int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear)
+{
+       struct ast_audiohook *audiohook = NULL;
+
+       ast_channel_lock(chan);
+
+       /* Ensure the channel has audiohooks on it */
+       if (!chan->audiohooks) {
+               ast_channel_unlock(chan);
+               return -1;
+       }
+
+       audiohook = find_audiohook_by_source(chan->audiohooks, source);
+
+       ast_channel_unlock(chan);
+
+       if (audiohook) {
+               if (clear)
+                       ast_clear_flag(audiohook, flag);
+
+               else
+                       ast_set_flag(audiohook, flag);
+       }
+
+
+       return (audiohook ? 0 : -1);
+}
+
Index: include/asterisk/audiohook.h
===================================================================
--- include/asterisk/audiohook.h	(revision 244059)
+++ include/asterisk/audiohook.h	(working copy)
@@ -58,6 +58,9 @@
 	 * slinfactories. We will flush the factories if they contain too many samples.
 	 */
 	AST_AUDIOHOOK_SMALL_QUEUE = (1 << 3),
+        AST_AUDIOHOOK_MUTE_READ = (1 << 4),
+        AST_AUDIOHOOK_MUTE_WRITE = (1 << 5),
+        AST_AUDIOHOOK_MUTE_BOTH = (1 << 6),
 };
 
 #define AST_AUDIOHOOK_SYNC_TOLERANCE 100 /*< Tolerance in milliseconds for audiohooks synchronization */
@@ -193,6 +196,8 @@
  */
 struct ast_frame *ast_audiohook_write_list(struct ast_channel *chan, struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame);
 
+int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear);
+
 /*! \brief Wait for audiohook trigger to be triggered
  * \param audiohook Audiohook to wait on
  */
