[asterisk-commits] russell: branch russell/chan_console r49057 - /team/russell/chan_console/chan...

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Fri Dec 29 06:25:54 MST 2006


Author: russell
Date: Fri Dec 29 07:25:54 2006
New Revision: 49057

URL: http://svn.digium.com/view/asterisk?view=rev&rev=49057
Log:
Split the portaudio callback into a couple of different functions.

Modified:
    team/russell/chan_console/channels/chan_console.c

Modified: team/russell/chan_console/channels/chan_console.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_console/channels/chan_console.c?view=diff&rev=49057&r1=49056&r2=49057
==============================================================================
--- team/russell/chan_console/channels/chan_console.c (original)
+++ team/russell/chan_console/channels/chan_console.c Fri Dec 29 07:25:54 2006
@@ -119,8 +119,11 @@
 	char write_buf[NUM_SAMPLES * 2];
 	/*! The index for the next write into write_buf */
 	unsigned int write_dst;
-	/*! The current index into the sounds array */
-	int cur_sound;
+	/*! The current index into the sounds array, -1 means none */
+	int cursound;
+	/*! The number of samples sent for the current sound, mod the total number
+	 *  of samples for the sound plus trailing silence. */
+	unsigned int sampsent;
 	/*! On-hook = 0, Off-hook = 1 */
 	unsigned int hookstate:1;
 	/*! Ignore context in the console dial CLI command */
@@ -137,7 +140,7 @@
 } pvt = {
 	.name = "default",
 	.lock = AST_MUTEX_INIT_VALUE,
-	.cur_sound = -1,
+	.cursound = -1,
 };
 
 /*! Global jitterbuffer configuration - by default, jb is disabled */
@@ -305,7 +308,7 @@
 	ast_verbose(" --- <(\"<) --- Hangup on Console --- (>\")> ---\n");
 
 	pvt.hookstate = 0;
-	pvt.cur_sound = -1;
+	pvt.cursound = -1;
 	c->tech_pvt = NULL;
 	pvt.owner = NULL;
 
@@ -331,7 +334,7 @@
 
 	ast_mutex_lock(&pvt.lock);
 	ast_setstate(c, AST_STATE_UP);
-	pvt.cur_sound = -1;
+	pvt.cursound = -1;
 	res = start_stream();
 	ast_mutex_unlock(&pvt.lock);
 
@@ -413,84 +416,96 @@
 	return 0;
 }
 
