Asterisk - The Open Source Telephony Project GIT-master-3dae2cf
chan_console.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2006 - 2008, Digium, Inc.
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 Cross-platform console channel driver
22 *
23 * \author Russell Bryant <russell@digium.com>
24 *
25 * \note Some of the code in this file came from chan_oss and chan_alsa.
26 * chan_oss, Mark Spencer <markster@digium.com>
27 * chan_oss, Luigi Rizzo
28 * chan_alsa, Matthew Fredrickson <creslin@digium.com>
29 *
30 * \ingroup channel_drivers
31 *
32 * Portaudio http://www.portaudio.com/
33 *
34 * To install portaudio v19 from svn, check it out using the following command:
35 * - svn co https://www.portaudio.com/repos/portaudio/branches/v19-devel
36 *
37 * \note Since this works with any audio system that libportaudio supports,
38 * including ALSA and OSS, it has come to replace the deprecated chan_alsa and
39 * chan_oss. However, the following features *at least* need to be implemented
40 * here for this to be a full replacement:
41 *
42 * - Set Auto-answer from the dialplan
43 * - transfer CLI command
44 * - boost CLI command and .conf option
45 * - console_video support
46 */
47
48/*! \li \ref chan_console.c uses the configuration file \ref console.conf
49 * \addtogroup configuration_file
50 */
51
52/*! \page console.conf console.conf
53 * \verbinclude console.conf.sample
54 */
55
56/*** MODULEINFO
57 <depend>portaudio</depend>
58 <support_level>extended</support_level>
59 ***/
60
61#include "asterisk.h"
62
63#include <signal.h> /* SIGURG */
64
65#include <portaudio.h>
66
67#include "asterisk/module.h"
68#include "asterisk/channel.h"
69#include "asterisk/pbx.h"
70#include "asterisk/causes.h"
71#include "asterisk/cli.h"
73#include "asterisk/callerid.h"
74#include "asterisk/astobj2.h"
77
78/*!
79 * \brief The sample rate to request from PortAudio
80 *
81 * \todo Make this optional. If this is only going to talk to 8 kHz endpoints,
82 * then it makes sense to use 8 kHz natively.
83 */
84#define SAMPLE_RATE 16000
85
86/*!
87 * \brief The number of samples to configure the portaudio stream for
88 *
89 * 320 samples (20 ms) is the most common frame size in Asterisk. So, the code
90 * in this module reads 320 sample frames from the portaudio stream and queues
91 * them up on the Asterisk channel. Frames of any size can be written to a
92 * portaudio stream, but the portaudio documentation does say that for high
93 * performance applications, the data should be written to Pa_WriteStream in
94 * the same size as what is used to initialize the stream.
95 */
96#define NUM_SAMPLES 320
97
98/*! \brief Mono Input */
99#define INPUT_CHANNELS 1
100
101/*! \brief Mono Output */
102#define OUTPUT_CHANNELS 1
103
104/*!
105 * \brief Maximum text message length
106 * \note This should be changed if there is a common definition somewhere
107 * that defines the maximum length of a text message.
108 */
109#define TEXT_SIZE 256
110
111/*! \brief Dance, Kirby, Dance! @{ */
112#define V_BEGIN " --- <(\"<) --- "
113#define V_END " --- (>\")> ---\n"
114/*! @} */
115
116static const char config_file[] = "console.conf";
117
118/*!
119 * \brief Console pvt structure
120 *
121 * Currently, this is a singleton object. However, multiple instances will be
122 * needed when this module is updated for multiple device support.
123 */
124static struct console_pvt {
126 /*! Name of the device */
130 /*! Default context for outgoing calls */
132 /*! Default extension for outgoing calls */
134 /*! Default CallerID number */
136 /*! Default CallerID name */
138 /*! Default MOH class to listen to, if:
139 * - No MOH class set on the channel
140 * - Peer channel putting this device on hold did not suggest a class */
142 /*! Default language */
144 /*! Default parkinglot */
146 );
147 /*! Current channel for this device */
149 /*! Current PortAudio stream for this device */
150 PaStream *stream;
151 /*! A frame for preparing to queue on to the channel */
152 struct ast_frame fr;
153 /*! Running = 1, Not running = 0 */
154 unsigned int streamstate:1;
155 /*! Abort stream processing? */
156 unsigned int abort:1;
157 /*! On-hook = 0, Off-hook = 1 */
158 unsigned int hookstate:1;
159 /*! Unmuted = 0, Muted = 1 */
160 unsigned int muted:1;
161 /*! Automatically answer incoming calls */
162 unsigned int autoanswer:1;
163 /*! Ignore context in the console dial CLI command */
164 unsigned int overridecontext:1;
165 /*! Set during a reload so that we know to destroy this if it is no longer
166 * in the configuration file. */
167 unsigned int destroy:1;
168 /*! ID for the stream monitor thread */
169 pthread_t thread;
171
173
174static struct ao2_container *pvts;
175#define NUM_PVT_BUCKETS 7
176
177static struct console_pvt *active_pvt;
179
180/*!
181 * \brief Global jitterbuffer configuration
182 *
183 * \note Disabled by default.
184 * \note Values shown here match the defaults shown in console.conf.sample
185 */
187 .flags = 0,
188 .max_size = 200,
189 .resync_threshold = 1000,
190 .impl = "fixed",
191 .target_extra = 40,
192};
194
195/*! Channel Technology Callbacks @{ */
196static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap,
197 const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
198static int console_digit_begin(struct ast_channel *c, char digit);
199static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration);
200static int console_text(struct ast_channel *c, const char *text);
201static int console_hangup(struct ast_channel *c);
202static int console_answer(struct ast_channel *c);
203static struct ast_frame *console_read(struct ast_channel *chan);
204static int console_call(struct ast_channel *c, const char *dest, int timeout);
205static int console_write(struct ast_channel *chan, struct ast_frame *f);
206static int console_indicate(struct ast_channel *chan, int cond,
207 const void *data, size_t datalen);
208static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
209/*! @} */
210
212 .type = "Console",
213 .description = "Console Channel Driver",
214 .requester = console_request,
215 .send_digit_begin = console_digit_begin,
216 .send_digit_end = console_digit_end,
217 .send_text = console_text,
218 .hangup = console_hangup,
219 .answer = console_answer,
220 .read = console_read,
221 .call = console_call,
222 .write = console_write,
223 .indicate = console_indicate,
224 .fixup = console_fixup,
225};
226
227/*! \brief lock a console_pvt struct */
228#define console_pvt_lock(pvt) ao2_lock(pvt)
229
230/*! \brief unlock a console_pvt struct */
231#define console_pvt_unlock(pvt) ao2_unlock(pvt)
232
233static inline struct console_pvt *ref_pvt(struct console_pvt *pvt)
234{
235 if (pvt)
236 ao2_ref(pvt, +1);
237 return pvt;
238}
239
240static inline struct console_pvt *unref_pvt(struct console_pvt *pvt)
241{
242 ao2_ref(pvt, -1);
243 return NULL;
244}
245
246static struct console_pvt *find_pvt(const char *name)
247{
248 struct console_pvt tmp_pvt = {
249 .name = name,
250 };
251
252 return ao2_find(pvts, &tmp_pvt, OBJ_POINTER);
253}
254
255/*!
256 * \brief Stream monitor thread
257 *
258 * \arg data A pointer to the console_pvt structure that contains the portaudio
259 * stream that needs to be monitored.
260 *
261 * This function runs in its own thread to monitor data coming in from a
262 * portaudio stream. When enough data is available, it is queued up to
263 * be read from the Asterisk channel.
264 */
265static void *stream_monitor(void *data)
266{
267 struct console_pvt *pvt = data;
268 char buf[NUM_SAMPLES * sizeof(int16_t)];
269 PaError res;
270 struct ast_frame f = {
272 .subclass.format = ast_format_slin16,
273 .src = "console_stream_monitor",
274 .data.ptr = buf,
275 .datalen = sizeof(buf),
276 .samples = sizeof(buf) / sizeof(int16_t),
277 };
278
279 for (;;) {
280 console_pvt_lock(pvt);
281 res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
283
284 if (!pvt->owner || pvt->abort) {
285 return NULL;
286 }
287
288 if (res == paNoError) {
289 ast_queue_frame(pvt->owner, &f);
290 } else {
291 ast_log(LOG_WARNING, "Console ReadStream failed: %s\n", Pa_GetErrorText(res));
292 }
293 }
294
295 return NULL;
296}
297
298static int open_stream(struct console_pvt *pvt)
299{
300 int res = paInternalError;
301
302 if (!strcasecmp(pvt->input_device, "default") &&
303 !strcasecmp(pvt->output_device, "default")) {
304 res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
305 paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
306 } else {
307 PaStreamParameters input_params = {
308 .channelCount = 1,
309 .sampleFormat = paInt16,
310 .suggestedLatency = (1.0 / 50.0), /* 20 ms */
311 .device = paNoDevice,
312 };
313 PaStreamParameters output_params = {
314 .channelCount = 1,
315 .sampleFormat = paInt16,
316 .suggestedLatency = (1.0 / 50.0), /* 20 ms */
317 .device = paNoDevice,
318 };
319 PaDeviceIndex idx, num_devices, def_input, def_output;
320
321 if (!(num_devices = Pa_GetDeviceCount()))
322 return res;
323
324 def_input = Pa_GetDefaultInputDevice();
325 def_output = Pa_GetDefaultOutputDevice();
326
327 for (idx = 0;
328 idx < num_devices && (input_params.device == paNoDevice
329 || output_params.device == paNoDevice);
330 idx++)
331 {
332 const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
333
334 if (dev->maxInputChannels) {
335 if ( (idx == def_input && !strcasecmp(pvt->input_device, "default")) ||
336 !strcasecmp(pvt->input_device, dev->name) )
337 input_params.device = idx;
338 }
339
340 if (dev->maxOutputChannels) {
341 if ( (idx == def_output && !strcasecmp(pvt->output_device, "default")) ||
342 !strcasecmp(pvt->output_device, dev->name) )
343 output_params.device = idx;
344 }
345 }
346
347 if (input_params.device == paNoDevice)
348 ast_log(LOG_ERROR, "No input device found for console device '%s'\n", pvt->name);
349 if (output_params.device == paNoDevice)
350 ast_log(LOG_ERROR, "No output device found for console device '%s'\n", pvt->name);
351
352 res = Pa_OpenStream(&pvt->stream, &input_params, &output_params,
353 SAMPLE_RATE, NUM_SAMPLES, paNoFlag, NULL, NULL);
354 }
355
356 return res;
357}
358
359static int start_stream(struct console_pvt *pvt)
360{
361 PaError res;
362 int ret_val = 0;
363
364 console_pvt_lock(pvt);
365
366 /* It is possible for console_hangup to be called before the
367 * stream is started, if this is the case pvt->owner will be NULL
368 * and start_stream should be aborted. */
369 if (pvt->streamstate || !pvt->owner)
370 goto return_unlock;
371
372 pvt->streamstate = 1;
373 ast_debug(1, "Starting stream\n");
374
375 res = open_stream(pvt);
376 if (res != paNoError) {
377 ast_log(LOG_WARNING, "Failed to open stream - (%d) %s\n",
378 res, Pa_GetErrorText(res));
379 ret_val = -1;
380 goto return_unlock;
381 }
382
383 res = Pa_StartStream(pvt->stream);
384 if (res != paNoError) {
385 ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
386 res, Pa_GetErrorText(res));
387 ret_val = -1;
388 goto return_unlock;
389 }
390
392 ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
393 ret_val = -1;
394 }
395
396return_unlock:
398
399 return ret_val;
400}
401
402static int stop_stream(struct console_pvt *pvt)
403{
404 if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
405 return 0;
406
407 pvt->abort = 1;
408 /* Wait for pvt->thread to exit cleanly, to avoid killing it while it's holding a lock. */
409 pthread_kill(pvt->thread, SIGURG); /* Wake it up if needed, but don't cancel it */
410 pthread_join(pvt->thread, NULL);
411
412 console_pvt_lock(pvt);
413 Pa_AbortStream(pvt->stream);
414 Pa_CloseStream(pvt->stream);
415 pvt->stream = NULL;
416 pvt->streamstate = 0;
418
419 return 0;
420}
421
422/*!
423 * \note Called with the pvt struct locked
424 */
425static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
426{
427 struct ast_format_cap *caps;
428 struct ast_channel *chan;
429
431 if (!caps) {
432 return NULL;
433 }
434
435 if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL,
436 ext, ctx, assignedids, requestor, 0, "Console/%s", pvt->name))) {
437 ao2_ref(caps, -1);
438 return NULL;
439 }
440
442
448 ao2_ref(caps, -1);
450
451 pvt->owner = chan;
452
453 if (!ast_strlen_zero(pvt->language))
454 ast_channel_language_set(chan, pvt->language);
455
457
459 ast_channel_unlock(chan);
460
461 if (state != AST_STATE_DOWN) {
462 if (ast_pbx_start(chan)) {
464 ast_hangup(chan);
465 chan = NULL;
466 } else
467 start_stream(pvt);
468 }
469
470 return chan;
471}
472
473static struct ast_channel *console_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
474{
475 struct ast_channel *chan = NULL;
476 struct console_pvt *pvt;
477
478 if (!(pvt = find_pvt(data))) {
479 ast_log(LOG_ERROR, "Console device '%s' not found\n", data);
480 return NULL;
481 }
482
485 ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n",
486 ast_format_cap_get_names(cap, &cap_buf));
487 goto return_unref;
488 }
489
490 if (pvt->owner) {
491 ast_log(LOG_NOTICE, "Console channel already active!\n");
492 *cause = AST_CAUSE_BUSY;
493 goto return_unref;
494 }
495
496 console_pvt_lock(pvt);
497 chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN, assignedids, requestor);
499
500 if (!chan)
501 ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
502
503return_unref:
504 unref_pvt(pvt);
505
506 return chan;
507}
508
509static int console_digit_begin(struct ast_channel *c, char digit)
510{
511 ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
512
513 return -1; /* non-zero to request inband audio */
514}
515
516static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
517{
518 ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END,
519 digit, duration);
520
521 return -1; /* non-zero to request inband audio */
522}
523
524static int console_text(struct ast_channel *c, const char *text)
525{
526 ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
527
528 return 0;
529}
530
531static int console_hangup(struct ast_channel *c)
532{
533 struct console_pvt *pvt = ast_channel_tech_pvt(c);
534
535 ast_verb(1, V_BEGIN "Hangup on Console" V_END);
536
537 pvt->hookstate = 0;
538 pvt->owner = NULL;
539 stop_stream(pvt);
540
542
543 return 0;
544}
545
546static int console_answer(struct ast_channel *c)
547{
548 struct console_pvt *pvt = ast_channel_tech_pvt(c);
549
550 ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
551
553
554 return start_stream(pvt);
555}
556
557/*!
558 * \brief Implementation of the ast_channel_tech read() callback
559 *
560 * Calling this function is harmless. However, if it does get called, it
561 * is an indication that something weird happened that really shouldn't
562 * have and is worth looking into.
563 *
564 * Why should this function not get called? Well, let me explain. There are
565 * a couple of ways to pass on audio that has come from this channel. The way
566 * that this channel driver uses is that once the audio is available, it is
567 * wrapped in an ast_frame and queued onto the channel using ast_queue_frame().
568 *
569 * The other method would be signalling to the core that there is audio waiting,
570 * and that it needs to call the channel's read() callback to get it. The way
571 * the channel gets signalled is that one or more file descriptors are placed
572 * in the fds array on the ast_channel which the core will poll() on. When the
573 * fd indicates that input is available, the read() callback is called. This
574 * is especially useful when there is a dedicated file descriptor where the
575 * audio is read from. An example would be the socket for an RTP stream.
576 */
577static struct ast_frame *console_read(struct ast_channel *chan)
578{
579 ast_debug(1, "I should not be called ...\n");
580
581 return &ast_null_frame;
582}
583
584static int console_call(struct ast_channel *c, const char *dest, int timeout)
585{
586 struct console_pvt *pvt = ast_channel_tech_pvt(c);
587 enum ast_control_frame_type ctrl;
588
589 ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
590 dest,
591 S_COR(ast_channel_caller(c)->id.name.valid, ast_channel_caller(c)->id.name.str, ""),
592 S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, ""));
593
594 console_pvt_lock(pvt);
595
596 if (pvt->autoanswer) {
597 pvt->hookstate = 1;
599 ast_verb(1, V_BEGIN "Auto-answered" V_END);
600 ctrl = AST_CONTROL_ANSWER;
601 } else {
603 ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
604 "for future calls" V_END);
605 ctrl = AST_CONTROL_RINGING;
607 }
608
609 ast_queue_control(c, ctrl);
610
611 return start_stream(pvt);
612}
613
614static int console_write(struct ast_channel *chan, struct ast_frame *f)
615{
616 struct console_pvt *pvt = ast_channel_tech_pvt(chan);
617
618 console_pvt_lock(pvt);
619 Pa_WriteStream(pvt->stream, f->data.ptr, f->samples);
621
622 return 0;
623}
624
625static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
626{
627 struct console_pvt *pvt = ast_channel_tech_pvt(chan);
628 int res = 0;
629
630 switch (cond) {
631 case AST_CONTROL_BUSY:
636 case -1:
637 res = -1; /* Ask for inband indications */
638 break;
643 break;
644 case AST_CONTROL_HOLD:
645 ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
646 ast_moh_start(chan, data, pvt->mohinterpret);
647 break;
649 ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
650 ast_moh_stop(chan);
651 break;
652 default:
653 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n",
654 cond, ast_channel_name(chan));
655 /* The core will play inband indications for us if appropriate */
656 res = -1;
657 }
658
659 return res;
660}
661
662static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
663{
664 struct console_pvt *pvt = ast_channel_tech_pvt(newchan);
665
666 pvt->owner = newchan;
667
668 return 0;
669}
670
671/*!
672 * split a string in extension-context, returns pointers to malloc'ed
673 * strings.
674 * If we do not have 'overridecontext' then the last @ is considered as
675 * a context separator, and the context is overridden.
676 * This is usually not very necessary as you can play with the dialplan,
677 * and it is nice not to need it because you have '@' in SIP addresses.
678 * Return value is the buffer address.
679 *
680 * \note came from chan_oss
681 */
682static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
683{
684 if (ext == NULL || ctx == NULL)
685 return NULL; /* error */
686
687 *ext = *ctx = NULL;
688
689 if (src && *src != '\0')
690 *ext = ast_strdup(src);
691
692 if (*ext == NULL)
693 return NULL;
694
695 if (!pvt->overridecontext) {
696 /* parse from the right */
697 *ctx = strrchr(*ext, '@');
698 if (*ctx)
699 *(*ctx)++ = '\0';
700 }
701
702 return *ext;
703}
704
705static struct console_pvt *get_active_pvt(void)
706{
707 struct console_pvt *pvt;
708
710 pvt = ref_pvt(active_pvt);
712
713 return pvt;
714}
715
716static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd,
717 struct ast_cli_args *a)
718{
719 struct console_pvt *pvt;
720 char *res = CLI_SUCCESS;
721
722 switch (cmd) {
723 case CLI_INIT:
724 e->command = "console {set|show} autoanswer [on|off]";
725 e->usage =
726 "Usage: console {set|show} autoanswer [on|off]\n"
727 " Enables or disables autoanswer feature. If used without\n"
728 " argument, displays the current on/off status of autoanswer.\n"
729 " The default value of autoanswer is in 'oss.conf'.\n";
730 return NULL;
731
732 case CLI_GENERATE:
733 return NULL;
734 }
735
736 pvt = get_active_pvt();
737 if (!pvt) {
738 ast_cli(a->fd, "No console device is set as active.\n");
739 return CLI_FAILURE;
740 }
741
742 if (a->argc == e->args - 1) {
743 ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
744 unref_pvt(pvt);
745 return CLI_SUCCESS;
746 }
747
748 if (a->argc != e->args) {
749 unref_pvt(pvt);
750 return CLI_SHOWUSAGE;
751 }
752
753 if (!strcasecmp(a->argv[e->args-1], "on"))
754 pvt->autoanswer = 1;
755 else if (!strcasecmp(a->argv[e->args - 1], "off"))
756 pvt->autoanswer = 0;
757 else
758 res = CLI_SHOWUSAGE;
759
760 unref_pvt(pvt);
761
762 return res;
763}
764
765static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
766{
767 struct console_pvt *pvt;
768
769 if (cmd == CLI_INIT) {
770 e->command = "console flash";
771 e->usage =
772 "Usage: console flash\n"
773 " Flashes the call currently placed on the console.\n";
774 return NULL;
775 } else if (cmd == CLI_GENERATE) {
776 return NULL;
777 }
778
779 if (a->argc != e->args) {
780 return CLI_SHOWUSAGE;
781 }
782
783 pvt = get_active_pvt();
784 if (!pvt) {
785 ast_cli(a->fd, "No console device is set as active\n");
786 return CLI_FAILURE;
787 }
788
789 if (!pvt->owner) {
790 ast_cli(a->fd, "No call to flash\n");
791 unref_pvt(pvt);
792 return CLI_FAILURE;
793 }
794
795 pvt->hookstate = 0;
796
798
799 unref_pvt(pvt);
800
801 return CLI_SUCCESS;
802}
803
804static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
805{
806 char *s = NULL;
807 const char *mye = NULL, *myc = NULL;
808 struct console_pvt *pvt;
809
810 if (cmd == CLI_INIT) {
811 e->command = "console dial";
812 e->usage =
813 "Usage: console dial [extension[@context]]\n"
814 " Dials a given extension (and context if specified)\n";
815 return NULL;
816 } else if (cmd == CLI_GENERATE) {
817 return NULL;
818 }
819
820 if (a->argc > e->args + 1) {
821 return CLI_SHOWUSAGE;
822 }
823
824 pvt = get_active_pvt();
825 if (!pvt) {
826 ast_cli(a->fd, "No console device is currently set as active\n");
827 return CLI_FAILURE;
828 }
829
830 if (pvt->owner) { /* already in a call */
831 int i;
832 struct ast_frame f = { AST_FRAME_DTMF };
833 const char *s;
834
835 if (a->argc == e->args) { /* argument is mandatory here */
836 ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
837 unref_pvt(pvt);
838 return CLI_FAILURE;
839 }
840 s = a->argv[e->args];
841 /* send the string one char at a time */
842 for (i = 0; i < strlen(s); i++) {
843 f.subclass.integer = s[i];
844 ast_queue_frame(pvt->owner, &f);
845 }
846 unref_pvt(pvt);
847 return CLI_SUCCESS;
848 }
849
850 /* if we have an argument split it into extension and context */
851 if (a->argc == e->args + 1) {
852 char *ext = NULL, *con = NULL;
853 s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
854 mye = ext;
855 myc = con;
856 ast_debug(1, "provided '%s', exten '%s' context '%s'\n",
857 a->argv[e->args], mye, myc);
858 }
859
860 /* supply default values if needed */
861 if (ast_strlen_zero(mye))
862 mye = pvt->exten;
863 if (ast_strlen_zero(myc))
864 myc = pvt->context;
865
866 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
867 console_pvt_lock(pvt);
868 pvt->hookstate = 1;
869 console_new(pvt, mye, myc, AST_STATE_RINGING, NULL, NULL);
871 } else
872 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
873
874 ast_free(s);
875
876 unref_pvt(pvt);
877
878 return CLI_SUCCESS;
879}
880
881static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
882{
883 struct console_pvt *pvt;
884
885 if (cmd == CLI_INIT) {
886 e->command = "console hangup";
887 e->usage =
888 "Usage: console hangup\n"
889 " Hangs up any call currently placed on the console.\n";
890 return NULL;
891 } else if (cmd == CLI_GENERATE) {
892 return NULL;
893 }
894
895 if (a->argc != e->args) {
896 return CLI_SHOWUSAGE;
897 }
898
899 pvt = get_active_pvt();
900 if (!pvt) {
901 ast_cli(a->fd, "No console device is set as active\n");
902 return CLI_FAILURE;
903 }
904
905 if (!pvt->owner && !pvt->hookstate) {
906 ast_cli(a->fd, "No call to hang up\n");
907 unref_pvt(pvt);
908 return CLI_FAILURE;
909 }
910
911 pvt->hookstate = 0;
912 if (pvt->owner)
914
915 unref_pvt(pvt);
916
917 return CLI_SUCCESS;
918}
919
920static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
921{
922 const char *s;
923 struct console_pvt *pvt;
924 char *res = CLI_SUCCESS;
925
926 if (cmd == CLI_INIT) {
927 e->command = "console {mute|unmute}";
928 e->usage =
929 "Usage: console {mute|unmute}\n"
930 " Mute/unmute the microphone.\n";
931 return NULL;
932 } else if (cmd == CLI_GENERATE) {
933 return NULL;
934 }
935
936 if (a->argc != e->args) {
937 return CLI_SHOWUSAGE;
938 }
939
940 pvt = get_active_pvt();
941 if (!pvt) {
942 ast_cli(a->fd, "No console device is set as active\n");
943 return CLI_FAILURE;
944 }
945
946 s = a->argv[e->args-1];
947 if (!strcasecmp(s, "mute"))
948 pvt->muted = 1;
949 else if (!strcasecmp(s, "unmute"))
950 pvt->muted = 0;
951 else
952 res = CLI_SHOWUSAGE;
953
954 ast_verb(1, V_BEGIN "The Console is now %s" V_END,
955 pvt->muted ? "Muted" : "Unmuted");
956
957 unref_pvt(pvt);
958
959 return res;
960}
961
962static char *cli_list_available(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
963{
964 PaDeviceIndex idx, num, def_input, def_output;
965
966 if (cmd == CLI_INIT) {
967 e->command = "console list available";
968 e->usage =
969 "Usage: console list available\n"
970 " List all available devices.\n";
971 return NULL;
972 } else if (cmd == CLI_GENERATE)
973 return NULL;
974
975 if (a->argc != e->args)
976 return CLI_SHOWUSAGE;
977
978 ast_cli(a->fd, "\n"
979 "=============================================================\n"
980 "=== Available Devices =======================================\n"
981 "=============================================================\n"
982 "===\n");
983
984 num = Pa_GetDeviceCount();
985 if (!num) {
986 ast_cli(a->fd, "(None)\n");
987 return CLI_SUCCESS;
988 }
989
990 def_input = Pa_GetDefaultInputDevice();
991 def_output = Pa_GetDefaultOutputDevice();
992 for (idx = 0; idx < num; idx++) {
993 const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
994 if (!dev)
995 continue;
996 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
997 "=== Device Name: %s\n", dev->name);
998 if (dev->maxInputChannels)
999 ast_cli(a->fd, "=== ---> %sInput Device\n", (idx == def_input) ? "Default " : "");
1000 if (dev->maxOutputChannels)
1001 ast_cli(a->fd, "=== ---> %sOutput Device\n", (idx == def_output) ? "Default " : "");
1002 ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
1003 }
1004
1005 ast_cli(a->fd, "=============================================================\n\n");
1006
1007 return CLI_SUCCESS;
1008}
1009
1010static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1011{
1012 struct ao2_iterator i;
1013 struct console_pvt *pvt;
1014
1015 if (cmd == CLI_INIT) {
1016 e->command = "console list devices";
1017 e->usage =
1018 "Usage: console list devices\n"
1019 " List all configured devices.\n";
1020 return NULL;
1021 } else if (cmd == CLI_GENERATE)
1022 return NULL;
1023
1024 if (a->argc != e->args)
1025 return CLI_SHOWUSAGE;
1026
1027 ast_cli(a->fd, "\n"
1028 "=============================================================\n"
1029 "=== Configured Devices ======================================\n"
1030 "=============================================================\n"
1031 "===\n");
1032
1033 i = ao2_iterator_init(pvts, 0);
1034 while ((pvt = ao2_iterator_next(&i))) {
1035 console_pvt_lock(pvt);
1036
1037 ast_cli(a->fd, "=== ---------------------------------------------------------\n"
1038 "=== Device Name: %s\n"
1039 "=== ---> Active: %s\n"
1040 "=== ---> Input Device: %s\n"
1041 "=== ---> Output Device: %s\n"
1042 "=== ---> Context: %s\n"
1043 "=== ---> Extension: %s\n"
1044 "=== ---> CallerID Num: %s\n"
1045 "=== ---> CallerID Name: %s\n"
1046 "=== ---> MOH Interpret: %s\n"
1047 "=== ---> Language: %s\n"
1048 "=== ---> Parkinglot: %s\n"
1049 "=== ---> Muted: %s\n"
1050 "=== ---> Auto-Answer: %s\n"
1051 "=== ---> Override Context: %s\n"
1052 "=== ---------------------------------------------------------\n===\n",
1053 pvt->name, (pvt == active_pvt) ? "Yes" : "No",
1054 pvt->input_device, pvt->output_device, pvt->context,
1055 pvt->exten, pvt->cid_num, pvt->cid_name, pvt->mohinterpret,
1056 pvt->language, pvt->parkinglot, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
1057 pvt->overridecontext ? "Yes" : "No");
1058
1059 console_pvt_unlock(pvt);
1060 unref_pvt(pvt);
1061 }
1063
1064 ast_cli(a->fd, "=============================================================\n\n");
1065
1066 return CLI_SUCCESS;
1067}
1068/*!
1069 * \brief answer command from the console
1070 */
1071static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1072{
1073 struct console_pvt *pvt;
1074
1075 switch (cmd) {
1076 case CLI_INIT:
1077 e->command = "console answer";
1078 e->usage =
1079 "Usage: console answer\n"
1080 " Answers an incoming call on the console channel.\n";
1081 return NULL;
1082
1083 case CLI_GENERATE:
1084 return NULL; /* no completion */
1085 }
1086
1087 pvt = get_active_pvt();
1088 if (!pvt) {
1089 ast_cli(a->fd, "No console device is set as active\n");
1090 return CLI_FAILURE;
1091 }
1092
1093 if (a->argc != e->args) {
1094 unref_pvt(pvt);
1095 return CLI_SHOWUSAGE;
1096 }
1097
1098 if (!pvt->owner) {
1099 ast_cli(a->fd, "No one is calling us\n");
1100 unref_pvt(pvt);
1101 return CLI_FAILURE;
1102 }
1103
1104 pvt->hookstate = 1;
1105
1106 ast_indicate(pvt->owner, -1);
1107
1109
1110 unref_pvt(pvt);
1111
1112 return CLI_SUCCESS;
1113}
1114
1115/*!
1116 * \brief Console send text CLI command
1117 *
1118 * \note concatenate all arguments into a single string. argv is NULL-terminated
1119 * so we can use it right away
1120 */
1121static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1122{
1123 char buf[TEXT_SIZE];
1124 struct console_pvt *pvt;
1125 struct ast_frame f = {
1127 .data.ptr = buf,
1128 .src = "console_send_text",
1129 };
1130 int len;
1131
1132 if (cmd == CLI_INIT) {
1133 e->command = "console send text";
1134 e->usage =
1135 "Usage: console send text <message>\n"
1136 " Sends a text message for display on the remote terminal.\n";
1137 return NULL;
1138 } else if (cmd == CLI_GENERATE) {
1139 return NULL;
1140 }
1141
1142 pvt = get_active_pvt();
1143 if (!pvt) {
1144 ast_cli(a->fd, "No console device is set as active\n");
1145 return CLI_FAILURE;
1146 }
1147
1148 if (a->argc < e->args + 1) {
1149 unref_pvt(pvt);
1150 return CLI_SHOWUSAGE;
1151 }
1152
1153 if (!pvt->owner) {
1154 ast_cli(a->fd, "Not in a call\n");
1155 unref_pvt(pvt);
1156 return CLI_FAILURE;
1157 }
1158
1159 ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
1160 if (ast_strlen_zero(buf)) {
1161 unref_pvt(pvt);
1162 return CLI_SHOWUSAGE;
1163 }
1164
1165 len = strlen(buf);
1166 buf[len] = '\n';
1167 f.datalen = len + 1;
1168
1169 ast_queue_frame(pvt->owner, &f);
1170
1171 unref_pvt(pvt);
1172
1173 return CLI_SUCCESS;
1174}
1175
1176static void set_active(struct console_pvt *pvt, const char *value)
1177{
1178 if (pvt == &globals) {
1179 ast_log(LOG_ERROR, "active is only valid as a per-device setting\n");
1180 return;
1181 }
1182
1183 if (!ast_true(value))
1184 return;
1185
1187 if (active_pvt)
1189 active_pvt = ref_pvt(pvt);
1191}
1192
1193static char *cli_console_active(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1194{
1195 struct console_pvt *pvt;
1196
1197 switch (cmd) {
1198 case CLI_INIT:
1199 e->command = "console {set|show} active";
1200 e->usage =
1201 "Usage: console {set|show} active [<device>]\n"
1202 " Set or show the active console device for the Asterisk CLI.\n";
1203 return NULL;
1204 case CLI_GENERATE:
1205 if (a->pos == e->args) {
1206 struct ao2_iterator i;
1207 int x = 0;
1208 char *res = NULL;
1209 i = ao2_iterator_init(pvts, 0);
1210 while ((pvt = ao2_iterator_next(&i))) {
1211 if (++x > a->n && !strncasecmp(pvt->name, a->word, strlen(a->word)))
1212 res = ast_strdup(pvt->name);
1213 unref_pvt(pvt);
1214 if (res) {
1216 return res;
1217 }
1218 }
1220 }
1221 return NULL;
1222 }
1223
1224 if (a->argc < e->args)
1225 return CLI_SHOWUSAGE;
1226
1227 if (a->argc == 3) {
1228 pvt = get_active_pvt();
1229
1230 if (!pvt)
1231 ast_cli(a->fd, "No device is currently set as the active console device.\n");
1232 else {
1233 console_pvt_lock(pvt);
1234 ast_cli(a->fd, "The active console device is '%s'.\n", pvt->name);
1235 console_pvt_unlock(pvt);
1236 pvt = unref_pvt(pvt);
1237 }
1238
1239 return CLI_SUCCESS;
1240 }
1241
1242 if (!(pvt = find_pvt(a->argv[e->args]))) {
1243 ast_cli(a->fd, "Could not find a device called '%s'.\n", a->argv[e->args]);
1244 return CLI_FAILURE;
1245 }
1246
1247 set_active(pvt, "yes");
1248
1249 console_pvt_lock(pvt);
1250 ast_cli(a->fd, "The active console device has been set to '%s'\n", pvt->name);
1251 console_pvt_unlock(pvt);
1252
1253 unref_pvt(pvt);
1254
1255 return CLI_SUCCESS;
1256}
1257
1258static struct ast_cli_entry cli_console[] = {
1259 AST_CLI_DEFINE(cli_console_dial, "Dial an extension from the console"),
1260 AST_CLI_DEFINE(cli_console_hangup, "Hangup a call on the console"),
1261 AST_CLI_DEFINE(cli_console_mute, "Disable/Enable mic input"),
1262 AST_CLI_DEFINE(cli_console_answer, "Answer an incoming console call"),
1263 AST_CLI_DEFINE(cli_console_sendtext, "Send text to a connected party"),
1264 AST_CLI_DEFINE(cli_console_flash, "Send a flash to the connected party"),
1265 AST_CLI_DEFINE(cli_console_autoanswer, "Turn autoanswer on or off"),
1266 AST_CLI_DEFINE(cli_list_available, "List available devices"),
1267 AST_CLI_DEFINE(cli_list_devices, "List configured devices"),
1268 AST_CLI_DEFINE(cli_console_active, "View or Set the active console device"),
1269};
1270
1271/*!
1272 * \brief Set default values for a pvt struct
1273 *
1274 * \note This function expects the pvt lock to be held.
1275 */
1276static void set_pvt_defaults(struct console_pvt *pvt)
1277{
1278 if (pvt == &globals) {
1279 ast_string_field_set(pvt, mohinterpret, "default");
1280 ast_string_field_set(pvt, context, "default");
1281 ast_string_field_set(pvt, exten, "s");
1283 ast_string_field_set(pvt, cid_num, "");
1284 ast_string_field_set(pvt, cid_name, "");
1285 ast_string_field_set(pvt, parkinglot, "");
1286
1287 pvt->overridecontext = 0;
1288 pvt->autoanswer = 0;
1289 } else {
1291
1294 ast_string_field_set(pvt, exten, globals.exten);
1296 ast_string_field_set(pvt, cid_num, globals.cid_num);
1297 ast_string_field_set(pvt, cid_name, globals.cid_name);
1298 ast_string_field_set(pvt, parkinglot, globals.parkinglot);
1299
1302
1304 }
1305}
1306
1307static void store_callerid(struct console_pvt *pvt, const char *value)
1308{
1309 char cid_name[256];
1310 char cid_num[256];
1311
1312 ast_callerid_split(value, cid_name, sizeof(cid_name),
1313 cid_num, sizeof(cid_num));
1314
1315 ast_string_field_set(pvt, cid_name, cid_name);
1316 ast_string_field_set(pvt, cid_num, cid_num);
1317}
1318
1319/*!
1320 * \brief Store a configuration parameter in a pvt struct
1321 *
1322 * \note This function expects the pvt lock to be held.
1323 */
1324static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
1325{
1326 if (pvt == &globals && !ast_jb_read_conf(&global_jbconf, var, value))
1327 return;
1328
1329 CV_START(var, value);
1330
1331 CV_STRFIELD("context", pvt, context);
1332 CV_STRFIELD("extension", pvt, exten);
1333 CV_STRFIELD("mohinterpret", pvt, mohinterpret);
1334 CV_STRFIELD("language", pvt, language);
1335 CV_F("callerid", store_callerid(pvt, value));
1336 CV_BOOL("overridecontext", pvt->overridecontext);
1337 CV_BOOL("autoanswer", pvt->autoanswer);
1338 CV_STRFIELD("parkinglot", pvt, parkinglot);
1339
1340 if (pvt != &globals) {
1341 CV_F("active", set_active(pvt, value))
1342 CV_STRFIELD("input_device", pvt, input_device);
1343 CV_STRFIELD("output_device", pvt, output_device);
1344 }
1345
1346 ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
1347
1348 CV_END;
1349}
1350
1351static void pvt_destructor(void *obj)
1352{
1353 struct console_pvt *pvt = obj;
1354
1356}
1357
1358static int init_pvt(struct console_pvt *pvt, const char *name)
1359{
1361
1362 if (ast_string_field_init(pvt, 32))
1363 return -1;
1364
1365 ast_string_field_set(pvt, name, S_OR(name, ""));
1366
1367 return 0;
1368}
1369
1370static void build_device(struct ast_config *cfg, const char *name)
1371{
1372 struct ast_variable *v;
1373 struct console_pvt *pvt;
1374 int new = 0;
1375
1376 if ((pvt = find_pvt(name))) {
1377 console_pvt_lock(pvt);
1378 set_pvt_defaults(pvt);
1379 pvt->destroy = 0;
1380 } else {
1381 if (!(pvt = ao2_alloc(sizeof(*pvt), pvt_destructor)))
1382 return;
1383 init_pvt(pvt, name);
1384 set_pvt_defaults(pvt);
1385 new = 1;
1386 }
1387
1388 for (v = ast_variable_browse(cfg, name); v; v = v->next)
1389 store_config_core(pvt, v->name, v->value);
1390
1391 if (new)
1392 ao2_link(pvts, pvt);
1393 else
1394 console_pvt_unlock(pvt);
1395
1396 unref_pvt(pvt);
1397}
1398
1399static int pvt_mark_destroy_cb(void *obj, void *arg, int flags)
1400{
1401 struct console_pvt *pvt = obj;
1402 pvt->destroy = 1;
1403 return 0;
1404}
1405
1406static void destroy_pvts(void)
1407{
1408 struct ao2_iterator i;
1409 struct console_pvt *pvt;
1410
1411 i = ao2_iterator_init(pvts, 0);
1412 while ((pvt = ao2_iterator_next(&i))) {
1413 if (pvt->destroy) {
1414 ao2_unlink(pvts, pvt);
1416 if (active_pvt == pvt)
1417 active_pvt = unref_pvt(pvt);
1419 }
1420 unref_pvt(pvt);
1421 }
1423}
1424
1425/*!
1426 * \brief Load the configuration
1427 * \param reload if this was called due to a reload
1428 * \retval 0 success
1429 * \retval -1 failure
1430 */
1431static int load_config(int reload)
1432{
1433 struct ast_config *cfg;
1434 struct ast_variable *v;
1435 struct ast_flags config_flags = { 0 };
1436 char *context = NULL;
1437
1438 /* default values */
1439 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
1443
1444 if (!(cfg = ast_config_load(config_file, config_flags))) {
1445 ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
1446 return -1;
1447 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
1448 ast_log(LOG_NOTICE, "Config file %s has an invalid format\n", config_file);
1449 return -1;
1450 }
1451
1453
1455 for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
1458
1459 while ((context = ast_category_browse(cfg, context))) {
1460 if (strcasecmp(context, "general"))
1461 build_device(cfg, context);
1462 }
1463
1464 ast_config_destroy(cfg);
1465
1466 destroy_pvts();
1467
1468 return 0;
1469}
1470
1471static int pvt_hash_cb(const void *obj, const int flags)
1472{
1473 const struct console_pvt *pvt = obj;
1474
1475 return ast_str_case_hash(pvt->name);
1476}
1477
1478static int pvt_cmp_cb(void *obj, void *arg, int flags)
1479{
1480 struct console_pvt *pvt = obj, *pvt2 = arg;
1481
1482 return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH | CMP_STOP : 0;
1483}
1484
1485static void stop_streams(void)
1486{
1487 struct console_pvt *pvt;
1488 struct ao2_iterator i;
1489
1490 i = ao2_iterator_init(pvts, 0);
1491 while ((pvt = ao2_iterator_next(&i))) {
1492 if (pvt->hookstate)
1493 stop_stream(pvt);
1494 unref_pvt(pvt);
1495 }
1497}
1498
1499static int unload_module(void)
1500{
1505
1506 stop_streams();
1507
1508 Pa_Terminate();
1509
1510 /* Will unref all the pvts so they will get destroyed, too */
1511 ao2_ref(pvts, -1);
1512
1514
1515 return 0;
1516}
1517
1518/*!
1519 * \brief Load the module
1520 *
1521 * Module loading including tests for configuration or dependencies.
1522 * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
1523 * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
1524 * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
1525 * configuration file or other non-critical problem return
1526 * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
1527 */
1528static int load_module(void)
1529{
1530 PaError res;
1531
1534 }
1536
1538
1541 if (!pvts)
1542 goto return_error;
1543
1544 if (load_config(0))
1545 goto return_error;
1546
1547 res = Pa_Initialize();
1548 if (res != paNoError) {
1549 ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
1550 res, Pa_GetErrorText(res));
1551 goto return_error_pa_init;
1552 }
1553
1555 ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
1556 goto return_error_chan_reg;
1557 }
1558
1560 goto return_error_cli_reg;
1561
1563
1564return_error_cli_reg:
1566return_error_chan_reg:
1568return_error_pa_init:
1569 Pa_Terminate();
1570return_error:
1571 if (pvts)
1572 ao2_ref(pvts, -1);
1573 pvts = NULL;
1577
1579}
1580
1581static int reload(void)
1582{
1583 return load_config(1);
1584}
1585
1587 .support_level = AST_MODULE_SUPPORT_EXTENDED,
1588 .load = load_module,
1589 .unload = unload_module,
1590 .reload = reload,
1591 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:593
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:545
char digit
char * text
Definition: app_queue.c:1639
ast_cond_t cond
Definition: app_sla.c:330
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_log
Definition: astobj2.c:42
#define ao2_iterator_next(iter)
Definition: astobj2.h:1911
#define ao2_link(container, obj)
Add an object to a container.
Definition: astobj2.h:1532
@ CMP_MATCH
Definition: astobj2.h:1027
@ CMP_STOP
Definition: astobj2.h:1028
#define OBJ_POINTER
Definition: astobj2.h:1150
@ AO2_ALLOC_OPT_LOCK_MUTEX
Definition: astobj2.h:363
#define ao2_callback(c, flags, cb_fn, arg)
ao2_callback() is a generic function that applies cb_fn() to all objects in a container,...
Definition: astobj2.h:1693
#define ao2_unlink(container, obj)
Remove an object from a container.
Definition: astobj2.h:1578
#define ao2_find(container, arg, flags)
Definition: astobj2.h:1736
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
@ OBJ_NODATA
Definition: astobj2.h:1044
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:409
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
Definition: astobj2.h:1303
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1292
Internal Asterisk hangup causes.
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:123
#define AST_CAUSE_BUSY
Definition: causes.h:149
#define V_BEGIN
Dance, Kirby, Dance!
Definition: chan_console.c:112
static struct console_pvt * ref_pvt(struct console_pvt *pvt)
Definition: chan_console.c:233
static char * cli_console_autoanswer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_console.c:716
static char * cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_console.c:881
#define NUM_PVT_BUCKETS
Definition: chan_console.c:175
static int open_stream(struct console_pvt *pvt)
Definition: chan_console.c:298
static void build_device(struct ast_config *cfg, const char *name)
#define console_pvt_lock(pvt)
lock a console_pvt struct
Definition: chan_console.c:228
static void destroy_pvts(void)
static struct ast_jb_conf default_jbconf
Global jitterbuffer configuration.
Definition: chan_console.c:186
static void stop_streams(void)
static void set_pvt_defaults(struct console_pvt *pvt)
Set default values for a pvt struct.
static struct console_pvt * active_pvt
Definition: chan_console.c:177
static struct ast_channel * console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
Definition: chan_console.c:425
static char * cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
answer command from the console
static struct ast_channel * console_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
Definition: chan_console.c:473
static void pvt_destructor(void *obj)
static int pvt_hash_cb(const void *obj, const int flags)
static char * cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_console.c:920
#define SAMPLE_RATE
The sample rate to request from PortAudio.
Definition: chan_console.c:84
#define OUTPUT_CHANNELS
Mono Output.
Definition: chan_console.c:102
static char * cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_console.c:765
#define console_pvt_unlock(pvt)
unlock a console_pvt struct
Definition: chan_console.c:231
static int init_pvt(struct console_pvt *pvt, const char *name)
static ast_rwlock_t active_lock
Definition: chan_console.c:178
static struct console_pvt * unref_pvt(struct console_pvt *pvt)
Definition: chan_console.c:240
static char * cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_console.c:804
static int console_call(struct ast_channel *c, const char *dest, int timeout)
Definition: chan_console.c:584
static int pvt_cmp_cb(void *obj, void *arg, int flags)
static void * stream_monitor(void *data)
Stream monitor thread.
Definition: chan_console.c:265
static struct ao2_container * pvts
Definition: chan_console.c:174
static int console_digit_begin(struct ast_channel *c, char digit)
Definition: chan_console.c:509
#define INPUT_CHANNELS
Mono Input.
Definition: chan_console.c:99
static char * cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Console send text CLI command.
static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
Definition: chan_console.c:625
static int stop_stream(struct console_pvt *pvt)
Definition: chan_console.c:402
static int console_write(struct ast_channel *chan, struct ast_frame *f)
Definition: chan_console.c:614
static struct ast_frame * console_read(struct ast_channel *chan)
Implementation of the ast_channel_tech read() callback.
Definition: chan_console.c:577
static char * cli_list_available(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: chan_console.c:962
static int console_hangup(struct ast_channel *c)
Definition: chan_console.c:531
static int console_answer(struct ast_channel *c)
Definition: chan_console.c:546
static void set_active(struct console_pvt *pvt, const char *value)
#define V_END
Definition: chan_console.c:113
static int console_text(struct ast_channel *c, const char *text)
Definition: chan_console.c:524
static struct ast_jb_conf global_jbconf
Definition: chan_console.c:193
static char * ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
Definition: chan_console.c:682
static struct ast_cli_entry cli_console[]
static const char config_file[]
Definition: chan_console.c:116
static struct console_pvt globals
static char * cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct console_pvt * get_active_pvt(void)
Definition: chan_console.c:705
static int load_module(void)
Load the module.
static ast_mutex_t globals_lock
Definition: chan_console.c:172
static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
Store a configuration parameter in a pvt struct.
static int pvt_mark_destroy_cb(void *obj, void *arg, int flags)
static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
Definition: chan_console.c:662
static struct ast_channel_tech console_tech
Definition: chan_console.c:211
static int unload_module(void)
static int load_config(int reload)
Load the configuration.
static int reload(void)
static char * cli_console_active(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct console_pvt * find_pvt(const char *name)
Definition: chan_console.c:246
static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
Definition: chan_console.c:516
#define NUM_SAMPLES
The number of samples to configure the portaudio stream for.
Definition: chan_console.c:96
static int start_stream(struct console_pvt *pvt)
Definition: chan_console.c:359
#define TEXT_SIZE
Maximum text message length.
Definition: chan_console.c:109
static void store_callerid(struct console_pvt *pvt, const char *value)
static char language[MAX_LANGUAGE]
Definition: chan_iax2.c:324
static char mohinterpret[MAX_MUSICCLASS]
Definition: chan_iax2.c:474
static const char type[]
Definition: chan_ooh323.c:109
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2560
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1299
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1169
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:570
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
Definition: channel.c:1250
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
Definition: channel.c:1158
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
void ast_channel_set_readformat(struct ast_channel *chan, struct ast_format *format)
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:539
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4296
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
#define ast_channel_unlock(chan)
Definition: channel.h:2969
void ast_channel_set_writeformat(struct ast_channel *chan, struct ast_format *format)
@ AST_STATE_RINGING
Definition: channelstate.h:41
@ AST_STATE_DOWN
Definition: channelstate.h:36
@ AST_STATE_UP
Definition: channelstate.h:42
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7408
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
short int16_t
Definition: db.h:59
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Media Format Cache API.
struct ast_format * ast_format_slin16
Built-in cached signed linear 16kHz format.
Definition: format_cache.c:51
#define AST_FORMAT_CAP_NAMES_LEN
Definition: format_cap.h:324
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
const char * ast_format_cap_get_names(const struct ast_format_cap *cap, struct ast_str **buf)
Get the names of codecs of a set of formats.
Definition: format_cap.c:734
int ast_format_cap_iscompatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2)
Determine if any joint capabilities exist between two capabilities structures.
Definition: format_cap.c:653
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
const char * ext
Definition: http.c:150
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
Definition: extconf.c:3326
#define CV_START(__in_var, __in_val)
the macro to open a block for variable parsing
#define CV_STRFIELD(__x, __obj, __field)
#define CV_END
close a variable parsing block
#define CV_F(__pattern, __body)
call a generic function if the name matches.
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
#define CV_BOOL(__x, __dst)
helper macros to assign the value to a BOOL, UINT, static string and dynamic string
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
#define AST_FRAME_DTMF
@ AST_FRAME_VOICE
@ AST_FRAME_TEXT
ast_control_frame_type
Internal control frame subtype field values.
@ AST_CONTROL_SRCUPDATE
@ AST_CONTROL_PROGRESS
@ AST_CONTROL_BUSY
@ AST_CONTROL_UNHOLD
@ AST_CONTROL_VIDUPDATE
@ AST_CONTROL_PROCEEDING
@ AST_CONTROL_CONGESTION
@ AST_CONTROL_ANSWER
@ AST_CONTROL_RINGING
@ AST_CONTROL_HOLD
@ AST_CONTROL_FLASH
@ AST_CONTROL_INCOMPLETE
@ AST_CONTROL_PVT_CAUSE_CODE
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define ast_verb(level,...)
#define LOG_NOTICE
#define LOG_WARNING
#define ast_rwlock_wrlock(a)
Definition: lock.h:236
#define AST_PTHREADT_NULL
Definition: lock.h:66
#define ast_rwlock_rdlock(a)
Definition: lock.h:235
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
Definition: lock.h:543
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_rwlock_unlock(a)
Definition: lock.h:234
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CHANNEL_DRIVER
Definition: module.h:341
@ AST_MODULE_SUPPORT_EXTENDED
Definition: module.h:122
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ 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
Music on hold handling.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:7788
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:7798
Core PBX routines and definitions.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:4175
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:4708
#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_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_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:359
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:374
#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
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
Definition: utils.c:2199
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
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
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:1303
#define ast_join(s, len, w)
Join an array of strings into a single string.
Definition: strings.h:520
Generic container type.
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1821
Structure to pass both assignedid values to channel drivers.
Definition: channel.h:606
Structure to describe a channel "technology", ie a channel driver See for examples:
Definition: channel.h:648
struct ast_format_cap * capabilities
Definition: channel.h:652
const char *const type
Definition: channel.h:649
Main Channel structure associated with a channel.
const char * data
descriptor for a cli entry.
Definition: cli.h:171
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
union ast_frame::@226 data
enum ast_frame_type frametype
General jitterbuffer configuration.
Definition: abstract_jb.h:70
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:72
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
Console pvt structure.
Definition: chan_console.c:124
pthread_t thread
Definition: chan_console.c:169
unsigned int hookstate
Definition: chan_console.c:158
const ast_string_field mohinterpret
Definition: chan_console.c:146
struct ast_frame fr
Definition: chan_console.c:152
unsigned int muted
Definition: chan_console.c:160
const ast_string_field language
Definition: chan_console.c:146
const ast_string_field cid_num
Definition: chan_console.c:146
unsigned int abort
Definition: chan_console.c:156
unsigned int streamstate
Definition: chan_console.c:154
unsigned int overridecontext
Definition: chan_console.c:164
const ast_string_field context
Definition: chan_console.c:146
const ast_string_field input_device
Definition: chan_console.c:146
const ast_string_field parkinglot
Definition: chan_console.c:146
const ast_string_field output_device
Definition: chan_console.c:146
struct ast_channel * owner
Definition: chan_console.c:148
PaStream * stream
Definition: chan_console.c:150
const ast_string_field exten
Definition: chan_console.c:146
unsigned int destroy
Definition: chan_console.c:167
const ast_string_field name
Definition: chan_console.c:146
const ast_string_field cid_name
Definition: chan_console.c:146
unsigned int autoanswer
Definition: chan_console.c:162
Number structure.
Definition: app_followme.c:154
const char * name
int value
Definition: syslog.c:37
static struct test_val a
static struct test_val c
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ARRAY_LEN(a)
Definition: utils.h:666