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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sat Dec 29 11:46:01 CST 2007


Author: russell
Date: Sat Dec 29 11:46:00 2007
New Revision: 95363

URL: http://svn.digium.com/view/asterisk?view=rev&rev=95363
Log:
And now, attempt number 3 at an approach for audio handling between asterisk
and portaudio.  This approach is _much_ simpler, and just uses the blocking
read/write mode from portaudio.  I wish I had realized that this was available
a long time ago.  It fits the Asterisk model much better, and appears to be
working better than my previous couple of methods ...

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=95363&r1=95362&r2=95363
==============================================================================
--- team/russell/chan_console/channels/chan_console.c (original)
+++ team/russell/chan_console/channels/chan_console.c Sat Dec 29 11:46:00 2007
@@ -48,14 +48,11 @@
 
 /*** MODULEINFO
 	<depend>portaudio</depend>
-	<depend>jack</depend>
  ***/
 
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
-#include <jack/ringbuffer.h>
 
 #include <portaudio.h>
 
@@ -146,13 +143,10 @@
 	unsigned int overridecontext:1;
 	/*! Lock for this struct */
 	ast_mutex_t lock;
-	jack_ringbuffer_t *input_rb;
-	jack_ringbuffer_t *output_rb;
-	struct ast_smoother *smoother;
-	int fds[2];
+	pthread_t thread;
 } console_pvt = {
 	.lock = AST_MUTEX_INIT_VALUE,
-	.fds = { -1, -1 },
+	.thread = AST_PTHREADT_NULL,
 };
 
 /*! Global jitterbuffer configuration - by default, jb is disabled */
@@ -195,9 +189,35 @@
 	.fixup = console_fixup,
 };
 
-static int console_callback(const void *input, void *output,
-	unsigned long frame_count, const PaStreamCallbackTimeInfo *time_info,
-	PaStreamCallbackFlags flags, void *userData);
+static void *stream_monitor(void *data)
+{
+	struct console_pvt *pvt = data;
+	char buf[NUM_SAMPLES * sizeof(int16_t)];
+	PaError res;
+
+	for (;;) {
+		pthread_testcancel();
+
+		res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
+
+		pthread_testcancel();
+
+		if (res == paNoError) {
+			struct ast_frame f = {
+				.frametype = AST_FRAME_VOICE,
+				.subclass = AST_FORMAT_SLINEAR,
+				.src = "console_stream_monitor",
+				.data = buf,
+				.datalen = sizeof(buf),
+				.samples = sizeof(buf) / sizeof(int16_t),
+			};
+
+			ast_queue_frame(pvt->owner, &f);
+		}
+	}
+
+	return NULL;
+}
 
 static int start_stream(struct console_pvt *pvt)
 {
@@ -213,7 +233,7 @@
 	ast_debug(1, "Starting stream\n");
 
 	res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS, 
-		paInt16, SAMPLE_RATE, NUM_SAMPLES, console_callback, NULL);
+		paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
 	if (res != paNoError) {
 		ast_log(LOG_WARNING, "Failed to open default audio device - (%d) %s\n",
 			res, Pa_GetErrorText(res));
@@ -226,6 +246,12 @@
 		ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
 			res, Pa_GetErrorText(res));
 		ret_val = -1;
+		goto return_unlock;
+	}
+
+	if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
+		ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
+		ret_val = -1;
 	}
 
 return_unlock:
