Fix build WRT ast_str_opaque
[asterisk/asterisk.git] / apps / app_jack.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007 - 2008, Russell Bryant
5  *
6  * Russell Bryant <russell@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Jack Application
22  *
23  * \author Russell Bryant <russell@digium.com>
24  *
25  * This is an application to connect an Asterisk channel to an input
26  * and output jack port so that the audio can be processed through
27  * another application, or to play audio from another application.
28  *
29  * \arg http://www.jackaudio.org/
30  *
31  * \note To install libresample, check it out of the following repository:
32  * <code>$ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk</code>
33  *
34  * \ingroup applications
35  */
36
37 /*** MODULEINFO
38         <depend>jack</depend>
39         <depend>resample</depend>
40  ***/
41
42 #include "asterisk.h"
43
44 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
45
46 #include <limits.h>
47
48 #include <jack/jack.h>
49 #include <jack/ringbuffer.h>
50
51 #include <libresample.h>
52
53 #include "asterisk/module.h"
54 #include "asterisk/channel.h"
55 #include "asterisk/strings.h"
56 #include "asterisk/lock.h"
57 #include "asterisk/app.h"
58 #include "asterisk/pbx.h"
59 #include "asterisk/audiohook.h"
60
61 #define RESAMPLE_QUALITY 1
62
63 #define RINGBUFFER_SIZE 16384
64
65 /*! \brief Common options between the Jack() app and JACK_HOOK() function */
66 #define COMMON_OPTIONS \
67 "    s(<name>) - Connect to the specified jack server name.\n" \
68 "    i(<name>) - Connect the output port that gets created to the specified\n" \
69 "                jack input port.\n" \
70 "    o(<name>) - Connect the input port that gets created to the specified\n" \
71 "                jack output port.\n" \
72 "    n         - Do not automatically start the JACK server if it is not already\n" \
73 "                running.\n" \
74 "    c(<name>) - By default, Asterisk will use the channel name for the jack client\n" \
75 "                name.  Use this option to specify a custom client name.\n"
76 /*** DOCUMENTATION
77         <application name="JACK" language="en_US">
78                 <synopsis>
79                         Jack Audio Connection Kit
80                 </synopsis>
81                 <syntax>
82                         <parameter name="options" required="false">
83                                 <optionlist>
84                                         <option name="s">
85                                                 <argument name="name" required="true">
86                                                         <para>Connect to the specified jack server name</para>
87                                                 </argument>
88                                         </option>
89                                         <option name="i">
90                                                 <argument name="name" required="true">
91                                                         <para>Connect the output port that gets created to the specified jack input port</para>
92                                                 </argument>
93                                         </option>
94                                         <option name="o">
95                                                 <argument name="name" required="true">
96                                                         <para>Connect the input port that gets created to the specified jack output port</para>
97                                                 </argument>
98                                         </option>
99                                         <option name="c">
100                                                 <argument name="name" required="true">
101                                                         <para>By default, Asterisk will use the channel name for the jack client name.</para>
102                                                         <para>Use this option to specify a custom client name.</para>
103                                                 </argument>
104                                         </option>
105                                 </optionlist>
106                         </parameter>
107                 </syntax>
108                 <description>
109                         <para>When executing this application, two jack ports will be created; 
110                         one input and one output. Other applications can be hooked up to 
111                         these ports to access audio coming from, or being send to the channel.</para>
112                 </description>
113         </application>
114  ***/
115 static char *jack_app = "JACK";
116
117 struct jack_data {
118         AST_DECLARE_STRING_FIELDS(
119                 AST_STRING_FIELD(server_name);
120                 AST_STRING_FIELD(client_name);
121                 AST_STRING_FIELD(connect_input_port);
122                 AST_STRING_FIELD(connect_output_port);
123         );
124         jack_client_t *client;
125         jack_port_t *input_port;
126         jack_port_t *output_port;
127         jack_ringbuffer_t *input_rb;
128         jack_ringbuffer_t *output_rb;
129         void *output_resampler;
130         double output_resample_factor;
131         void *input_resampler;
132         double input_resample_factor;
133         unsigned int stop:1;
134         unsigned int has_audiohook:1;
135         unsigned int no_start_server:1;
136         /*! Only used with JACK_HOOK */
137         struct ast_audiohook audiohook;
138 };
139
140 static const struct {
141         jack_status_t status;
142         const char *str;
143 } jack_status_table[] = {
144         { JackFailure,        "Failure" },
145         { JackInvalidOption,  "Invalid Option" },
146         { JackNameNotUnique,  "Name Not Unique" },
147         { JackServerStarted,  "Server Started" },
148         { JackServerFailed,   "Server Failed" },
149         { JackServerError,    "Server Error" },
150         { JackNoSuchClient,   "No Such Client" },
151         { JackLoadFailure,    "Load Failure" },
152         { JackInitFailure,    "Init Failure" },
153         { JackShmFailure,     "Shared Memory Access Failure" },
154         { JackVersionError,   "Version Mismatch" },
155 };
156
157 static const char *jack_status_to_str(jack_status_t status)
158 {
159         int i;
160
161         for (i = 0; i < ARRAY_LEN(jack_status_table); i++) {
162                 if (jack_status_table[i].status == status)
163                         return jack_status_table[i].str;
164         }
165
166         return "Unknown Error";
167 }
168
169 static void log_jack_status(const char *prefix, jack_status_t status)
170 {
171         struct ast_str *str = ast_str_alloca(512);
172         int i, first = 0;
173
174         for (i = 0; i < (sizeof(status) * 8); i++) {
175                 if (!(status & (1 << i)))
176                         continue;
177
178                 if (!first) {
179                         ast_str_set(&str, 0, "%s", jack_status_to_str((1 << i)));
180                         first = 1;
181                 } else
182                         ast_str_append(&str, 0, ", %s", jack_status_to_str((1 << i)));
183         }
184         
185         ast_log(LOG_NOTICE, "%s: %s\n", prefix, ast_str_buffer(str));
186 }
187
188 static int alloc_resampler(struct jack_data *jack_data, int input)
189 {
190         double from_srate, to_srate, jack_srate;
191         void **resampler;
192         double *resample_factor;
193
194         if (input && jack_data->input_resampler)
195                 return 0;
196
197         if (!input && jack_data->output_resampler)
198                 return 0;
199
200         jack_srate = jack_get_sample_rate(jack_data->client);
201
202         /* XXX Hard coded 8 kHz */
203
204         to_srate = input ? 8000.0 : jack_srate; 
205         from_srate = input ? jack_srate : 8000.0;
206
207         resample_factor = input ? &jack_data->input_resample_factor : 
208                 &jack_data->output_resample_factor;
209
210         if (from_srate == to_srate) {
211                 /* Awesome!  The jack sample rate is the same as ours.
212                  * Resampling isn't needed. */
213                 *resample_factor = 1.0;
214                 return 0;
215         }
216
217         *resample_factor = to_srate / from_srate;
218
219         resampler = input ? &jack_data->input_resampler :
220                 &jack_data->output_resampler;
221
222         if (!(*resampler = resample_open(RESAMPLE_QUALITY, 
223                 *resample_factor, *resample_factor))) {
224                 ast_log(LOG_ERROR, "Failed to open %s resampler\n", 
225                         input ? "input" : "output");
226                 return -1;
227         }
228
229         return 0;
230 }
231
232 /*!
233  * \brief Handle jack input port
234  *
235  * Read nframes number of samples from the input buffer, resample it
236  * if necessary, and write it into the appropriate ringbuffer. 
237  */
238 static void handle_input(void *buf, jack_nframes_t nframes, 
239         struct jack_data *jack_data)
240 {
241         short s_buf[nframes];
242         float *in_buf = buf;
243         size_t res;
244         int i;
245         size_t write_len = sizeof(s_buf);
246
247         if (jack_data->input_resampler) {
248                 int total_in_buf_used = 0;
249                 int total_out_buf_used = 0;
250                 float f_buf[nframes + 1];
251
252                 memset(f_buf, 0, sizeof(f_buf));
253
254                 while (total_in_buf_used < nframes) {
255                         int in_buf_used;
256                         int out_buf_used;
257
258                         out_buf_used = resample_process(jack_data->input_resampler,
259                                 jack_data->input_resample_factor,
260                                 &in_buf[total_in_buf_used], nframes - total_in_buf_used,
261                                 0, &in_buf_used,
262                                 &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
263
264                         if (out_buf_used < 0)
265                                 break;
266
267                         total_out_buf_used += out_buf_used;
268                         total_in_buf_used += in_buf_used;
269         
270                         if (total_out_buf_used == ARRAY_LEN(f_buf)) {
271                                 ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size, "
272                                         "nframes '%d', total_out_buf_used '%d'\n", nframes, total_out_buf_used);
273                                 break;
274                         }
275                 }
276
277                 for (i = 0; i < total_out_buf_used; i++)
278                         s_buf[i] = f_buf[i] * (SHRT_MAX / 1.0);
279                 
280                 write_len = total_out_buf_used * sizeof(int16_t);
281         } else {
282                 /* No resampling needed */
283
284                 for (i = 0; i < nframes; i++)
285                         s_buf[i] = in_buf[i] * (SHRT_MAX / 1.0);
286         }
287
288         res = jack_ringbuffer_write(jack_data->input_rb, (const char *) s_buf, write_len);
289         if (res != write_len) {
290                 ast_debug(2, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
291                         (int) sizeof(s_buf), (int) res);
292         }
293 }
294
295 /*!
296  * \brief Handle jack output port
297  *
298  * Read nframes number of samples from the ringbuffer and write it out to the
299  * output port buffer.
300  */
301 static void handle_output(void *buf, jack_nframes_t nframes, 
302         struct jack_data *jack_data)
303 {
304         size_t res, len;
305
306         len = nframes * sizeof(float);
307
308         res = jack_ringbuffer_read(jack_data->output_rb, buf, len);
309
310         if (len != res) {
311                 ast_debug(2, "Wanted %d bytes to send to the output port, "
312                         "but only got %d\n", (int) len, (int) res);
313         }
314 }
315
316 static int jack_process(jack_nframes_t nframes, void *arg)
317 {
318         struct jack_data *jack_data = arg;
319         void *input_port_buf, *output_port_buf;
320
321         if (!jack_data->input_resample_factor)
322                 alloc_resampler(jack_data, 1);
323
324         input_port_buf = jack_port_get_buffer(jack_data->input_port, nframes);
325         handle_input(input_port_buf, nframes, jack_data);
326
327         output_port_buf = jack_port_get_buffer(jack_data->output_port, nframes);
328         handle_output(output_port_buf, nframes, jack_data);
329
330         return 0;
331 }
332
333 static void jack_shutdown(void *arg)
334 {
335         struct jack_data *jack_data = arg;
336
337         jack_data->stop = 1;
338 }
339
340 static struct jack_data *destroy_jack_data(struct jack_data *jack_data)
341 {
342         if (jack_data->input_port) {
343                 jack_port_unregister(jack_data->client, jack_data->input_port);
344                 jack_data->input_port = NULL;
345         }
346
347         if (jack_data->output_port) {
348                 jack_port_unregister(jack_data->client, jack_data->output_port);
349                 jack_data->output_port = NULL;
350         }
351
352         if (jack_data->client) {
353                 jack_client_close(jack_data->client);
354                 jack_data->client = NULL;
355         }
356
357         if (jack_data->input_rb) {
358                 jack_ringbuffer_free(jack_data->input_rb);
359                 jack_data->input_rb = NULL;
360         }
361
362         if (jack_data->output_rb) {
363                 jack_ringbuffer_free(jack_data->output_rb);
364                 jack_data->output_rb = NULL;
365         }
366
367         if (jack_data->output_resampler) {
368                 resample_close(jack_data->output_resampler);
369                 jack_data->output_resampler = NULL;
370         }
371         
372         if (jack_data->input_resampler) {
373                 resample_close(jack_data->input_resampler);
374                 jack_data->input_resampler = NULL;
375         }
376
377         if (jack_data->has_audiohook)
378                 ast_audiohook_destroy(&jack_data->audiohook);
379
380         ast_string_field_free_memory(jack_data);
381
382         ast_free(jack_data);
383
384         return NULL;
385 }
386
387 static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
388 {
389         const char *client_name;
390         jack_status_t status = 0;
391         jack_options_t jack_options = JackNullOption;
392
393         if (!ast_strlen_zero(jack_data->client_name)) {
394                 client_name = jack_data->client_name;
395         } else {
396                 ast_channel_lock(chan);
397                 client_name = ast_strdupa(chan->name);
398                 ast_channel_unlock(chan);
399         }
400
401         if (!(jack_data->output_rb = jack_ringbuffer_create(RINGBUFFER_SIZE)))
402                 return -1;
403
404         if (!(jack_data->input_rb = jack_ringbuffer_create(RINGBUFFER_SIZE)))
405                 return -1;
406
407         if (jack_data->no_start_server)
408                 jack_options |= JackNoStartServer;
409
410         if (!ast_strlen_zero(jack_data->server_name)) {
411                 jack_options |= JackServerName;
412                 jack_data->client = jack_client_open(client_name, jack_options, &status,
413                         jack_data->server_name);
414         } else {
415                 jack_data->client = jack_client_open(client_name, jack_options, &status);
416         }
417
418         if (status)
419                 log_jack_status("Client Open Status", status);
420
421         if (!jack_data->client)
422                 return -1;
423
424         jack_data->input_port = jack_port_register(jack_data->client, "input",
425                 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
426         if (!jack_data->input_port) {
427                 ast_log(LOG_ERROR, "Failed to create input port for jack port\n");
428                 return -1;
429         }
430
431         jack_data->output_port = jack_port_register(jack_data->client, "output",
432                 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
433         if (!jack_data->output_port) {
434                 ast_log(LOG_ERROR, "Failed to create output port for jack port\n");
435                 return -1;
436         }
437
438         if (jack_set_process_callback(jack_data->client, jack_process, jack_data)) {
439                 ast_log(LOG_ERROR, "Failed to register process callback with jack client\n");
440                 return -1;
441         }
442
443         jack_on_shutdown(jack_data->client, jack_shutdown, jack_data);
444
445         if (jack_activate(jack_data->client)) {
446                 ast_log(LOG_ERROR, "Unable to activate jack client\n");
447                 return -1;
448         }
449
450         while (!ast_strlen_zero(jack_data->connect_input_port)) {
451                 const char **ports;
452                 int i;
453
454                 ports = jack_get_ports(jack_data->client, jack_data->connect_input_port,
455                         NULL, JackPortIsInput);
456
457                 if (!ports) {
458                         ast_log(LOG_ERROR, "No input port matching '%s' was found\n",
459                                 jack_data->connect_input_port);
460                         break;
461                 }
462
463                 for (i = 0; ports[i]; i++) {
464                         ast_debug(1, "Found port '%s' that matched specified input port '%s'\n",
465                                 ports[i], jack_data->connect_input_port);
466                 }
467
468                 if (jack_connect(jack_data->client, jack_port_name(jack_data->output_port), ports[0])) {
469                         ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
470                                 jack_port_name(jack_data->output_port));
471                 } else {
472                         ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
473                                 jack_port_name(jack_data->output_port));
474                 }
475
476                 free((void *) ports);
477
478                 break;
479         }
480
481         while (!ast_strlen_zero(jack_data->connect_output_port)) {
482                 const char **ports;
483                 int i;
484
485                 ports = jack_get_ports(jack_data->client, jack_data->connect_output_port,
486                         NULL, JackPortIsOutput);
487
488                 if (!ports) {
489                         ast_log(LOG_ERROR, "No output port matching '%s' was found\n",
490                                 jack_data->connect_output_port);
491                         break;
492                 }
493
494                 for (i = 0; ports[i]; i++) {
495                         ast_debug(1, "Found port '%s' that matched specified output port '%s'\n",
496                                 ports[i], jack_data->connect_output_port);
497                 }
498
499                 if (jack_connect(jack_data->client, ports[0], jack_port_name(jack_data->input_port))) {
500                         ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
501                                 jack_port_name(jack_data->input_port));
502                 } else {
503                         ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
504                                 jack_port_name(jack_data->input_port));
505                 }
506
507                 free((void *) ports);
508
509                 break;
510         }
511
512         return 0;
513 }
514
515 static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
516 {
517         float f_buf[f->samples * 8];
518         size_t f_buf_used = 0;
519         int i;
520         int16_t *s_buf = f->data.ptr;
521         size_t res;
522
523         memset(f_buf, 0, sizeof(f_buf));
524
525         if (!jack_data->output_resample_factor)
526                 alloc_resampler(jack_data, 0);
527
528         if (jack_data->output_resampler) {
529                 float in_buf[f->samples];
530                 int total_in_buf_used = 0;
531                 int total_out_buf_used = 0;
532
533                 memset(in_buf, 0, sizeof(in_buf));
534
535                 for (i = 0; i < f->samples; i++)
536                         in_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
537
538                 while (total_in_buf_used < ARRAY_LEN(in_buf)) {
539                         int in_buf_used;
540                         int out_buf_used;
541
542                         out_buf_used = resample_process(jack_data->output_resampler, 
543                                 jack_data->output_resample_factor,
544                                 &in_buf[total_in_buf_used], ARRAY_LEN(in_buf) - total_in_buf_used, 
545                                 0, &in_buf_used, 
546                                 &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
547
548                         if (out_buf_used < 0)
549                                 break;
550
551                         total_out_buf_used += out_buf_used;
552                         total_in_buf_used += in_buf_used;
553
554                         if (total_out_buf_used == ARRAY_LEN(f_buf)) {
555                                 ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
556                                 break;
557                         }
558                 }
559
560                 f_buf_used = total_out_buf_used;
561                 if (f_buf_used > ARRAY_LEN(f_buf))
562                         f_buf_used = ARRAY_LEN(f_buf);
563         } else {
564                 /* No resampling needed */
565
566                 for (i = 0; i < f->samples; i++)
567                         f_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
568
569                 f_buf_used = f->samples;
570         }
571
572         res = jack_ringbuffer_write(jack_data->output_rb, (const char *) f_buf, f_buf_used * sizeof(float));
573         if (res != (f_buf_used * sizeof(float))) {
574                 ast_debug(2, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
575                         (int) (f_buf_used * sizeof(float)), (int) res);
576         }
577
578         return 0;
579 }
580
581 /*!
582  * \brief handle jack audio
583  *
584  * \param[in]  chan The Asterisk channel to write the frames to if no output frame
585  *             is provided.
586  * \param[in]  jack_data This is the jack_data struct that contains the input
587  *             ringbuffer that audio will be read from.
588  * \param[out] out_frame If this argument is non-NULL, then assuming there is
589  *             enough data avilable in the ringbuffer, the audio in this frame
590  *             will get replaced with audio from the input buffer.  If there is
591  *             not enough data available to read at this time, then the frame
592  *             data gets zeroed out.
593  *
594  * Read data from the input ringbuffer, which is the properly resampled audio
595  * that was read from the jack input port.  Write it to the channel in 20 ms frames,
596  * or fill up an output frame instead if one is provided.
597  *
598  * \return Nothing.
599  */
600 static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data,
601         struct ast_frame *out_frame)
602 {       
603         short buf[160];
604         struct ast_frame f = {
605                 .frametype = AST_FRAME_VOICE,
606                 .subclass = AST_FORMAT_SLINEAR,
607                 .src = "JACK",
608                 .data.ptr = buf,
609                 .datalen = sizeof(buf),
610                 .samples = ARRAY_LEN(buf),
611         };
612
613         for (;;) {
614                 size_t res, read_len;
615                 char *read_buf;
616
617                 read_len = out_frame ? out_frame->datalen : sizeof(buf);
618                 read_buf = out_frame ? out_frame->data.ptr : buf;
619
620                 res = jack_ringbuffer_read_space(jack_data->input_rb);
621
622                 if (res < read_len) {
623                         /* Not enough data ready for another frame, move on ... */
624                         if (out_frame) {
625                                 ast_debug(1, "Sending an empty frame for the JACK_HOOK\n");
626                                 memset(out_frame->data.ptr, 0, out_frame->datalen);
627                         }
628                         break;
629                 }
630
631                 res = jack_ringbuffer_read(jack_data->input_rb, (char *) read_buf, read_len);
632
633                 if (res < read_len) {
634                         ast_log(LOG_ERROR, "Error reading from ringbuffer, even though it said there was enough data\n");
635                         break;
636                 }
637
638                 if (out_frame) {
639                         /* If an output frame was provided, then we just want to fill up the
640                          * buffer in that frame and return. */
641                         break;
642                 }
643
644                 ast_write(chan, &f);
645         }
646 }
647
648 enum {
649         OPT_SERVER_NAME =    (1 << 0),
650         OPT_INPUT_PORT =     (1 << 1),
651         OPT_OUTPUT_PORT =    (1 << 2),
652         OPT_NOSTART_SERVER = (1 << 3),
653         OPT_CLIENT_NAME =    (1 << 4),
654 };
655
656 enum {
657         OPT_ARG_SERVER_NAME,
658         OPT_ARG_INPUT_PORT,
659         OPT_ARG_OUTPUT_PORT,
660         OPT_ARG_CLIENT_NAME,
661
662         /* Must be the last element */
663         OPT_ARG_ARRAY_SIZE,
664 };
665
666 AST_APP_OPTIONS(jack_exec_options, BEGIN_OPTIONS
667         AST_APP_OPTION_ARG('s', OPT_SERVER_NAME, OPT_ARG_SERVER_NAME),
668         AST_APP_OPTION_ARG('i', OPT_INPUT_PORT, OPT_ARG_INPUT_PORT),
669         AST_APP_OPTION_ARG('o', OPT_OUTPUT_PORT, OPT_ARG_OUTPUT_PORT),
670         AST_APP_OPTION('n', OPT_NOSTART_SERVER),
671         AST_APP_OPTION_ARG('c', OPT_CLIENT_NAME, OPT_ARG_CLIENT_NAME),
672 END_OPTIONS );
673
674 static struct jack_data *jack_data_alloc(void)
675 {
676         struct jack_data *jack_data;
677
678         if (!(jack_data = ast_calloc(1, sizeof(*jack_data))))
679                 return NULL;
680         
681         if (ast_string_field_init(jack_data, 32)) {
682                 ast_free(jack_data);
683                 return NULL;
684         }
685
686         return jack_data;
687 }
688
689 /*!
690  * \note This must be done before calling init_jack_data().
691  */
692 static int handle_options(struct jack_data *jack_data, const char *__options_str)
693 {
694         struct ast_flags options = { 0, };
695         char *option_args[OPT_ARG_ARRAY_SIZE];
696         char *options_str;
697
698         options_str = ast_strdupa(__options_str);
699
700         ast_app_parse_options(jack_exec_options, &options, option_args, options_str);
701
702         if (ast_test_flag(&options, OPT_SERVER_NAME)) {
703                 if (!ast_strlen_zero(option_args[OPT_ARG_SERVER_NAME]))
704                         ast_string_field_set(jack_data, server_name, option_args[OPT_ARG_SERVER_NAME]);
705                 else {
706                         ast_log(LOG_ERROR, "A server name must be provided with the s() option\n");
707                         return -1;
708                 }
709         }
710
711         if (ast_test_flag(&options, OPT_CLIENT_NAME)) {
712                 if (!ast_strlen_zero(option_args[OPT_ARG_CLIENT_NAME]))
713                         ast_string_field_set(jack_data, client_name, option_args[OPT_ARG_CLIENT_NAME]);
714                 else {
715                         ast_log(LOG_ERROR, "A client name must be provided with the c() option\n");
716                         return -1;
717                 }
718         }
719
720         if (ast_test_flag(&options, OPT_INPUT_PORT)) {
721                 if (!ast_strlen_zero(option_args[OPT_ARG_INPUT_PORT]))
722                         ast_string_field_set(jack_data, connect_input_port, option_args[OPT_ARG_INPUT_PORT]);
723                 else {
724                         ast_log(LOG_ERROR, "A name must be provided with the i() option\n");
725                         return -1;
726                 }
727         }
728
729         if (ast_test_flag(&options, OPT_OUTPUT_PORT)) {
730                 if (!ast_strlen_zero(option_args[OPT_ARG_OUTPUT_PORT]))
731                         ast_string_field_set(jack_data, connect_output_port, option_args[OPT_ARG_OUTPUT_PORT]);
732                 else {
733                         ast_log(LOG_ERROR, "A name must be provided with the o() option\n");
734                         return -1;
735                 }
736         }
737
738         jack_data->no_start_server = ast_test_flag(&options, OPT_NOSTART_SERVER) ? 1 : 0;
739
740         return 0;
741 }
742
743 static int jack_exec(struct ast_channel *chan, void *data)
744 {
745         struct jack_data *jack_data;
746         AST_DECLARE_APP_ARGS(args,
747                 AST_APP_ARG(options);
748         );
749
750         if (!(jack_data = jack_data_alloc()))
751                 return -1;
752
753         args.options = data;
754
755         if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options)) {
756                 destroy_jack_data(jack_data);
757                 return -1;
758         }
759
760         if (init_jack_data(chan, jack_data)) {
761                 destroy_jack_data(jack_data);
762                 return -1;
763         }
764
765         if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
766                 destroy_jack_data(jack_data);
767                 return -1;
768         }
769
770         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
771                 destroy_jack_data(jack_data);
772                 return -1;
773         }
774
775         while (!jack_data->stop) {
776                 struct ast_frame *f;
777
778                 ast_waitfor(chan, -1);
779
780                 f = ast_read(chan);
781                 if (!f) {
782                         jack_data->stop = 1;
783                         continue;
784                 }
785
786                 switch (f->frametype) {
787                 case AST_FRAME_CONTROL:
788                         if (f->subclass == AST_CONTROL_HANGUP)
789                                 jack_data->stop = 1;
790                         break;
791                 case AST_FRAME_VOICE:
792                         queue_voice_frame(jack_data, f);
793                 default:
794                         break;
795                 }
796
797                 ast_frfree(f);
798
799                 handle_jack_audio(chan, jack_data, NULL);
800         }
801
802         jack_data = destroy_jack_data(jack_data);
803
804         return 0;
805 }
806
807 static void jack_hook_ds_destroy(void *data)
808 {
809         struct jack_data *jack_data = data;
810
811         destroy_jack_data(jack_data);
812 }
813
814 static const struct ast_datastore_info jack_hook_ds_info = {
815         .type = "JACK_HOOK",
816         .destroy = jack_hook_ds_destroy,
817 };
818
819 static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, 
820         struct ast_frame *frame, enum ast_audiohook_direction direction)
821 {
822         struct ast_datastore *datastore;
823         struct jack_data *jack_data;
824
825         if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
826                 return 0;
827
828         if (direction != AST_AUDIOHOOK_DIRECTION_READ)
829                 return 0;
830
831         if (frame->frametype != AST_FRAME_VOICE)
832                 return 0;
833
834         if (frame->subclass != AST_FORMAT_SLINEAR) {
835                 ast_log(LOG_WARNING, "Expected frame in SLINEAR for the audiohook, but got format %d\n",
836                         frame->subclass);
837                 return 0;
838         }
839
840         ast_channel_lock(chan);
841
842         if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
843                 ast_log(LOG_ERROR, "JACK_HOOK datastore not found for '%s'\n", chan->name);
844                 ast_channel_unlock(chan);
845                 return -1;
846         }
847
848         jack_data = datastore->data;
849
850         queue_voice_frame(jack_data, frame);
851
852         handle_jack_audio(chan, jack_data, frame);
853
854         ast_channel_unlock(chan);
855
856         return 0;
857 }
858
859 static int enable_jack_hook(struct ast_channel *chan, char *data)
860 {
861         struct ast_datastore *datastore;
862         struct jack_data *jack_data = NULL;
863         AST_DECLARE_APP_ARGS(args,
864                 AST_APP_ARG(mode);
865                 AST_APP_ARG(options);
866         );
867
868         AST_STANDARD_APP_ARGS(args, data);
869
870         ast_channel_lock(chan);
871
872         if ((datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
873                 ast_log(LOG_ERROR, "JACK_HOOK already enabled for '%s'\n", chan->name);
874                 goto return_error;
875         }
876
877         if (ast_strlen_zero(args.mode) || strcasecmp(args.mode, "manipulate")) {
878                 ast_log(LOG_ERROR, "'%s' is not a supported mode.  Only manipulate is supported.\n", 
879                         S_OR(args.mode, "<none>"));
880                 goto return_error;
881         }
882
883         if (!(jack_data = jack_data_alloc()))
884                 goto return_error;
885
886         if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options))
887                 goto return_error;
888
889         if (init_jack_data(chan, jack_data))
890                 goto return_error;
891
892         if (!(datastore = ast_datastore_alloc(&jack_hook_ds_info, NULL)))
893                 goto return_error;
894
895         jack_data->has_audiohook = 1;
896         ast_audiohook_init(&jack_data->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "JACK_HOOK");
897         jack_data->audiohook.manipulate_callback = jack_hook_callback;
898
899         datastore->data = jack_data;
900
901         if (ast_audiohook_attach(chan, &jack_data->audiohook))
902                 goto return_error;
903
904         if (ast_channel_datastore_add(chan, datastore))
905                 goto return_error;
906
907         ast_channel_unlock(chan);
908
909         return 0;
910
911 return_error:
912         ast_channel_unlock(chan);
913
914         if (jack_data)
915                 destroy_jack_data(jack_data);
916
917         return -1;
918 }
919
920 static int disable_jack_hook(struct ast_channel *chan)
921 {
922         struct ast_datastore *datastore;
923         struct jack_data *jack_data;
924
925         ast_channel_lock(chan);
926
927         if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
928                 ast_channel_unlock(chan);
929                 ast_log(LOG_WARNING, "No JACK_HOOK found to disable\n");
930                 return -1;
931         }
932
933         ast_channel_datastore_remove(chan, datastore);
934
935         jack_data = datastore->data;
936         ast_audiohook_detach(&jack_data->audiohook);
937
938         /* Keep the channel locked while we destroy the datastore, so that we can
939          * ensure that all of the jack stuff is stopped just in case another frame
940          * tries to come through the audiohook callback. */
941         ast_datastore_free(datastore);
942
943         ast_channel_unlock(chan);
944
945         return 0;
946 }
947
948 static int jack_hook_write(struct ast_channel *chan, const char *cmd, char *data, 
949         const char *value)
950 {
951         int res;
952
953         if (!strcasecmp(value, "on"))
954                 res = enable_jack_hook(chan, data);
955         else if (!strcasecmp(value, "off"))
956                 res = disable_jack_hook(chan);
957         else {
958                 ast_log(LOG_ERROR, "'%s' is not a valid value for JACK_HOOK()\n", value);       
959                 res = -1;
960         }
961
962         return res;
963 }
964
965 static struct ast_custom_function jack_hook_function = {
966         .name = "JACK_HOOK",
967         .synopsis = "Enable a jack hook on a channel",
968         .syntax = "JACK_HOOK(<mode>,[options])",
969         .desc =
970         "   The JACK_HOOK allows turning on or off jack connectivity to this channel.\n"
971         "When the JACK_HOOK is turned on, jack ports will get created that allow\n"
972         "access to the audio stream for this channel.  The mode specifies which mode\n"
973         "this hook should run in.  A mode must be specified when turning the JACK_HOOK.\n"
974         "on.  However, all arguments are optional when turning it off.\n"
975         "\n"
976         "   Valid modes are:\n"
977 #if 0
978         /* XXX TODO */
979         "    spy -        Create a read-only audio hook.  Only an output jack port will\n"
980         "                 get created.\n"
981         "    whisper -    Create a write-only audio hook.  Only an input jack port will\n"
982         "                 get created.\n"
983 #endif
984         "    manipulate - Create a read/write audio hook.  Both an input and an output\n"
985         "                 jack port will get created.  Audio from the channel will be\n"
986         "                 sent out the output port and will be replaced by the audio\n"
987         "                 coming in on the input port as it gets passed on.\n"
988         "\n"
989         "   Valid options are:\n"
990         COMMON_OPTIONS
991         "\n"
992         " Examples:\n"
993         "   To turn on the JACK_HOOK,\n"
994         "     Set(JACK_HOOK(manipulate,i(pure_data_0:input0)o(pure_data_0:output0))=on)\n"
995         "   To turn off the JACK_HOOK,\n"
996         "     Set(JACK_HOOK()=off)\n"
997         "",
998         .write = jack_hook_write,
999 };
1000
1001 static int unload_module(void)
1002 {
1003         int res;
1004
1005         res = ast_unregister_application(jack_app);
1006         res |= ast_custom_function_unregister(&jack_hook_function);
1007
1008         return res;
1009 }
1010
1011 static int load_module(void)
1012 {
1013         if (ast_register_application_xml(jack_app, jack_exec)) {
1014                 return AST_MODULE_LOAD_DECLINE;
1015         }
1016
1017         if (ast_custom_function_register(&jack_hook_function)) {
1018                 ast_unregister_application(jack_app);
1019                 return AST_MODULE_LOAD_DECLINE;
1020         }
1021
1022         return AST_MODULE_LOAD_SUCCESS;
1023 }
1024
1025 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "JACK Interface");