[asterisk-commits] file: branch file/ah r59060 - in /team/file/ah: apps/ include/asterisk/ main/

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Mon Mar 19 20:44:56 MST 2007


Author: file
Date: Mon Mar 19 22:44:56 2007
New Revision: 59060

URL: http://svn.digium.com/view/asterisk?view=rev&rev=59060
Log:
Add support for whispering.

Modified:
    team/file/ah/apps/app_chanspy.c
    team/file/ah/apps/app_mixmonitor.c
    team/file/ah/include/asterisk/audiohook.h
    team/file/ah/main/audiohook.c

Modified: team/file/ah/apps/app_chanspy.c
URL: http://svn.digium.com/view/asterisk/team/file/ah/apps/app_chanspy.c?view=diff&rev=59060&r1=59059&r2=59060
==============================================================================
--- team/file/ah/apps/app_chanspy.c (original)
+++ team/file/ah/apps/app_chanspy.c Mon Mar 19 22:44:56 2007
@@ -166,7 +166,8 @@
 
 struct chanspy_translation_helper {
 	/* spy data */
-	struct ast_audiohook audiohook;
+	struct ast_audiohook spy_audiohook;
+	struct ast_audiohook whisper_audiohook;
 	int fd;
 	int volfactor;
 };
@@ -187,16 +188,16 @@
 	struct chanspy_translation_helper *csth = data;
 	struct ast_frame *f = NULL;
 		