@@ -238,6 +264,10 @@
 {
 	if (!pvt->streamstate)
 		return 0;
+
+	pthread_cancel(pvt->thread);
+	pthread_kill(pvt->thread, SIGURG);
+	pthread_join(pvt->thread, NULL);
 
 	ast_mutex_lock(&pvt->lock);
 	Pa_AbortStream(pvt->stream);
@@ -264,7 +294,6 @@
 	chan->readformat = AST_FORMAT_SLINEAR;
 	chan->writeformat = AST_FORMAT_SLINEAR;
 	chan->tech_pvt = pvt;
-	chan->fds[0] = pvt->fds[0];
 
 	pvt->owner = chan;
 
@@ -359,44 +388,9 @@
 
 static struct ast_frame *console_read(struct ast_channel *chan)
 {
-	struct console_pvt *pvt = chan->tech_pvt;
-	struct pollfd pfd;
-	int res;
-	char buf[1024];
-	struct ast_frame *fr, *ret_fr;
-	struct ast_frame f = {
-		.frametype = AST_FRAME_VOICE,
-		.subclass = AST_FORMAT_SLINEAR,
-		.src = "console_read",
-		.data = buf,
-	};
-
-	pfd.fd = pvt->fds[0];
-	pfd.events = POLLIN;
-	pfd.revents = 0;
-	while (poll(&pfd, 1, 0) == 1) {
-		int blah;
-		read(pvt->fds[0], &blah, sizeof(blah));
-	}
-
-	while ((res = jack_ringbuffer_read(pvt->input_rb, buf, sizeof(buf))) > 0) {
-		f.datalen = res;
-		f.samples = res / sizeof(int16_t);
-
-		ast_smoother_feed(pvt->smoother, &f);
-	}
-
-	/* Read one frame to return, and queue up any others on the channel just
-	 * in case we have run behind a bit. */
-
-	ret_fr = ast_smoother_read(pvt->smoother);
-
-	while ((fr = ast_smoother_read(pvt->smoother))) {
-		ast_queue_frame(chan, fr);
-		ast_frfree(fr);
-	}
-
-	return ret_fr ? ret_fr : &ast_null_frame;
+	ast_debug(1, "I should not be called ...\n");
+
+	return &ast_null_frame;
 }
 
 static int console_call(struct ast_channel *c, char *dest, int timeout)
@@ -430,18 +424,9 @@
 
 static int console_write(struct ast_channel *chan, struct ast_frame *f)
 {
-	struct ast_frame *fr = ast_frdup(f);
-	struct console_pvt *pvt = &console_pvt;
-	int res;
-
-	if (!fr)
-		return -1;
-
-	res = jack_ringbuffer_write(pvt->output_rb, fr->data, fr->datalen);
-	if (res != fr->datalen) {
-		/* ast_log(LOG_WARNING, "Failed to write %d bytes to the output ringbuffer\n",
-			fr->datalen); */
-	}
+	struct console_pvt *pvt = &console_pvt;
+
+	Pa_WriteStream(pvt->stream, f->data, f->samples);
 
 	return 0;
 }
@@ -489,61 +474,7 @@
 	return 0;
 }
 
-static int handle_output(struct console_pvt *pvt, void *output, unsigned long frame_count)
-{
-	size_t res;
-	unsigned long total_bytes = frame_count * 2;
-
-	res = jack_ringbuffer_read_space(pvt->output_rb);
-	if (res < total_bytes) {
-		/* ast_debug(1, "Missed a frame\n"); */
-		memset(output, 0, total_bytes);
-		return paContinue;
-	}
-
-	jack_ringbuffer_read(pvt->output_rb, output, frame_count * 2);
-
-	return paContinue;
-}
-
-static int handle_input(struct console_pvt *pvt, const void *input, unsigned long frame_count)
-{
-	char buf[frame_count * 2];
-	int res;
-	int blah = 0;
-
-	if (pvt->muted) {
-		memset(buf, 0, sizeof(buf));
-		input = buf;
-	}
-	
-	res = jack_ringbuffer_write(pvt->input_rb, input, frame_count * 2);
-	if (res != frame_count * 2) {
-		/* ast_log(LOG_WARNING, "Wanted to write %ld bytes into the input ringbuffer, "
-			"but only wrote %d\n", frame_count * 2, res); */
-	}
-	
-	write(pvt->fds[1], &blah, sizeof(blah));
-
-	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;
-	struct console_pvt *pvt = &console_pvt;
-
-	if (output)
-		res = handle_output(pvt, output, frame_count);
-	if (res != paAbort && input)
-		res = handle_input(pvt, input, frame_count);
-
-	return res;
-}
-
-/*
+/*!
  * split a string in extension-context, returns pointers to malloc'ed
  * strings.
  * If we do not have 'overridecontext' then the last @ is considered as
@@ -551,6 +482,8 @@
  * This is usually not very necessary as you can play with the dialplan,
  * and it is nice not to need it because you have '@' in SIP addresses.
  * Return value is the buffer address.
+ *
+ * \note came from chan_oss
  */
 static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
 {
@@ -892,8 +825,11 @@
 	AST_CLI_DEFINE(cli_list_devices, "List available devices"),
 };
 
