Asterisk - The Open Source Telephony Project GIT-master-754dea3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
app_jack.c
Go to the documentation of this file.
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 * \extref 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 <support_level>extended</support_level>
41 ***/
42
43#include "asterisk.h"
44
45#include <limits.h>
46
47#include <jack/jack.h>
48#include <jack/ringbuffer.h>
49
50#include <libresample.h>
51
52#include "asterisk/module.h"
53#include "asterisk/channel.h"
54#include "asterisk/strings.h"
55#include "asterisk/lock.h"
56#include "asterisk/app.h"
57#include "asterisk/pbx.h"
58#include "asterisk/audiohook.h"
60
61#define RESAMPLE_QUALITY 1
62
63/* The number of frames the ringbuffers can store. The actual size is RINGBUFFER_FRAME_CAPACITY * jack_data->frame_datalen */
64#define RINGBUFFER_FRAME_CAPACITY 100
65
66/*! \brief Common options between the Jack() app and JACK_HOOK() function */
67#define COMMON_OPTIONS \
68" s(<name>) - Connect to the specified jack server name.\n" \
69" i(<name>) - Connect the output port that gets created to the specified\n" \
70" jack input port.\n" \
71" o(<name>) - Connect the input port that gets created to the specified\n" \
72" jack output port.\n" \
73" n - Do not automatically start the JACK server if it is not already\n" \
74" running.\n" \
75" c(<name>) - By default, Asterisk will use the channel name for the jack client\n" \
76" name. Use this option to specify a custom client name.\n"
77/*** DOCUMENTATION
78 <application name="JACK" language="en_US">
79 <since>
80 <version>1.6.0</version>
81 </since>
82 <synopsis>
83 Jack Audio Connection Kit
84 </synopsis>
85 <syntax>
86 <parameter name="options" required="false">
87 <optionlist>
88 <option name="s">
89 <argument name="name" required="true">
90 <para>Connect to the specified jack server name</para>
91 </argument>
92 </option>
93 <option name="i">
94 <argument name="name" required="true">
95 <para>Connect the output port that gets created to the specified jack input port</para>
96 </argument>
97 </option>
98 <option name="o">
99 <argument name="name" required="true">
100 <para>Connect the input port that gets created to the specified jack output port</para>
101 </argument>
102 </option>
103 <option name="c">
104 <argument name="name" required="true">
105 <para>By default, Asterisk will use the channel name for the jack client name.</para>
106 <para>Use this option to specify a custom client name.</para>
107 </argument>
108 </option>
109 </optionlist>
110 </parameter>
111 </syntax>
112 <description>
113 <para>When executing this application, two jack ports will be created;
114 one input and one output. Other applications can be hooked up to
115 these ports to access audio coming from, or being send to the channel.</para>
116 </description>
117 </application>
118 ***/
119
120static const char jack_app[] = "JACK";
121
122struct jack_data {
128 );
129 jack_client_t *client;
130 jack_port_t *input_port;
131 jack_port_t *output_port;
132 jack_ringbuffer_t *input_rb;
133 jack_ringbuffer_t *output_rb;
135 unsigned int audiohook_rate;
136 unsigned int frame_datalen;
141 unsigned int stop:1;
142 unsigned int has_audiohook:1;
143 unsigned int no_start_server:1;
144 /*! Only used with JACK_HOOK */
146};
147
148static const struct {
149 jack_status_t status;
150 const char *str;
151} jack_status_table[] = {
152 { JackFailure, "Failure" },
153 { JackInvalidOption, "Invalid Option" },
154 { JackNameNotUnique, "Name Not Unique" },
155 { JackServerStarted, "Server Started" },
156 { JackServerFailed, "Server Failed" },
157 { JackServerError, "Server Error" },
158 { JackNoSuchClient, "No Such Client" },
159 { JackLoadFailure, "Load Failure" },
160 { JackInitFailure, "Init Failure" },
161 { JackShmFailure, "Shared Memory Access Failure" },
162 { JackVersionError, "Version Mismatch" },
164
165static const char *jack_status_to_str(jack_status_t status)
166{
167 int i;
168
169 for (i = 0; i < ARRAY_LEN(jack_status_table); i++) {
171 return jack_status_table[i].str;
172 }
173
174 return "Unknown Error";
175}
176
177static void log_jack_status(const char *prefix, jack_status_t status)
178{
179 struct ast_str *str = ast_str_alloca(512);
180 int i, first = 0;
181
182 for (i = 0; i < (sizeof(status) * 8); i++) {
183 if (!(status & (1 << i)))
184 continue;
185
186 if (!first) {
187 ast_str_set(&str, 0, "%s", jack_status_to_str((1 << i)));
188 first = 1;
189 } else
190 ast_str_append(&str, 0, ", %s", jack_status_to_str((1 << i)));
191 }
192
194}
195
196static int alloc_resampler(struct jack_data *jack_data, int input)
197{
198 double from_srate, to_srate, jack_srate;
199 void **resampler;
200 double *resample_factor;
201
203 return 0;
204
206 return 0;
207
208 jack_srate = jack_get_sample_rate(jack_data->client);
209
210 to_srate = input ? jack_data->audiohook_rate : jack_srate;
211 from_srate = input ? jack_srate : jack_data->audiohook_rate;
212
213 resample_factor = input ? &jack_data->input_resample_factor :
215
216 if (from_srate == to_srate) {
217 /* Awesome! The jack sample rate is the same as ours.
218 * Resampling isn't needed. */
219 *resample_factor = 1.0;
220 return 0;
221 }
222
223 *resample_factor = to_srate / from_srate;
224
225 resampler = input ? &jack_data->input_resampler :
227
228 if (!(*resampler = resample_open(RESAMPLE_QUALITY,
229 *resample_factor, *resample_factor))) {
230 ast_log(LOG_ERROR, "Failed to open %s resampler\n",
231 input ? "input" : "output");
232 return -1;
233 }
234
235 return 0;
236}
237
238/*!
239 * \brief Handle jack input port
240 *
241 * Read nframes number of samples from the input buffer, resample it
242 * if necessary, and write it into the appropriate ringbuffer.
243 */
244static void handle_input(void *buf, jack_nframes_t nframes,
245 struct jack_data *jack_data)
246{
247 short s_buf[nframes];
248 float *in_buf = buf;
249 size_t res;
250 int i;
251 size_t write_len = sizeof(s_buf);
252
254 int total_in_buf_used = 0;
255 int total_out_buf_used = 0;
256 float f_buf[nframes + 1];
257
258 memset(f_buf, 0, sizeof(f_buf));
259
260 while (total_in_buf_used < nframes) {
261 int in_buf_used;
262 int out_buf_used;
263
264 out_buf_used = resample_process(jack_data->input_resampler,
266 &in_buf[total_in_buf_used], nframes - total_in_buf_used,
267 0, &in_buf_used,
268 &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
269
270 if (out_buf_used < 0)
271 break;
272
273 total_out_buf_used += out_buf_used;
274 total_in_buf_used += in_buf_used;
275
276 if (total_out_buf_used == ARRAY_LEN(f_buf)) {
277 ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size, "
278 "nframes '%d', total_out_buf_used '%d'\n", nframes, total_out_buf_used);
279 break;
280 }
281 }
282
283 for (i = 0; i < total_out_buf_used; i++)
284 s_buf[i] = f_buf[i] * (SHRT_MAX / 1.0);
285
286 write_len = total_out_buf_used * sizeof(int16_t);
287 } else {
288 /* No resampling needed */
289
290 for (i = 0; i < nframes; i++)
291 s_buf[i] = in_buf[i] * (SHRT_MAX / 1.0);
292 }
293
294 res = jack_ringbuffer_write(jack_data->input_rb, (const char *) s_buf, write_len);
295 if (res != write_len) {
296 ast_log(LOG_WARNING, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
297 (int) sizeof(s_buf), (int) res);
298 }
299}
300
301/*!
302 * \brief Handle jack output port
303 *
304 * Read nframes number of samples from the ringbuffer and write it out to the
305 * output port buffer.
306 */
307static void handle_output(void *buf, jack_nframes_t nframes,
308 struct jack_data *jack_data)
309{
310 size_t res, len;
311
312 len = nframes * sizeof(float);
313
314 res = jack_ringbuffer_read(jack_data->output_rb, buf, len);
315
316 if (len != res) {
317 ast_debug(2, "Wanted %d bytes to send to the output port, "
318 "but only got %d\n", (int) len, (int) res);
319 }
320}
321
322static int jack_process(jack_nframes_t nframes, void *arg)
323{
324 struct jack_data *jack_data = arg;
325 void *input_port_buf, *output_port_buf;
326
329
330 input_port_buf = jack_port_get_buffer(jack_data->input_port, nframes);
331 handle_input(input_port_buf, nframes, jack_data);
332
333 output_port_buf = jack_port_get_buffer(jack_data->output_port, nframes);
334 handle_output(output_port_buf, nframes, jack_data);
335
336 return 0;
337}
338
339static void jack_shutdown(void *arg)
340{
341 struct jack_data *jack_data = arg;
342
343 jack_data->stop = 1;
344}
345
347{
348 if (jack_data->input_port) {
349 jack_port_unregister(jack_data->client, jack_data->input_port);
351 }
352
353 if (jack_data->output_port) {
354 jack_port_unregister(jack_data->client, jack_data->output_port);
356 }
357
358 if (jack_data->client) {
359 jack_client_close(jack_data->client);
361 }
362
363 if (jack_data->input_rb) {
364 jack_ringbuffer_free(jack_data->input_rb);
366 }
367
368 if (jack_data->output_rb) {
369 jack_ringbuffer_free(jack_data->output_rb);
371 }
372
374 resample_close(jack_data->output_resampler);
376 }
377
379 resample_close(jack_data->input_resampler);
381 }
382
385
387
389
390 return NULL;
391}
392
393static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
394{
395 const char *client_name;
396 jack_status_t status = 0;
397 jack_options_t jack_options = JackNullOption;
398
399 unsigned int channel_rate;
400
401 unsigned int ringbuffer_size;
402
403 /* Deducing audiohook sample rate from channel format
404 ATTENTION: Might be problematic, if channel has different sampling than used by audiohook!
405 */
409
410 /* Guessing frame->datalen assuming a ptime of 20ms */
412
414
415 ast_debug(1, "Audiohook parameters: slin-format:%s, rate:%d, frame-len:%d, ringbuffer_size: %d\n",
417
420 } else {
421 ast_channel_lock(chan);
423 ast_channel_unlock(chan);
424 }
425
426 if (!(jack_data->output_rb = jack_ringbuffer_create(ringbuffer_size)))
427 return -1;
428
429 if (!(jack_data->input_rb = jack_ringbuffer_create(ringbuffer_size)))
430 return -1;
431
433 jack_options |= JackNoStartServer;
434
436 jack_options |= JackServerName;
437 jack_data->client = jack_client_open(client_name, jack_options, &status,
439 } else {
440 jack_data->client = jack_client_open(client_name, jack_options, &status);
441 }
442
443 if (status)
444 log_jack_status("Client Open Status", status);
445
446 if (!jack_data->client)
447 return -1;
448
449 jack_data->input_port = jack_port_register(jack_data->client, "input",
450 JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
451 if (!jack_data->input_port) {
452 ast_log(LOG_ERROR, "Failed to create input port for jack port\n");
453 return -1;
454 }
455
456 jack_data->output_port = jack_port_register(jack_data->client, "output",
457 JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
458 if (!jack_data->output_port) {
459 ast_log(LOG_ERROR, "Failed to create output port for jack port\n");
460 return -1;
461 }
462
463 if (jack_set_process_callback(jack_data->client, jack_process, jack_data)) {
464 ast_log(LOG_ERROR, "Failed to register process callback with jack client\n");
465 return -1;
466 }
467
468 jack_on_shutdown(jack_data->client, jack_shutdown, jack_data);
469
470 if (jack_activate(jack_data->client)) {
471 ast_log(LOG_ERROR, "Unable to activate jack client\n");
472 return -1;
473 }
474
476 const char **ports;
477 int i;
478
479 ports = jack_get_ports(jack_data->client, jack_data->connect_input_port,
480 NULL, JackPortIsInput);
481
482 if (!ports) {
483 ast_log(LOG_ERROR, "No input port matching '%s' was found\n",
485 break;
486 }
487
488 for (i = 0; ports[i]; i++) {
489 ast_debug(1, "Found port '%s' that matched specified input port '%s'\n",
490 ports[i], jack_data->connect_input_port);
491 }
492
493 if (jack_connect(jack_data->client, jack_port_name(jack_data->output_port), ports[0])) {
494 ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
495 jack_port_name(jack_data->output_port));
496 } else {
497 ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
498 jack_port_name(jack_data->output_port));
499 }
500
501 jack_free(ports);
502
503 break;
504 }
505
507 const char **ports;
508 int i;
509
510 ports = jack_get_ports(jack_data->client, jack_data->connect_output_port,
511 NULL, JackPortIsOutput);
512
513 if (!ports) {
514 ast_log(LOG_ERROR, "No output port matching '%s' was found\n",
516 break;
517 }
518
519 for (i = 0; ports[i]; i++) {
520 ast_debug(1, "Found port '%s' that matched specified output port '%s'\n",
521 ports[i], jack_data->connect_output_port);
522 }
523
524 if (jack_connect(jack_data->client, ports[0], jack_port_name(jack_data->input_port))) {
525 ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
526 jack_port_name(jack_data->input_port));
527 } else {
528 ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
529 jack_port_name(jack_data->input_port));
530 }
531
532 jack_free(ports);
533
534 break;
535 }
536
537 return 0;
538}
539
540static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
541{
542 float f_buf[f->samples * 8];
543 size_t f_buf_used = 0;
544 int i;
545 int16_t *s_buf = f->data.ptr;
546 size_t res;
547
548 memset(f_buf, 0, sizeof(f_buf));
549
552
554 float in_buf[f->samples];
555 int total_in_buf_used = 0;
556 int total_out_buf_used = 0;
557
558 memset(in_buf, 0, sizeof(in_buf));
559
560 for (i = 0; i < f->samples; i++)
561 in_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
562
563 while (total_in_buf_used < ARRAY_LEN(in_buf)) {
564 int in_buf_used;
565 int out_buf_used;
566
567 out_buf_used = resample_process(jack_data->output_resampler,
569 &in_buf[total_in_buf_used], ARRAY_LEN(in_buf) - total_in_buf_used,
570 0, &in_buf_used,
571 &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
572
573 if (out_buf_used < 0)
574 break;
575
576 total_out_buf_used += out_buf_used;
577 total_in_buf_used += in_buf_used;
578
579 if (total_out_buf_used == ARRAY_LEN(f_buf)) {
580 ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
581 break;
582 }
583 }
584
585 f_buf_used = total_out_buf_used;
586 if (f_buf_used > ARRAY_LEN(f_buf))
587 f_buf_used = ARRAY_LEN(f_buf);
588 } else {
589 /* No resampling needed */
590
591 for (i = 0; i < f->samples; i++)
592 f_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
593
594 f_buf_used = f->samples;
595 }
596
597 res = jack_ringbuffer_write(jack_data->output_rb, (const char *) f_buf, f_buf_used * sizeof(float));
598 if (res != (f_buf_used * sizeof(float))) {
599 ast_log(LOG_WARNING, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
600 (int) (f_buf_used * sizeof(float)), (int) res);
601 }
602 return 0;
603}
604
605/*!
606 * \brief handle jack audio
607 *
608 * \param[in] chan The Asterisk channel to write the frames to if no output frame
609 * is provided.
610 * \param[in] jack_data This is the jack_data struct that contains the input
611 * ringbuffer that audio will be read from.
612 * \param[out] out_frame If this argument is non-NULL, then assuming there is
613 * enough data available in the ringbuffer, the audio in this frame
614 * will get replaced with audio from the input buffer. If there is
615 * not enough data available to read at this time, then the frame
616 * data gets zeroed out.
617 *
618 * Read data from the input ringbuffer, which is the properly resampled audio
619 * that was read from the jack input port. Write it to the channel in 20 ms frames,
620 * or fill up an output frame instead if one is provided.
621 */
622static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data,
623 struct ast_frame *out_frame)
624{
626 struct ast_frame f = {
628 .subclass.format = jack_data->audiohook_format,
629 .src = "JACK",
630 .data.ptr = buf,
631 .datalen = sizeof(buf),
633 };
634
635 for (;;) {
636 size_t res, read_len;
637 char *read_buf;
638
639 read_len = out_frame ? out_frame->datalen : sizeof(buf);
640 read_buf = out_frame ? out_frame->data.ptr : buf;
641
642 res = jack_ringbuffer_read_space(jack_data->input_rb);
643
644 if (res < read_len) {
645 /* Not enough data ready for another frame, move on ... */
646 if (out_frame) {
647 ast_debug(1, "Sending an empty frame for the JACK_HOOK\n");
648 memset(out_frame->data.ptr, 0, out_frame->datalen);
649 }
650 break;
651 }
652
653 res = jack_ringbuffer_read(jack_data->input_rb, (char *) read_buf, read_len);
654
655 if (res < read_len) {
656 ast_log(LOG_ERROR, "Error reading from ringbuffer, even though it said there was enough data\n");
657 break;
658 }
659
660 if (out_frame) {
661 /* If an output frame was provided, then we just want to fill up the
662 * buffer in that frame and return. */
663 break;
664 }
665
666 ast_write(chan, &f);
667 }
668}
669
670enum {
671 OPT_SERVER_NAME = (1 << 0),
672 OPT_INPUT_PORT = (1 << 1),
673 OPT_OUTPUT_PORT = (1 << 2),
675 OPT_CLIENT_NAME = (1 << 4),
676};
677
678enum {
683
684 /* Must be the last element */
686};
687
695
696static struct jack_data *jack_data_alloc(void)
697{
698 struct jack_data *jack_data;
699
700 if (!(jack_data = ast_calloc_with_stringfields(1, struct jack_data, 32))) {
701 return NULL;
702 }
703
704 return jack_data;
705}
706
707/*!
708 * \note This must be done before calling init_jack_data().
709 */
710static int handle_options(struct jack_data *jack_data, const char *__options_str)
711{
712 struct ast_flags options = { 0, };
714 char *options_str;
715
716 options_str = ast_strdupa(__options_str);
717
719
723 else {
724 ast_log(LOG_ERROR, "A server name must be provided with the s() option\n");
725 return -1;
726 }
727 }
728
732 else {
733 ast_log(LOG_ERROR, "A client name must be provided with the c() option\n");
734 return -1;
735 }
736 }
737
741 else {
742 ast_log(LOG_ERROR, "A name must be provided with the i() option\n");
743 return -1;
744 }
745 }
746
750 else {
751 ast_log(LOG_ERROR, "A name must be provided with the o() option\n");
752 return -1;
753 }
754 }
755
757
758 return 0;
759}
760
761static int jack_exec(struct ast_channel *chan, const char *data)
762{
763 struct jack_data *jack_data;
764
765 if (!(jack_data = jack_data_alloc()))
766 return -1;
767
768 if (!ast_strlen_zero(data) && handle_options(jack_data, data)) {
770 return -1;
771 }
772
773 if (init_jack_data(chan, jack_data)) {
775 return -1;
776 }
777
780 return -1;
781 }
782
785 return -1;
786 }
787
788 while (!jack_data->stop) {
789 struct ast_frame *f;
790
791 if (ast_waitfor(chan, -1) < 0) {
792 break;
793 }
794
795 f = ast_read(chan);
796 if (!f) {
797 jack_data->stop = 1;
798 continue;
799 }
800
801 switch (f->frametype) {
804 jack_data->stop = 1;
805 break;
806 case AST_FRAME_VOICE:
808 default:
809 break;
810 }
811
812 ast_frfree(f);
813
815 }
816
818
819 return 0;
820}
821
822static void jack_hook_ds_destroy(void *data)
823{
824 struct jack_data *jack_data = data;
825
827}
828
830 .type = "JACK_HOOK",
831 .destroy = jack_hook_ds_destroy,
832};
833
834static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan,
835 struct ast_frame *frame, enum ast_audiohook_direction direction)
836{
837 struct ast_datastore *datastore;
838 struct jack_data *jack_data;
839
841 return 0;
842
844 return 0;
845
846 if (frame->frametype != AST_FRAME_VOICE)
847 return 0;
848
849 ast_channel_lock(chan);
850
851 if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
852 ast_log(LOG_ERROR, "JACK_HOOK datastore not found for '%s'\n", ast_channel_name(chan));
853 ast_channel_unlock(chan);
854 return -1;
855 }
856
857 jack_data = datastore->data;
858
860 ast_log(LOG_WARNING, "Expected frame in %s for the audiohook, but got format %s\n",
863 ast_channel_unlock(chan);
864 return 0;
865 }
866
868
869 handle_jack_audio(chan, jack_data, frame);
870
871 ast_channel_unlock(chan);
872
873 return 0;
874}
875
876static int enable_jack_hook(struct ast_channel *chan, char *data)
877{
878 struct ast_datastore *datastore;
879 struct jack_data *jack_data = NULL;
881 AST_APP_ARG(mode);
883 );
884
886
887 ast_channel_lock(chan);
888
889 if ((datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
890 ast_log(LOG_ERROR, "JACK_HOOK already enabled for '%s'\n", ast_channel_name(chan));
891 goto return_error;
892 }
893
894 if (ast_strlen_zero(args.mode) || strcasecmp(args.mode, "manipulate")) {
895 ast_log(LOG_ERROR, "'%s' is not a supported mode. Only manipulate is supported.\n",
896 S_OR(args.mode, "<none>"));
897 goto return_error;
898 }
899
900 if (!(jack_data = jack_data_alloc()))
901 goto return_error;
902
903 if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options))
904 goto return_error;
905
906 if (init_jack_data(chan, jack_data))
907 goto return_error;
908
909 if (!(datastore = ast_datastore_alloc(&jack_hook_ds_info, NULL)))
910 goto return_error;
911
915
916 datastore->data = jack_data;
917
919 goto return_error;
920
921 if (ast_channel_datastore_add(chan, datastore))
922 goto return_error;
923
924 ast_channel_unlock(chan);
925
926 return 0;
927
928return_error:
929 ast_channel_unlock(chan);
930
931 if (jack_data) {
933 }
934
935 if (datastore) {
936 datastore->data = NULL;
937 ast_datastore_free(datastore);
938 }
939
940 return -1;
941}
942
943static int disable_jack_hook(struct ast_channel *chan)
944{
945 struct ast_datastore *datastore;
946 struct jack_data *jack_data;
947
948 ast_channel_lock(chan);
949
950 if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
951 ast_channel_unlock(chan);
952 ast_log(LOG_WARNING, "No JACK_HOOK found to disable\n");
953 return -1;
954 }
955
956 ast_channel_datastore_remove(chan, datastore);
957
958 jack_data = datastore->data;
960
961 /* Keep the channel locked while we destroy the datastore, so that we can
962 * ensure that all of the jack stuff is stopped just in case another frame
963 * tries to come through the audiohook callback. */
964 ast_datastore_free(datastore);
965
966 ast_channel_unlock(chan);
967
968 return 0;
969}
970
971static int jack_hook_write(struct ast_channel *chan, const char *cmd, char *data,
972 const char *value)
973{
974 int res;
975
976 if (!chan) {
977 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
978 return -1;
979 }
980
981 if (!strcasecmp(value, "on"))
982 res = enable_jack_hook(chan, data);
983 else if (!strcasecmp(value, "off"))
984 res = disable_jack_hook(chan);
985 else {
986 ast_log(LOG_ERROR, "'%s' is not a valid value for JACK_HOOK()\n", value);
987 res = -1;
988 }
989
990 return res;
991}
992
994 .name = "JACK_HOOK",
995 .synopsis = "Enable a jack hook on a channel",
996 .syntax = "JACK_HOOK(<mode>,[options])",
997 .desc =
998 " The JACK_HOOK allows turning on or off jack connectivity to this channel.\n"
999 "When the JACK_HOOK is turned on, jack ports will get created that allow\n"
1000 "access to the audio stream for this channel. The mode specifies which mode\n"
1001 "this hook should run in. A mode must be specified when turning the JACK_HOOK.\n"
1002 "on. However, all arguments are optional when turning it off.\n"
1003 "\n"
1004 " Valid modes are:\n"
1005#if 0
1006 /* XXX TODO */
1007 " spy - Create a read-only audio hook. Only an output jack port will\n"
1008 " get created.\n"
1009 " whisper - Create a write-only audio hook. Only an input jack port will\n"
1010 " get created.\n"
1011#endif
1012 " manipulate - Create a read/write audio hook. Both an input and an output\n"
1013 " jack port will get created. Audio from the channel will be\n"
1014 " sent out the output port and will be replaced by the audio\n"
1015 " coming in on the input port as it gets passed on.\n"
1016 "\n"
1017 " Valid options are:\n"
1019 "\n"
1020 " Examples:\n"
1021 " To turn on the JACK_HOOK,\n"
1022 " Set(JACK_HOOK(manipulate,i(pure_data_0:input0)o(pure_data_0:output0))=on)\n"
1023 " To turn off the JACK_HOOK,\n"
1024 " Set(JACK_HOOK()=off)\n"
1025 "",
1026 .write = jack_hook_write,
1027};
1028
1029static int unload_module(void)
1030{
1031 int res;
1032
1035
1036 return res;
1037}
1038
1039static int load_module(void)
1040{
1043 }
1044
1048 }
1049
1051}
1052
static struct jack_data * destroy_jack_data(struct jack_data *jack_data)
Definition: app_jack.c:346
static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
Definition: app_jack.c:540
static int jack_process(jack_nframes_t nframes, void *arg)
Definition: app_jack.c:322
static const struct @27 jack_status_table[]
static void handle_output(void *buf, jack_nframes_t nframes, struct jack_data *jack_data)
Handle jack output port.
Definition: app_jack.c:307
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "JACK Interface")
#define COMMON_OPTIONS
Common options between the Jack() app and JACK_HOOK() function.
Definition: app_jack.c:67
static const struct ast_datastore_info jack_hook_ds_info
Definition: app_jack.c:829
static const char * jack_status_to_str(jack_status_t status)
Definition: app_jack.c:165
static int disable_jack_hook(struct ast_channel *chan)
Definition: app_jack.c:943
static void handle_input(void *buf, jack_nframes_t nframes, struct jack_data *jack_data)
Handle jack input port.
Definition: app_jack.c:244
@ OPT_CLIENT_NAME
Definition: app_jack.c:675
@ OPT_SERVER_NAME
Definition: app_jack.c:671
@ OPT_INPUT_PORT
Definition: app_jack.c:672
@ OPT_OUTPUT_PORT
Definition: app_jack.c:673
@ OPT_NOSTART_SERVER
Definition: app_jack.c:674
static int enable_jack_hook(struct ast_channel *chan, char *data)
Definition: app_jack.c:876
static void jack_hook_ds_destroy(void *data)
Definition: app_jack.c:822
static int handle_options(struct jack_data *jack_data, const char *__options_str)
Definition: app_jack.c:710
static struct ast_custom_function jack_hook_function
Definition: app_jack.c:993
static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
Definition: app_jack.c:393
static struct jack_data * jack_data_alloc(void)
Definition: app_jack.c:696
static int jack_exec(struct ast_channel *chan, const char *data)
Definition: app_jack.c:761
static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
Definition: app_jack.c:834
#define RINGBUFFER_FRAME_CAPACITY
Definition: app_jack.c:64
static int jack_hook_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: app_jack.c:971
static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data, struct ast_frame *out_frame)
handle jack audio
Definition: app_jack.c:622
#define RESAMPLE_QUALITY
Definition: app_jack.c:61
static void jack_shutdown(void *arg)
Definition: app_jack.c:339
@ OPT_ARG_CLIENT_NAME
Definition: app_jack.c:682
@ OPT_ARG_SERVER_NAME
Definition: app_jack.c:679
@ OPT_ARG_OUTPUT_PORT
Definition: app_jack.c:681
@ OPT_ARG_INPUT_PORT
Definition: app_jack.c:680
@ OPT_ARG_ARRAY_SIZE
Definition: app_jack.c:685
static void log_jack_status(const char *prefix, jack_status_t status)
Definition: app_jack.c:177
jack_status_t status
Definition: app_jack.c:149
static int load_module(void)
Definition: app_jack.c:1039
static const struct ast_app_option jack_exec_options[128]
Definition: app_jack.c:694
static int unload_module(void)
Definition: app_jack.c:1029
static const char jack_app[]
Definition: app_jack.c:120
static int alloc_resampler(struct jack_data *jack_data, int input)
Definition: app_jack.c:196
const char * str
Definition: app_jack.c:150
option_args
Definition: app_skel.c:184
struct sla_ringing_trunk * first
Definition: app_sla.c:338
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1570
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
Audiohooks Architecture.
@ AST_AUDIOHOOK_MANIPULATE_ALL_RATES
Definition: audiohook.h:75
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
Definition: audiohook.c:100
ast_audiohook_direction
Definition: audiohook.h:48
@ AST_AUDIOHOOK_DIRECTION_READ
Definition: audiohook.h:49
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:578
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:512
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:124
@ AST_AUDIOHOOK_TYPE_MANIPULATE
Definition: audiohook.h:38
@ AST_AUDIOHOOK_STATUS_DONE
Definition: audiohook.h:45
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2414
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2423
#define ast_channel_lock(chan)
Definition: channel.h:2970
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3190
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:5161
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4274
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5779
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
Definition: channel.c:5820
#define ast_channel_unlock(chan)
Definition: channel.h:2971
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2428
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Media Format Cache API.
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:512
direction
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static char prefix[MAX_PREFIX]
Definition: http.c:144
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define END_OPTIONS
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define BEGIN_OPTIONS
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3066
#define ast_frfree(fr)
@ AST_FRAME_VOICE
@ AST_FRAME_CONTROL
@ AST_CONTROL_HANGUP
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
Asterisk locking-related definitions:
Asterisk module definitions.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
Core PBX routines and definitions.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1559
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#define NULL
Definition: resample.c:96
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:341
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:432
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:303
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:521
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
#define ast_str_alloca(init_len)
Definition: strings.h:848
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
ast_audiohook_manipulate_callback manipulate_callback
Definition: audiohook.h:118
enum ast_audiohook_status status
Definition: audiohook.h:108
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
Structure used to handle boolean flags.
Definition: utils.h:199
Definition of a media format.
Definition: format.c:43
struct ast_format * format
Data structure associated with a single frame of data.
union ast_frame::@228 data
struct ast_frame_subclass subclass
enum ast_frame_type frametype
Support for dynamic strings.
Definition: strings.h:623
jack_ringbuffer_t * input_rb
Definition: app_jack.c:132
unsigned int stop
Definition: app_jack.c:141
jack_port_t * output_port
Definition: app_jack.c:131
double output_resample_factor
Definition: app_jack.c:138
struct ast_format * audiohook_format
Definition: app_jack.c:134
const ast_string_field client_name
Definition: app_jack.c:128
void * input_resampler
Definition: app_jack.c:139
const ast_string_field connect_input_port
Definition: app_jack.c:128
double input_resample_factor
Definition: app_jack.c:140
jack_ringbuffer_t * output_rb
Definition: app_jack.c:133
void * output_resampler
Definition: app_jack.c:137
unsigned int frame_datalen
Definition: app_jack.c:136
const ast_string_field connect_output_port
Definition: app_jack.c:128
unsigned int no_start_server
Definition: app_jack.c:143
struct ast_audiohook audiohook
Definition: app_jack.c:145
const ast_string_field server_name
Definition: app_jack.c:128
unsigned int has_audiohook
Definition: app_jack.c:142
unsigned int audiohook_rate
Definition: app_jack.c:135
jack_port_t * input_port
Definition: app_jack.c:130
jack_client_t * client
Definition: app_jack.c:129
int value
Definition: syslog.c:37
const char * args
static struct test_options options
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ARRAY_LEN(a)
Definition: utils.h:666