-	ast_mutex_lock(&csth->audiohook.lock);
-	if (csth->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
+	ast_audiohook_lock(&csth->spy_audiohook);
+	if (csth->spy_audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
 		/* Channel is already gone more than likely */
-		ast_mutex_unlock(&csth->audiohook.lock);
+		ast_audiohook_unlock(&csth->spy_audiohook);
 		return -1;
 	}
 
-	f = ast_audiohook_read_frame(&csth->audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR);
-
-	ast_mutex_unlock(&csth->audiohook.lock);
+	f = ast_audiohook_read_frame(&csth->spy_audiohook, samples, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR);
+
+	ast_audiohook_unlock(&csth->spy_audiohook);
 		
 	if (!f)
 		return 0;
@@ -254,11 +255,16 @@
 
 	memset(&csth, 0, sizeof(csth));
 
-	ast_audiohook_init(&csth.audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
+	ast_audiohook_init(&csth.spy_audiohook, AST_AUDIOHOOK_TYPE_SPY, "ChanSpy");
 	
-	if (start_spying(spyee, chan, &csth.audiohook)) {
-		ast_audiohook_destroy(&csth.audiohook);
+	if (start_spying(spyee, chan, &csth.spy_audiohook)) {
+		ast_audiohook_destroy(&csth.spy_audiohook);
 		return 0;
+	}
+
+	if (ast_test_flag(flags, OPTION_WHISPER)) {
+		ast_audiohook_init(&csth.whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "ChanSpy");
+		start_spying(spyee, chan, &csth.whisper_audiohook);
 	}
 
 	if (ast_test_flag(flags, OPTION_PRIVATE))
@@ -280,10 +286,18 @@
 	   has arrived, since the spied-on channel could have gone away while
 	   we were waiting
 	*/
-	while ((res = ast_waitfor(chan, -1) > -1) && csth.audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
+	while ((res = ast_waitfor(chan, -1) > -1) && csth.spy_audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
 		if (!(f = ast_read(chan)) || ast_check_hangup(chan)) {
 			running = -1;
 			break;
+		}
+
+		if (ast_test_flag(flags, OPTION_WHISPER) && f->frametype == AST_FRAME_VOICE) {
+			ast_audiohook_lock(&csth.whisper_audiohook);
+			ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
+			ast_audiohook_unlock(&csth.whisper_audiohook);
+			ast_frfree(f);
+			continue;
 		}
 		
 		res = (f->frametype == AST_FRAME_DTMF) ? f->subclass : 0;
@@ -337,12 +351,17 @@
 	else
 		ast_deactivate_generator(chan);
 
-	ast_mutex_lock(&csth.audiohook.lock);
-	ast_audiohook_detach(&csth.audiohook);
-	ast_mutex_unlock(&csth.audiohook.lock);
-
-	/* If a channel still exists on our spy structure then we need to remove ourselves */
-	ast_audiohook_destroy(&csth.audiohook);
+	if (ast_test_flag(flags, OPTION_WHISPER)) {
+		ast_audiohook_lock(&csth.whisper_audiohook);
+		ast_audiohook_detach(&csth.whisper_audiohook);
+		ast_audiohook_unlock(&csth.whisper_audiohook);
+		ast_audiohook_destroy(&csth.whisper_audiohook);
+	}
+
+	ast_audiohook_lock(&csth.spy_audiohook);
+	ast_audiohook_detach(&csth.spy_audiohook);
+	ast_audiohook_unlock(&csth.spy_audiohook);
+	ast_audiohook_destroy(&csth.spy_audiohook);
 	
 	if (option_verbose >= 2)
 		ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name);

Modified: team/file/ah/apps/app_mixmonitor.c
URL: http://svn.digium.com/view/asterisk/team/file/ah/apps/app_mixmonitor.c?view=diff&rev=59060&r1=59059&r2=59060
==============================================================================
--- team/file/ah/apps/app_mixmonitor.c (original)
+++ team/file/ah/apps/app_mixmonitor.c Mon Mar 19 22:44:56 2007
@@ -152,7 +152,7 @@
 	if (option_verbose > 1)
 		ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name);
 	
-	ast_mutex_lock(&mixmonitor->audiohook.lock);
+	ast_audiohook_lock(&mixmonitor->audiohook);
 
 	while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
 		struct ast_frame *fr = NULL;
@@ -191,9 +191,7 @@
 	}
 
 	ast_audiohook_detach(&mixmonitor->audiohook);
-
-	ast_mutex_unlock(&mixmonitor->audiohook.lock);
-
+	ast_audiohook_unlock(&mixmonitor->audiohook);
 	ast_audiohook_destroy(&mixmonitor->audiohook);
 
 	if (option_verbose > 1)

Modified: team/file/ah/include/asterisk/audiohook.h
URL: http://svn.digium.com/view/asterisk/team/file/ah/include/asterisk/audiohook.h?view=diff&rev=59060&r1=59059&r2=59060
==============================================================================
--- team/file/ah/include/asterisk/audiohook.h (original)
+++ team/file/ah/include/asterisk/audiohook.h Mon Mar 19 22:44:56 2007
@@ -133,6 +133,22 @@
  */
 void ast_audiohook_trigger_wait(struct ast_audiohook *audiohook);
 
+/*! \brief Lock an audiohook
+ * \param audiohook Audiohook structure
+ */
+static inline int ast_audiohook_lock(struct ast_audiohook *audiohook)
+{
+	return ast_mutex_lock(&audiohook->lock);
+}
+
+/*! \brief Unlock an audiohook
+ * \param audiohook Audiohook structure
+ */
+static inline int ast_audiohook_unlock(struct ast_audiohook *audiohook)
+{
+	return ast_mutex_unlock(&audiohook->lock);
+}
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/file/ah/main/audiohook.c
URL: http://svn.digium.com/view/asterisk/team/file/ah/main/audiohook.c?view=diff&rev=59060&r1=59059&r2=59060
==============================================================================
--- team/file/ah/main/audiohook.c (original)
+++ team/file/ah/main/audiohook.c Mon Mar 19 22:44:56 2007
@@ -301,31 +301,32 @@
 
 	/* Drop any spies */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
-		ast_mutex_lock(&audiohook->lock);
+		ast_audiohook_lock(audiohook);
 		AST_LIST_REMOVE_CURRENT(&audiohook_list->spy_list, list);
 		audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
 		ast_cond_signal(&audiohook->trigger);
-		ast_mutex_unlock(&audiohook->lock);
+		ast_audiohook_unlock(audiohook);
 	}
 	AST_LIST_TRAVERSE_SAFE_END
 
 	/* Drop any whispering sources */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
-		ast_mutex_lock(&audiohook->lock);
+		ast_audiohook_lock(audiohook);
 		AST_LIST_REMOVE_CURRENT(&audiohook_list->whisper_list, list);
 		audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
 		ast_cond_signal(&audiohook->trigger);
-		ast_mutex_unlock(&audiohook->lock);
+		ast_audiohook_unlock(audiohook);
 	}
 	AST_LIST_TRAVERSE_SAFE_END
 
 	/* Drop any manipulaters */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