+static int handle_output(void *output, unsigned long frame_count)
+{
+	unsigned int src = 0;
+	unsigned int num_samples;
+	struct ast_frame *fr;
+
+	ast_mutex_lock(&pvt.lock);
+	if (pvt.write_dst) {
+		num_samples = (pvt.write_dst * 2) > frame_count ? pvt.write_dst * 2 : frame_count;
+		memcpy(output, &pvt.write_buf, num_samples * 2);
+		pvt.write_dst -= num_samples * 2;
+		src += num_samples * 2;
+		frame_count -= num_samples;
+	}
+	while (frame_count) { 
+		while (!(fr = AST_LIST_REMOVE_HEAD(&pvt.frames, frame_list))) {
+			ast_cond_wait(&pvt.cond, &pvt.lock);
+			if (!pvt.hookstate) {
+				if (fr)
+					ast_frfree(fr);
+				ast_mutex_unlock(&pvt.lock);
+				pvt.incallback = 0;
+				return paAbort;	
+			}
+		}
+		num_samples = fr->samples > frame_count ? frame_count : fr->samples;
+		memcpy(output + src, fr->data, num_samples * 2);
+		frame_count -= num_samples;
+		if (num_samples != fr->samples) {
+			memcpy(&pvt.write_buf + pvt.write_dst, fr->data + num_samples * 2, (fr->samples - num_samples) * 2);
+			pvt.write_dst += (fr->samples - num_samples) * 2;
+		}
+		ast_frfree(fr);
+	}
+	ast_mutex_unlock(&pvt.lock);
+
+	return paContinue;
+}
+
+static int handle_input(const void *input, unsigned long frame_count)
+{
+	struct ast_frame *fr = &pvt.fr;
+	unsigned int count = 0;
+
+	memset(fr, 0, sizeof(*fr));
+	memset(pvt.read_buf, 0, NUM_SAMPLES * 2 + AST_FRIENDLY_OFFSET);
+	fr->data = pvt.read_buf + AST_FRIENDLY_OFFSET;
+	fr->offset = AST_FRIENDLY_OFFSET;
+	fr->frametype = AST_FRAME_VOICE;
+	fr->subclass = AST_FORMAT_SLINEAR;
+	fr->samples = NUM_SAMPLES;
+	fr->datalen = NUM_SAMPLES * 2;
+	memcpy(fr->data, input, NUM_SAMPLES * 2);
+
+	/* If the channel is in the process of being hung up, then it will be
+	 * locked while calling the console_hangup callback, and that could be
+	 * waiting to stop the audio stream, which will block until this
+	 * function returns.  Thus, locking the channel could result in a
+	 * deadlock.  So, we use the fact that the locks are recursive to test
+	 * locking the channel before queueing the frame. */
+	while (ast_channel_trylock(pvt.owner)) {
+		if (++count == 100) {
+			ast_log(LOG_DEBUG, "Dropping frame\n");
+			pvt.incallback = 0;
+			return paContinue;	
+		}
+		usleep(10);
+	}
+	ast_queue_frame(pvt.owner, fr);
+	ast_channel_unlock(pvt.owner);
+
+	return paContinue;
+}
+
 static int console_callback(const void *input, void *output,
 	unsigned long frame_count, const PaStreamCallbackTimeInfo *time_info,
 	PaStreamCallbackFlags flags, void *userData)
 {
+	int res = paContinue;
+
 	pvt.incallback = 1;
 
-	if (output) {
-		unsigned int src = 0;
-		unsigned int num_samples;
-		struct ast_frame *fr;
-		ast_mutex_lock(&pvt.lock);
-		if (pvt.write_dst) {
-			num_samples = (pvt.write_dst * 2) > frame_count ? pvt.write_dst * 2 : frame_count;
-			memcpy(output, &pvt.write_buf, num_samples * 2);
-			pvt.write_dst -= num_samples * 2;
-			src += num_samples * 2;
-			frame_count -= num_samples;
-		}
-		while (frame_count) { 
-			while (!(fr = AST_LIST_REMOVE_HEAD(&pvt.frames, frame_list))) {
-				ast_cond_wait(&pvt.cond, &pvt.lock);
-				if (!pvt.hookstate) {
-					if (fr)
-						ast_frfree(fr);
-					ast_mutex_unlock(&pvt.lock);
-					pvt.incallback = 0;
-					return paAbort;	
-				}
-			}
-			num_samples = fr->samples > frame_count ? frame_count : fr->samples;
-			memcpy(output + src, fr->data, num_samples * 2);
-			frame_count -= num_samples;
-			if (num_samples != fr->samples) {
-				memcpy(&pvt.write_buf + pvt.write_dst, fr->data + num_samples * 2, (fr->samples - num_samples) * 2);
-				pvt.write_dst += (fr->samples - num_samples) * 2;
-			}
-			ast_frfree(fr);
-		}
-		ast_mutex_unlock(&pvt.lock);
-
-		if (frame_count) {
-			ast_log(LOG_WARNING, "console_callback didn't get %lu of the samples it wanted :(\n", frame_count);
-			memset(output + src, 0, frame_count * 2);
-		}
-	}
-
-	if (input) {
-		struct ast_frame *fr = &pvt.fr;
-		unsigned int count = 0;
-		memset(fr, 0, sizeof(*fr));
-		memset(pvt.read_buf, 0, NUM_SAMPLES * 2 + AST_FRIENDLY_OFFSET);
-		fr->data = pvt.read_buf + AST_FRIENDLY_OFFSET;
-		fr->offset = AST_FRIENDLY_OFFSET;
-		fr->frametype = AST_FRAME_VOICE;
-		fr->subclass = AST_FORMAT_SLINEAR;
-		fr->samples = NUM_SAMPLES;
-		fr->datalen = NUM_SAMPLES * 2;
-		memcpy(fr->data, input, NUM_SAMPLES * 2);
-		/* If the channel is in the process of being hung up, then it will be
-		 * locked while calling the console_hangup callback, and that could be
-		 * waiting to stop the audio stream, which will block until this
-		 * function returns.  Thus, locking the channel could result in a
-		 * deadlock.  So, we use the fact that the locks are recursive to test
-		 * locking the channel before queueing the frame. */
-		while (ast_channel_trylock(pvt.owner)) {
-			if (++count == 100) {
-				ast_log(LOG_DEBUG, "Dropping frame\n");
-				pvt.incallback = 0;
-				return paContinue;	
-			}
-			usleep(10);
-		}
-		ast_queue_frame(pvt.owner, fr);
-		ast_channel_unlock(pvt.owner);
-	}
+	if (output)
+		res = handle_output(output, frame_count);
+	if (res != paAbort && input)
+		res = handle_input(input, frame_count);
 
 	pvt.incallback = 0;
-	return paContinue;
+
+	return res;
 }
 
 /*
@@ -594,7 +609,7 @@
 		return CLI_FAILURE;
 	}
 	pvt.hookstate = 0;
-	pvt.cur_sound = -1;
+	pvt.cursound = -1;
 	if (pvt.owner)
 		ast_queue_hangup(pvt.owner);
 



More information about the asterisk-commits mailing list