2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2006 - 2007, Digium, Inc.
6 * Russell Bryant <russell@digium.com>
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.
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.
21 * \brief Cross-platform console channel driver
23 * \author Russell Bryant <russell@digium.com>
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>
30 * \ingroup channel_drivers
32 * \note Since this works with any audio system that libportaudio supports,
33 * including ALSA and OSS, this may someday deprecate chan_alsa and chan_oss.
34 * However, before that can be done, it needs to *at least* have all of the
35 * features that these other channel drivers have. The features implemented
36 * in at least one of the other console channel drivers that are not yet
37 * implemented here are:
39 * - Multiple device support
40 * - with "active" CLI command
41 * - Set Auto-answer from the dialplan
42 * - transfer CLI command
43 * - boost CLI command and .conf option
44 * - console_video support
48 <depend>portaudio</depend>
53 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
55 #include <sys/signal.h> /* SIGURG */
57 #include <portaudio.h>
59 #include "asterisk/module.h"
60 #include "asterisk/channel.h"
61 #include "asterisk/pbx.h"
62 #include "asterisk/causes.h"
63 #include "asterisk/cli.h"
64 #include "asterisk/musiconhold.h"
65 #include "asterisk/callerid.h"
68 * \brief The sample rate to request from PortAudio
70 * \todo Make this optional. If this is only going to talk to 8 kHz endpoints,
71 * then it makes sense to use 8 kHz natively.
73 #define SAMPLE_RATE 16000
76 * \brief The number of samples to configure the portaudio stream for
78 * 320 samples (20 ms) is the most common frame size in Asterisk. So, the code
79 * in this module reads 320 sample frames from the portaudio stream and queues
80 * them up on the Asterisk channel. Frames of any size can be written to a
81 * portaudio stream, but the portaudio documentation does say that for high
82 * performance applications, the data should be written to Pa_WriteStream in
83 * the same size as what is used to initialize the stream.
85 #define NUM_SAMPLES 320
87 /*! \brief Mono Input */
88 #define INPUT_CHANNELS 1
90 /*! \brief Mono Output */
91 #define OUTPUT_CHANNELS 1
94 * \brief Maximum text message length
95 * \note This should be changed if there is a common definition somewhere
96 * that defines the maximum length of a text message.
101 #define MIN(a,b) ((a) < (b) ? (a) : (b))
104 #define MAX(a,b) ((a) > (b) ? (a) : (b))
107 /*! \brief Dance, Kirby, Dance! @{ */
108 #define V_BEGIN " --- <(\"<) --- "
109 #define V_END " --- (>\")> ---\n"
112 static const char config_file[] = "console.conf";
115 * \brief Console pvt structure
117 * Currently, this is a singleton object. However, multiple instances will be
118 * needed when this module is updated for multiple device support.
120 static struct console_pvt {
121 AST_DECLARE_STRING_FIELDS(
122 /*! Name of the device */
123 AST_STRING_FIELD(name);
124 /*! Default context for outgoing calls */
125 AST_STRING_FIELD(context);
126 /*! Default extension for outgoing calls */
127 AST_STRING_FIELD(exten);
128 /*! Default CallerID number */
129 AST_STRING_FIELD(cid_num);
130 /*! Default CallerID name */
131 AST_STRING_FIELD(cid_name);
132 /*! Default MOH class to listen to, if:
133 * - No MOH class set on the channel
134 * - Peer channel putting this device on hold did not suggest a class */
135 AST_STRING_FIELD(mohinterpret);
136 /*! Default language */
137 AST_STRING_FIELD(language);
139 /*! Current channel for this device */
140 struct ast_channel *owner;
141 /*! Current PortAudio stream for this device */
143 /*! A frame for preparing to queue on to the channel */
145 /*! Running = 1, Not running = 0 */
146 unsigned int streamstate:1;
147 /*! On-hook = 0, Off-hook = 1 */
148 unsigned int hookstate:1;
149 /*! Unmuted = 0, Muted = 1 */
150 unsigned int muted:1;
151 /*! Automatically answer incoming calls */
152 unsigned int autoanswer:1;
153 /*! Ignore context in the console dial CLI command */
154 unsigned int overridecontext:1;
155 /*! Lock to protect data in this struct */
157 /*! ID for the stream monitor thread */
160 .__lock = AST_MUTEX_INIT_VALUE,
161 .thread = AST_PTHREADT_NULL,
165 * \brief Global jitterbuffer configuration
167 * \note Disabled by default.
169 static struct ast_jb_conf default_jbconf = {
172 .resync_threshold = -1,
175 static struct ast_jb_conf global_jbconf;
177 /*! Channel Technology Callbacks @{ */
178 static struct ast_channel *console_request(const char *type, int format,
179 void *data, int *cause);
180 static int console_digit_begin(struct ast_channel *c, char digit);
181 static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration);
182 static int console_text(struct ast_channel *c, const char *text);
183 static int console_hangup(struct ast_channel *c);
184 static int console_answer(struct ast_channel *c);
185 static struct ast_frame *console_read(struct ast_channel *chan);
186 static int console_call(struct ast_channel *c, char *dest, int timeout);
187 static int console_write(struct ast_channel *chan, struct ast_frame *f);
188 static int console_indicate(struct ast_channel *chan, int cond,
189 const void *data, size_t datalen);
190 static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
194 * \brief Formats natively supported by this module.
196 #define SUPPORTED_FORMATS ( AST_FORMAT_SLINEAR16 )
198 static const struct ast_channel_tech console_tech = {
200 .description = "Console Channel Driver",
201 .capabilities = SUPPORTED_FORMATS,
202 .requester = console_request,
203 .send_digit_begin = console_digit_begin,
204 .send_digit_end = console_digit_end,
205 .send_text = console_text,
206 .hangup = console_hangup,
207 .answer = console_answer,
208 .read = console_read,
209 .call = console_call,
210 .write = console_write,
211 .indicate = console_indicate,
212 .fixup = console_fixup,
215 /*! \brief lock a console_pvt struct */
216 #define console_pvt_lock(pvt) ast_mutex_lock(&(pvt)->__lock)
218 /*! \brief unlock a console_pvt struct */
219 #define console_pvt_unlock(pvt) ast_mutex_unlock(&(pvt)->__lock)
222 * \brief Stream monitor thread
224 * \arg data A pointer to the console_pvt structure that contains the portaudio
225 * stream that needs to be monitored.
227 * This function runs in its own thread to monitor data coming in from a
228 * portaudio stream. When enough data is available, it is queued up to
229 * be read from the Asterisk channel.
231 static void *stream_monitor(void *data)
233 struct console_pvt *pvt = data;
234 char buf[NUM_SAMPLES * sizeof(int16_t)];
236 struct ast_frame f = {
237 .frametype = AST_FRAME_VOICE,
238 .subclass = AST_FORMAT_SLINEAR16,
239 .src = "console_stream_monitor",
241 .datalen = sizeof(buf),
242 .samples = sizeof(buf) / sizeof(int16_t),
246 pthread_testcancel();
247 res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
248 pthread_testcancel();
250 if (res == paNoError)
251 ast_queue_frame(pvt->owner, &f);
257 static int start_stream(struct console_pvt *pvt)
262 console_pvt_lock(pvt);
264 if (pvt->streamstate)
267 pvt->streamstate = 1;
268 ast_debug(1, "Starting stream\n");
270 res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS,
271 paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
272 if (res != paNoError) {
273 ast_log(LOG_WARNING, "Failed to open default audio device - (%d) %s\n",
274 res, Pa_GetErrorText(res));
279 res = Pa_StartStream(pvt->stream);
280 if (res != paNoError) {
281 ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
282 res, Pa_GetErrorText(res));
287 if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
288 ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
293 console_pvt_unlock(pvt);
298 static int stop_stream(struct console_pvt *pvt)
300 if (!pvt->streamstate)
303 pthread_cancel(pvt->thread);
304 pthread_kill(pvt->thread, SIGURG);
305 pthread_join(pvt->thread, NULL);
307 console_pvt_lock(pvt);
308 Pa_AbortStream(pvt->stream);
309 Pa_CloseStream(pvt->stream);
311 pvt->streamstate = 0;
312 console_pvt_unlock(pvt);
318 * \note Called with the pvt struct locked
320 static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state)
322 struct ast_channel *chan;
324 if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL,
325 ext, ctx, 0, "Console/%s", pvt->name))) {
329 chan->tech = &console_tech;
330 chan->nativeformats = AST_FORMAT_SLINEAR16;
331 chan->readformat = AST_FORMAT_SLINEAR16;
332 chan->writeformat = AST_FORMAT_SLINEAR16;
333 chan->tech_pvt = pvt;
337 if (!ast_strlen_zero(pvt->language))
338 ast_string_field_set(chan, language, pvt->language);
340 ast_jb_configure(chan, &global_jbconf);
342 if (state != AST_STATE_DOWN) {
343 if (ast_pbx_start(chan)) {
344 chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
354 static struct ast_channel *console_request(const char *type, int format, void *data, int *cause)
356 int oldformat = format;
357 struct ast_channel *chan;
358 struct console_pvt *pvt = &console_pvt;
360 format &= SUPPORTED_FORMATS;
362 ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%d'\n", oldformat);
367 ast_log(LOG_NOTICE, "Console channel already active!\n");
368 *cause = AST_CAUSE_BUSY;
372 console_pvt_lock(pvt);
373 chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN);
374 console_pvt_unlock(pvt);
377 ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
382 static int console_digit_begin(struct ast_channel *c, char digit)
384 ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
386 return -1; /* non-zero to request inband audio */
389 static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
391 ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END,
394 return -1; /* non-zero to request inband audio */
397 static int console_text(struct ast_channel *c, const char *text)
399 ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
404 static int console_hangup(struct ast_channel *c)
406 struct console_pvt *pvt = &console_pvt;
408 ast_verb(1, V_BEGIN "Hangup on Console" V_END);
419 static int console_answer(struct ast_channel *c)
421 struct console_pvt *pvt = &console_pvt;
423 ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
425 ast_setstate(c, AST_STATE_UP);
427 return start_stream(pvt);
431 * \brief Implementation of the ast_channel_tech read() callback
433 * Calling this function is harmless. However, if it does get called, it
434 * is an indication that something weird happened that really shouldn't
435 * have and is worth looking into.
437 * Why should this function not get called? Well, let me explain. There are
438 * a couple of ways to pass on audio that has come from this channel. The way
439 * that this channel driver uses is that once the audio is available, it is
440 * wrapped in an ast_frame and queued onto the channel using ast_queue_frame().
442 * The other method would be signalling to the core that there is audio waiting,
443 * and that it needs to call the channel's read() callback to get it. The way
444 * the channel gets signalled is that one or more file descriptors are placed
445 * in the fds array on the ast_channel which the core will poll() on. When the
446 * fd indicates that input is available, the read() callback is called. This
447 * is especially useful when there is a dedicated file descriptor where the
448 * audio is read from. An example would be the socket for an RTP stream.
450 static struct ast_frame *console_read(struct ast_channel *chan)
452 ast_debug(1, "I should not be called ...\n");
454 return &ast_null_frame;
457 static int console_call(struct ast_channel *c, char *dest, int timeout)
459 struct ast_frame f = { 0, };
460 struct console_pvt *pvt = &console_pvt;
462 ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
463 dest, c->cid.cid_name, c->cid.cid_num);
465 console_pvt_lock(pvt);
467 if (pvt->autoanswer) {
469 console_pvt_unlock(pvt);
470 ast_verb(1, V_BEGIN "Auto-answered" V_END);
471 f.frametype = AST_FRAME_CONTROL;
472 f.subclass = AST_CONTROL_ANSWER;
474 console_pvt_unlock(pvt);
475 ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
476 "for future calls" V_END);
477 f.frametype = AST_FRAME_CONTROL;
478 f.subclass = AST_CONTROL_RINGING;
479 ast_indicate(c, AST_CONTROL_RINGING);
482 ast_queue_frame(c, &f);
484 return start_stream(pvt);
487 static int console_write(struct ast_channel *chan, struct ast_frame *f)
489 struct console_pvt *pvt = &console_pvt;
491 Pa_WriteStream(pvt->stream, f->data, f->samples);
496 static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
498 struct console_pvt *pvt = chan->tech_pvt;
502 case AST_CONTROL_BUSY:
503 case AST_CONTROL_CONGESTION:
504 case AST_CONTROL_RINGING:
506 res = -1; /* Ask for inband indications */
508 case AST_CONTROL_PROGRESS:
509 case AST_CONTROL_PROCEEDING:
510 case AST_CONTROL_VIDUPDATE:
512 case AST_CONTROL_HOLD:
513 ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
514 ast_moh_start(chan, data, pvt->mohinterpret);
516 case AST_CONTROL_UNHOLD:
517 ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
521 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n",
523 /* The core will play inband indications for us if appropriate */
530 static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
532 struct console_pvt *pvt = &console_pvt;
534 pvt->owner = newchan;
540 * split a string in extension-context, returns pointers to malloc'ed
542 * If we do not have 'overridecontext' then the last @ is considered as
543 * a context separator, and the context is overridden.
544 * This is usually not very necessary as you can play with the dialplan,
545 * and it is nice not to need it because you have '@' in SIP addresses.
546 * Return value is the buffer address.
548 * \note came from chan_oss
550 static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
552 if (ext == NULL || ctx == NULL)
553 return NULL; /* error */
557 if (src && *src != '\0')
558 *ext = ast_strdup(src);
563 if (!pvt->overridecontext) {
564 /* parse from the right */
565 *ctx = strrchr(*ext, '@');
573 static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd,
574 struct ast_cli_args *a)
576 struct console_pvt *pvt = &console_pvt;
580 e->command = "console set autoanswer [on|off]";
582 "Usage: console set autoanswer [on|off]\n"
583 " Enables or disables autoanswer feature. If used without\n"
584 " argument, displays the current on/off status of autoanswer.\n"
585 " The default value of autoanswer is in 'oss.conf'.\n";
592 if (a->argc == e->args - 1) {
593 ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
597 if (a->argc != e->args)
598 return CLI_SHOWUSAGE;
601 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
606 if (!strcasecmp(a->argv[e->args-1], "on"))
608 else if (!strcasecmp(a->argv[e->args - 1], "off"))
611 return CLI_SHOWUSAGE;
616 static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
618 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
619 struct console_pvt *pvt = &console_pvt;
621 if (cmd == CLI_INIT) {
622 e->command = "console flash";
624 "Usage: console flash\n"
625 " Flashes the call currently placed on the console.\n";
627 } else if (cmd == CLI_GENERATE)
630 if (a->argc != e->args)
631 return CLI_SHOWUSAGE;
634 ast_cli(a->fd, "No call to flash\n");
640 ast_queue_frame(pvt->owner, &f);
645 static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
648 const char *mye = NULL, *myc = NULL;
649 struct console_pvt *pvt = &console_pvt;
651 if (cmd == CLI_INIT) {
652 e->command = "console dial";
654 "Usage: console dial [extension[@context]]\n"
655 " Dials a given extension (and context if specified)\n";
657 } else if (cmd == CLI_GENERATE)
660 if (a->argc > e->args + 1)
661 return CLI_SHOWUSAGE;
663 if (pvt->owner) { /* already in a call */
665 struct ast_frame f = { AST_FRAME_DTMF, 0 };
667 if (a->argc == e->args) { /* argument is mandatory here */
668 ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
671 s = a->argv[e->args];
672 /* send the string one char at a time */
673 for (i = 0; i < strlen(s); i++) {
675 ast_queue_frame(pvt->owner, &f);
680 /* if we have an argument split it into extension and context */
681 if (a->argc == e->args + 1) {
682 char *ext = NULL, *con = NULL;
683 s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
684 ast_debug(1, "provided '%s', exten '%s' context '%s'\n",
685 a->argv[e->args], mye, myc);
690 /* supply default values if needed */
691 if (ast_strlen_zero(mye))
693 if (ast_strlen_zero(myc))
696 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
697 console_pvt_lock(pvt);
699 console_new(pvt, mye, myc, AST_STATE_RINGING);
700 console_pvt_unlock(pvt);
702 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
710 static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
712 struct console_pvt *pvt = &console_pvt;
714 if (cmd == CLI_INIT) {
715 e->command = "console hangup";
717 "Usage: console hangup\n"
718 " Hangs up any call currently placed on the console.\n";
720 } else if (cmd == CLI_GENERATE)
723 if (a->argc != e->args)
724 return CLI_SHOWUSAGE;
726 if (!pvt->owner && !pvt->hookstate) {
727 ast_cli(a->fd, "No call to hang up\n");
733 ast_queue_hangup(pvt->owner);
738 static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
741 struct console_pvt *pvt = &console_pvt;
743 if (cmd == CLI_INIT) {
744 e->command = "console {mute|unmute}";
746 "Usage: console {mute|unmute}\n"
747 " Mute/unmute the microphone.\n";
749 } else if (cmd == CLI_GENERATE)
752 if (a->argc != e->args)
753 return CLI_SHOWUSAGE;
755 s = a->argv[e->args-1];
756 if (!strcasecmp(s, "mute"))
758 else if (!strcasecmp(s, "unmute"))
761 return CLI_SHOWUSAGE;
763 ast_verb(1, V_BEGIN "The Console is now %s" V_END,
764 pvt->muted ? "Muted" : "Unmuted");
769 static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
771 PaDeviceIndex index, num, def_input, def_output;
773 if (cmd == CLI_INIT) {
774 e->command = "console list devices";
776 "Usage: console list devices\n"
777 " List all available devices.\n";
779 } else if (cmd == CLI_GENERATE)
782 if (a->argc != e->args)
783 return CLI_SHOWUSAGE;
785 ast_cli(a->fd, "Available Devices:\n---------------------------------\n");
787 num = Pa_GetDeviceCount();
789 ast_cli(a->fd, "(None)\n");
793 def_input = Pa_GetDefaultInputDevice();
794 def_output = Pa_GetDefaultOutputDevice();
795 for (index = 0; index < num; index++) {
796 const PaDeviceInfo *dev = Pa_GetDeviceInfo(index);
799 ast_cli(a->fd, "Device Name: %s\n", dev->name);
800 if (index == def_input)
801 ast_cli(a->fd, " ---> Default Input Device\n");
802 if (index == def_output)
803 ast_cli(a->fd, " ---> Default Output Device\n");
810 * \brief answer command from the console
812 static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
814 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
815 struct console_pvt *pvt = &console_pvt;
819 e->command = "console answer";
821 "Usage: console answer\n"
822 " Answers an incoming call on the console channel.\n";
826 return NULL; /* no completion */
829 if (a->argc != e->args)
830 return CLI_SHOWUSAGE;
833 ast_cli(a->fd, "No one is calling us\n");
839 ast_indicate(pvt->owner, -1);
841 ast_queue_frame(pvt->owner, &f);
847 * \brief Console send text CLI command
849 * \note concatenate all arguments into a single string. argv is NULL-terminated
850 * so we can use it right away
852 static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
855 struct console_pvt *pvt = &console_pvt;
856 struct ast_frame f = {
857 .frametype = AST_FRAME_TEXT,
859 .src = "console_send_text",
863 if (cmd == CLI_INIT) {
864 e->command = "console send text";
866 "Usage: console send text <message>\n"
867 " Sends a text message for display on the remote terminal.\n";
869 } else if (cmd == CLI_GENERATE)
872 if (a->argc < e->args + 1)
873 return CLI_SHOWUSAGE;
876 ast_cli(a->fd, "Not in a call\n");
880 ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
881 if (ast_strlen_zero(buf))
882 return CLI_SHOWUSAGE;
888 ast_queue_frame(pvt->owner, &f);
893 static struct ast_cli_entry cli_console[] = {
894 AST_CLI_DEFINE(cli_console_dial, "Dial an extension from the console"),
895 AST_CLI_DEFINE(cli_console_hangup, "Hangup a call on the console"),
896 AST_CLI_DEFINE(cli_console_mute, "Disable/Enable mic input"),
897 AST_CLI_DEFINE(cli_console_answer, "Answer an incoming console call"),
898 AST_CLI_DEFINE(cli_console_sendtext, "Send text to a connected party"),
899 AST_CLI_DEFINE(cli_console_flash, "Send a flash to the connected party"),
900 AST_CLI_DEFINE(cli_console_autoanswer, "Turn autoanswer on or off"),
901 AST_CLI_DEFINE(cli_list_devices, "List available devices"),
905 * \brief Set default values for a pvt struct
907 * \note This function expects the pvt lock to be held.
909 static void set_pvt_defaults(struct console_pvt *pvt, int reload)
912 /* This should be changed for multiple device support. Right now,
913 * there is no way to change the name of a device. The default
914 * input and output sound devices are the only ones supported. */
915 ast_string_field_set(pvt, name, "default");
918 ast_string_field_set(pvt, mohinterpret, "default");
919 ast_string_field_set(pvt, context, "default");
920 ast_string_field_set(pvt, exten, "s");
921 ast_string_field_set(pvt, language, "");
922 ast_string_field_set(pvt, cid_num, "");
923 ast_string_field_set(pvt, cid_name, "");
925 pvt->overridecontext = 0;
929 static void store_callerid(struct console_pvt *pvt, const char *value)
934 ast_callerid_split(value, cid_name, sizeof(cid_name),
935 cid_num, sizeof(cid_num));
937 ast_string_field_set(pvt, cid_name, cid_name);
938 ast_string_field_set(pvt, cid_num, cid_num);
942 * \brief Store a configuration parameter in a pvt struct
944 * \note This function expects the pvt lock to be held.
946 static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
948 if (!ast_jb_read_conf(&global_jbconf, var, value))
951 CV_START(var, value);
953 CV_STRFIELD("context", pvt, context);
954 CV_STRFIELD("extension", pvt, exten);
955 CV_STRFIELD("mohinterpret", pvt, mohinterpret);
956 CV_STRFIELD("language", pvt, language);
957 CV_F("callerid", store_callerid(pvt, value));
958 CV_BOOL("overridecontext", pvt->overridecontext);
959 CV_BOOL("autoanswer", pvt->autoanswer);
961 ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
967 * \brief Load the configuration
968 * \param reload if this was called due to a reload
972 static int load_config(int reload)
974 struct ast_config *cfg;
975 struct ast_variable *v;
976 struct console_pvt *pvt = &console_pvt;
977 struct ast_flags config_flags = { 0 };
981 memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
983 console_pvt_lock(pvt);
985 set_pvt_defaults(pvt, reload);
987 if (!(cfg = ast_config_load(config_file, config_flags))) {
988 ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
992 for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
993 store_config_core(pvt, v->name, v->value);
995 ast_config_destroy(cfg);
1000 console_pvt_unlock(pvt);
1004 static int init_pvt(struct console_pvt *pvt)
1006 if (ast_string_field_init(pvt, 32))
1009 if (ast_mutex_init(&pvt->__lock)) {
1010 ast_log(LOG_ERROR, "Failed to initialize mutex\n");
1017 static void destroy_pvt(struct console_pvt *pvt)
1019 ast_string_field_free_memory(pvt);
1021 ast_mutex_destroy(&pvt->__lock);
1024 static int unload_module(void)
1026 struct console_pvt *pvt = &console_pvt;
1033 ast_channel_unregister(&console_tech);
1034 ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
1041 static int load_module(void)
1044 struct console_pvt *pvt = &console_pvt;
1052 res = Pa_Initialize();
1053 if (res != paNoError) {
1054 ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
1055 res, Pa_GetErrorText(res));
1056 goto return_error_pa_init;
1059 if (ast_channel_register(&console_tech)) {
1060 ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
1061 goto return_error_chan_reg;
1064 if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
1065 goto return_error_cli_reg;
1067 return AST_MODULE_LOAD_SUCCESS;
1069 return_error_cli_reg:
1070 ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
1071 return_error_chan_reg:
1072 ast_channel_unregister(&console_tech);
1073 return_error_pa_init:
1078 return AST_MODULE_LOAD_DECLINE;
1081 static int reload(void)
1083 return load_config(1);
1086 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Console Channel Driver",
1087 .load = load_module,
1088 .unload = unload_module,