+		ast_audiohook_lock(audiohook);
 		ast_mutex_lock(&audiohook->lock);
 		AST_LIST_REMOVE_CURRENT(&audiohook_list->manipulate_list, list);
 		audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
 		ast_cond_signal(&audiohook->trigger);
-		ast_mutex_unlock(&audiohook->lock);
+		ast_audiohook_unlock(audiohook);
 	}
 	AST_LIST_TRAVERSE_SAFE_END
 
@@ -352,9 +353,10 @@
 struct ast_frame *ast_audiohook_write_list(struct ast_audiohook_list *audiohook_list, enum ast_audiohook_direction direction, struct ast_frame *frame)
 {
 	struct ast_audiohook_translate *in_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->in_translate[0] : &audiohook_list->in_translate[1]);
-//	struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
+	struct ast_audiohook_translate *out_translate = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook_list->out_translate[0] : &audiohook_list->out_translate[1]);
 	struct ast_frame *start_frame = frame, *middle_frame = frame, *end_frame = frame;
 	struct ast_audiohook *audiohook = NULL;
+	int samples = frame->samples;
 	
 	/* If the frame coming in is not signed linear we have to send it through the in_translate path */
 	if (frame->subclass != AST_FORMAT_SLINEAR) {
@@ -371,65 +373,93 @@
 
 	/* Queue up signed linear frame to each spy */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->spy_list, audiohook, list) {
-		ast_mutex_lock(&audiohook->lock);
+		ast_audiohook_lock(audiohook);
 		if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
 			AST_LIST_REMOVE_CURRENT(&audiohook_list->spy_list, list);
 			audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
 			ast_cond_signal(&audiohook->trigger);
-			ast_mutex_unlock(&audiohook->lock);
+			ast_audiohook_unlock(audiohook);
 			continue;
 		}
 		ast_audiohook_write_frame(audiohook, direction, middle_frame);
-		ast_mutex_unlock(&audiohook->lock);
+		ast_audiohook_unlock(audiohook);
 	}
 	AST_LIST_TRAVERSE_SAFE_END
 
 	/* If this frame is being written out to the channel then we need to use whisper sources */
 	if (direction == AST_AUDIOHOOK_DIRECTION_WRITE && !AST_LIST_EMPTY(&audiohook_list->whisper_list)) {
-		short read_buf[middle_frame->samples], combine_buf[middle_frame->samples];
-		/* Ensure our combined buffer is blank to begin with */
+		int i = 0;
+		short read_buf[samples], combine_buf[samples], *data1 = NULL, *data2 = NULL;
 		memset(&combine_buf, 0, sizeof(combine_buf));
 		AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->whisper_list, audiohook, list) {
-			ast_mutex_lock(&audiohook->lock);
+			ast_audiohook_lock(audiohook);
 			if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
 				AST_LIST_REMOVE_CURRENT(&audiohook_list->whisper_list, list);
 				audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
 				ast_cond_signal(&audiohook->trigger);
-				ast_mutex_unlock(&audiohook->lock);
+				ast_audiohook_unlock(audiohook);
 				continue;
 			}
