[asterisk-commits] russell: branch russell/jack r96774 - /team/russell/jack/apps/app_jack.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Jan 6 16:54:50 CST 2008


Author: russell
Date: Sun Jan  6 16:54:50 2008
New Revision: 96774

URL: http://svn.digium.com/view/asterisk?view=rev&rev=96774
Log:
Theoretically finish the first version of JACK_HOOK.  I have not tested it
yet, though.  But, I ran the Jack app and that still works.

Modified:
    team/russell/jack/apps/app_jack.c

Modified: team/russell/jack/apps/app_jack.c
URL: http://svn.digium.com/view/asterisk/team/russell/jack/apps/app_jack.c?view=diff&rev=96774&r1=96773&r2=96774
==============================================================================
--- team/russell/jack/apps/app_jack.c (original)
+++ team/russell/jack/apps/app_jack.c Sun Jan  6 16:54:50 2008
@@ -96,6 +96,9 @@
 	void *input_resampler;
 	double input_resample_factor;
 	unsigned int stop:1;
+	unsigned int has_audiohook:1;
+	/*! Only used with JACK_HOOK */
+	struct ast_audiohook audiohook;
 };
 
 static const struct {
@@ -335,6 +338,9 @@
 		jack_data->input_resampler = NULL;
 	}
 
+	if (jack_data->has_audiohook)
+		ast_audiohook_destroy(&jack_data->audiohook);
+
 	ast_string_field_free_memory(jack_data);
 
 	ast_free(jack_data);
@@ -533,7 +539,8 @@
  * Read data from the input ringbuffer, which is the properly resampled audio
  * that was read from the jack input port.  Write it to the channel in 20 ms frames.
  */
-static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data)
+static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data,
+	struct ast_frame *out_frame)
 {	
 	short buf[160];
 	struct ast_frame f = {
@@ -546,19 +553,33 @@
 	};
 
 	for (;;) {
-		size_t res;
+		size_t res, read_len;
+		char *read_buf;
+
+		read_len = out_frame ? out_frame->datalen : sizeof(buf);
+		read_buf = out_frame ? out_frame->data : buf;
 
 		res = jack_ringbuffer_read_space(jack_data->input_rb);
 
-		if (res < sizeof(buf)) {
+		if (res < read_len) {
 			/* Not enough data ready for another frame, move on ... */
+			if (out_frame) {
+				ast_debug(1, "Sending an empty frame for the JACK_HOOK\n");
+				memset(out_frame->data, 0, out_frame->datalen);
+			}
 			break;
 		}
 
-		res = jack_ringbuffer_read(jack_data->input_rb, (char *) buf, sizeof(buf));
-
-		if (res < sizeof(buf)) {
+		res = jack_ringbuffer_read(jack_data->input_rb, (char *) read_buf, read_len);
+
+		if (res < read_len) {
 			ast_log(LOG_ERROR, "Error reading from ringbuffer, even though it said there was enough data\n");
+			break;
+		}
+
+		if (out_frame) {
+			/* If an output frame was provided, then we just want to fill up the
+			 * buffer in that frame and return. */
 			break;
 		}
 
@@ -656,11 +677,9 @@
 
 	args.options = data;
 
-	if (!ast_strlen_zero(args.options)) {
-		if (handle_options(jack_data, args.options)) {
-			destroy_jack_data(jack_data);
-			return -1;
-		}
+	if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options)) {
+		destroy_jack_data(jack_data);
+		return -1;
 	}
 
 	if (init_jack_data(chan, jack_data)) {
@@ -702,7 +721,7 @@
 
 		ast_frfree(f);
 
-		handle_jack_audio(chan, jack_data);
+		handle_jack_audio(chan, jack_data, NULL);
 	}
 
 	jack_data = destroy_jack_data(jack_data);
@@ -712,7 +731,9 @@
 
 static void jack_hook_ds_destroy(void *data)
 {
-
+	struct jack_data *jack_data = data;
+
+	destroy_jack_data(jack_data);
 }
 
 static const struct ast_datastore_info jack_hook_ds_info = {
@@ -720,16 +741,103 @@
 	.destroy = jack_hook_ds_destroy,
 };
 
+static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, 
+	struct ast_frame *frame, enum ast_audiohook_direction direction)
+{
+	struct ast_datastore *datastore;
+	struct jack_data *jack_data;
+
+	if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
+		return 0;
+
+	if (direction != AST_AUDIOHOOK_DIRECTION_READ)
+		return 0;
+
+	if (frame->frametype != AST_FRAME_VOICE)
+		return 0;
+
+	ast_channel_lock(chan);
+
+	if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
+		ast_log(LOG_ERROR, "JACK_HOOK datastore not found for '%s'\n", chan->name);
+		ast_channel_unlock(chan);
+		return -1;
+	}
+
+	jack_data = datastore->data;
+
+	queue_voice_frame(jack_data, frame);
+
+	handle_jack_audio(chan, jack_data, frame);
+
+	ast_channel_unlock(chan);
+
+	return 0;
+}
+
 static int enable_jack_hook(struct ast_channel *chan, char *data)
 {
-	/* XXX */
+	struct ast_datastore *datastore;
+	struct jack_data *jack_data = NULL;
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(mode);
+		AST_APP_ARG(options);
+	);
+
+	AST_STANDARD_APP_ARGS(args, data);
+
+	ast_channel_lock(chan);
+
+	if ((datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
+		ast_log(LOG_ERROR, "JACK_HOOK already enabled for '%s'\n", chan->name);
+		goto return_error;
+	}
+
+	if (strcasecmp(args.mode, "manipulate")) {
+		ast_log(LOG_ERROR, "'%s' is not a supported mode.  Only manipulate is supported.\n", 
+			args.mode);
+		goto return_error;
+	}
+
+	if (!(jack_data = jack_data_alloc()))
+		goto return_error;
+
+	if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options))
+		goto return_error;
+
+	if (init_jack_data(chan, jack_data))
+		goto return_error;
+
+	if (!(datastore = ast_channel_datastore_alloc(&jack_hook_ds_info, NULL)))
+		goto return_error;
+
+	jack_data->has_audiohook = 1;
+	ast_audiohook_init(&jack_data->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "JACK_HOOK");
+	jack_data->audiohook.manipulate_callback = jack_hook_callback;
+
+	datastore->data = jack_data;
+
+	if (ast_audiohook_attach(chan, &jack_data->audiohook))
+		goto return_error;
+
+	if (ast_channel_datastore_add(chan, datastore))
+		goto return_error;
 
 	return 0;
+
+return_error:
+	ast_channel_unlock(chan);
+
+	if (jack_data)
+		destroy_jack_data(jack_data);
+
+	return -1;
 }
 
 static int disable_jack_hook(struct ast_channel *chan)
 {
 	struct ast_datastore *datastore;
+	struct jack_data *jack_data;
 
 	ast_channel_lock(chan);
 
@@ -740,6 +848,9 @@
 	}
 
 	ast_channel_datastore_remove(chan, datastore);
+
+	jack_data = datastore->data;
+	ast_audiohook_detach(&jack_data->audiohook);
 
 	/* Keep the channel locked while we destroy the datastore, so that we can
 	 * ensure that all of the jack stuff is stopped just in case another frame




More information about the asterisk-commits mailing list