-static void set_pvt_defaults(struct console_pvt *pvt)
-{
+static void set_pvt_defaults(struct console_pvt *pvt, int reload)
+{
+	if (!reload)
+		ast_string_field_set(pvt, name, "default");
+
 	ast_string_field_set(pvt, mohinterpret, "default");
 	ast_string_field_set(pvt, context, "default");
 	ast_string_field_set(pvt, exten, "s");
@@ -924,13 +860,7 @@
 
 	ast_mutex_lock(&pvt->lock);
 
-	if (!reload) {
-		if (ast_string_field_init(pvt, 32))
-			goto return_unlock;
-		ast_string_field_set(pvt, name, "default");
-	}
-
-	set_pvt_defaults(pvt);
+	set_pvt_defaults(pvt, reload);
 
 	if (!(cfg = ast_config_load(config_file, config_flags))) {
 		ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
@@ -975,65 +905,22 @@
 
 static int init_pvt(struct console_pvt *pvt)
 {
+	if (ast_string_field_init(pvt, 32))
+		return -1;
+	
 	if (ast_mutex_init(&pvt->lock)) {
 		ast_log(LOG_ERROR, "Failed to initialize mutex\n");
 		return -1;
 	}
 
-	if (!(pvt->smoother = ast_smoother_new(320))) { /* 20ms frames */
-		ast_log(LOG_ERROR, "Failed to create smoother\n");
-		return -1;
-	}
-
-	if (!(pvt->input_rb = jack_ringbuffer_create(RINGBUFFER_SIZE))) {
-		ast_log(LOG_ERROR, "Failed to create input ringbuffer of size %d\n",
-			RINGBUFFER_SIZE);
-		return -1;
-	}
-
-	if (!(pvt->output_rb = jack_ringbuffer_create(RINGBUFFER_SIZE))) {
-		ast_log(LOG_ERROR, "Failed to create output ringbuffer of size %d\n",
-			RINGBUFFER_SIZE);
-		return -1;
-	}
-
-	if (pipe(pvt->fds)) {
-		ast_log(LOG_ERROR, "Unable to create alert pipe: %s\n", strerror(errno));
-		return -1;
-	}
-
 	return 0;
 }
 
 static void destroy_pvt(struct console_pvt *pvt)
 {
-	int i;
-
 	ast_string_field_free_memory(pvt);
 	
 	ast_mutex_destroy(&pvt->lock);
-
-	if (pvt->smoother) {
-		ast_smoother_free(pvt->smoother);
-		pvt->smoother = NULL;
-	}
-
-	if (pvt->input_rb) {
-		jack_ringbuffer_free(pvt->input_rb);
-		pvt->input_rb = NULL;
-	}
-	
-	if (pvt->output_rb) {
-		jack_ringbuffer_free(pvt->output_rb);
-		pvt->output_rb = NULL;
-	}
-
-	for (i = 0; i < 2; i++) {
-		if (pvt->fds[i] > -1) {
-			close(pvt->fds[i]);
-			pvt->fds[i] = -1;
-		}
-	}
 }
 
 static int unload_module(void)




More information about the asterisk-commits mailing list