-			if ((ast_slinfactory_available(&audiohook->write_factory) >= middle_frame->samples) && ast_slinfactory_read(&audiohook->write_factory, read_buf, frame->samples)) {
-			}
-			ast_mutex_unlock(&audiohook->lock);
+			if (ast_slinfactory_available(&audiohook->write_factory) >= samples && ast_slinfactory_read(&audiohook->write_factory, read_buf, samples)) {
+				/* Take audio from this whisper source and combine it into our main buffer */
+				for (i = 0, data1 = combine_buf, data2 = read_buf; i < samples; i++, data1++, data2++)
+					ast_slinear_saturated_add(data1, data2);
+			}
+			ast_audiohook_unlock(audiohook);
 		}
 		AST_LIST_TRAVERSE_SAFE_END
-		/* Now that we are done with the whisper sources, we take their combined values and combine them into our source frame */
+		/* We take all of the combined whisper sources and combine them into the audio being written out */
+		for (i = 0, data1 = middle_frame->data, data2 = combine_buf; i < samples; i++, data1++, data2++)
+			ast_slinear_saturated_add(data1, data2);
 		end_frame = middle_frame;
 	}
 
 	/* Pass off frame to manipulate audiohooks */
 	if (!AST_LIST_EMPTY(&audiohook_list->manipulate_list)) {
 		AST_LIST_TRAVERSE_SAFE_BEGIN(&audiohook_list->manipulate_list, audiohook, list) {
-			ast_mutex_lock(&audiohook->lock);
+			ast_audiohook_lock(audiohook);
 			if (audiohook->status != AST_AUDIOHOOK_STATUS_RUNNING) {
 				AST_LIST_REMOVE_CURRENT(&audiohook_list->manipulate_list, list);
 				audiohook->status = AST_AUDIOHOOK_STATUS_DONE;
 				ast_cond_signal(&audiohook->trigger);
-				ast_mutex_unlock(&audiohook->lock);
+				ast_audiohook_unlock(audiohook);
 				continue;
 			}
-			ast_mutex_unlock(&audiohook->lock);
+			ast_audiohook_unlock(audiohook);
 		}
 		AST_LIST_TRAVERSE_SAFE_END
 		end_frame = middle_frame;
 	}
 
-	if (start_frame != end_frame) {
-		/* We are ending with a different frame then we started with... probably have to transcode */
-	}
-
-	/* We never ever need to keep the middle frame */
-	ast_frfree(middle_frame);
+	/* Now we figure out what to do with our end frame (whether to transcode or not) */
+	if (middle_frame == end_frame) {
+		/* Middle frame was modified and became the end frame... let's see if we need to transcode */
+		if (end_frame->subclass != start_frame->subclass) {
+			if (out_translate->format != start_frame->subclass) {
+				if (out_translate->trans_pvt)
+					ast_translator_free_path(out_translate->trans_pvt);
+				if (!(out_translate->trans_pvt = ast_translator_build_path(start_frame->subclass, AST_FORMAT_SLINEAR))) {
+					/* We can't transcode this... drop our middle frame and return the original */
+					ast_frfree(middle_frame);
+					return start_frame;
+				}
+				out_translate->format = start_frame->subclass;
+			}
+			/* Transcode from our middle (signed linear) frame to new format of the frame that came in */
+			if (!(end_frame = ast_translate(out_translate->trans_pvt, middle_frame, 0))) {
+				/* Failed to transcode the frame... drop it and return the original */
+				ast_frfree(middle_frame);
+				return start_frame;
+			}
+			/* Here's the scoop... middle frame is no longer of use to us */
+			ast_frfree(middle_frame);
+		}
+		/* Yay let's rid ourselves of the start frame */
+		ast_frfree(start_frame);
+	} else {
+		/* No frame was modified, we can just drop our middle frame and pass the frame we got in out */
+		ast_frfree(middle_frame);
+	}
 
 	return end_frame;
 }



More information about the asterisk-commits mailing list