[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