Note that this module doesn't actually play a ringing sound for an incoming call
[asterisk/asterisk.git] / channels / chan_console.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2006 - 2007, 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  * \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:
38  *
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
45  * - Add ringing sound on incoming calls
46  */
47
48 /*** MODULEINFO
49         <depend>portaudio</depend>
50  ***/
51
52 #include "asterisk.h"
53
54 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
55
56 #include <sys/signal.h>  /* SIGURG */
57
58 #include <portaudio.h>
59
60 #include "asterisk/module.h"
61 #include "asterisk/channel.h"
62 #include "asterisk/pbx.h"
63 #include "asterisk/causes.h"
64 #include "asterisk/cli.h"
65 #include "asterisk/musiconhold.h"
66 #include "asterisk/callerid.h"
67
68 /*! 
69  * \brief The sample rate to request from PortAudio 
70  *
71  * \todo Make this optional.  If this is only going to talk to 8 kHz endpoints,
72  *       then it makes sense to use 8 kHz natively.
73  */
74 #define SAMPLE_RATE      16000
75
76 /*! 
77  * \brief The number of samples to configure the portaudio stream for
78  *
79  * 320 samples (20 ms) is the most common frame size in Asterisk.  So, the code
80  * in this module reads 320 sample frames from the portaudio stream and queues
81  * them up on the Asterisk channel.  Frames of any size can be written to a
82  * portaudio stream, but the portaudio documentation does say that for high
83  * performance applications, the data should be written to Pa_WriteStream in
84  * the same size as what is used to initialize the stream.
85  */
86 #define NUM_SAMPLES      320
87
88 /*! \brief Mono Input */
89 #define INPUT_CHANNELS   1
90
91 /*! \brief Mono Output */
92 #define OUTPUT_CHANNELS  1
93
94 /*! 
95  * \brief Maximum text message length
96  * \note This should be changed if there is a common definition somewhere
97  *       that defines the maximum length of a text message.
98  */
99 #define TEXT_SIZE       256
100
101 #ifndef MIN
102 #define MIN(a,b) ((a) < (b) ? (a) : (b))
103 #endif
104 #ifndef MAX
105 #define MAX(a,b) ((a) > (b) ? (a) : (b))
106 #endif
107
108 /*! \brief Dance, Kirby, Dance! @{ */
109 #define V_BEGIN " --- <(\"<) --- "
110 #define V_END   " --- (>\")> ---\n"
111 /*! @} */
112
113 static const char config_file[] = "console.conf";
114
115 /*!
116  * \brief Console pvt structure
117  *
118  * Currently, this is a singleton object.  However, multiple instances will be
119  * needed when this module is updated for multiple device support.
120  */
121 static struct console_pvt {
122         AST_DECLARE_STRING_FIELDS(
123                 /*! Name of the device */
124                 AST_STRING_FIELD(name);
125                 /*! Default context for outgoing calls */
126                 AST_STRING_FIELD(context);
127                 /*! Default extension for outgoing calls */
128                 AST_STRING_FIELD(exten);
129                 /*! Default CallerID number */
130                 AST_STRING_FIELD(cid_num);
131                 /*! Default CallerID name */
132                 AST_STRING_FIELD(cid_name);
133                 /*! Default MOH class to listen to, if:
134                  *    - No MOH class set on the channel
135                  *    - Peer channel putting this device on hold did not suggest a class */
136                 AST_STRING_FIELD(mohinterpret);
137                 /*! Default language */
138                 AST_STRING_FIELD(language);
139         );
140         /*! Current channel for this device */
141         struct ast_channel *owner;
142         /*! Current PortAudio stream for this device */
143         PaStream *stream;
144         /*! A frame for preparing to queue on to the channel */
145         struct ast_frame fr;
146         /*! Running = 1, Not running = 0 */
147         unsigned int streamstate:1;
148         /*! On-hook = 0, Off-hook = 1 */
149         unsigned int hookstate:1;
150         /*! Unmuted = 0, Muted = 1 */
151         unsigned int muted:1;
152         /*! Automatically answer incoming calls */
153         unsigned int autoanswer:1;
154         /*! Ignore context in the console dial CLI command */
155         unsigned int overridecontext:1;
156         /*! Lock to protect data in this struct */
157         ast_mutex_t __lock;
158         /*! ID for the stream monitor thread */
159         pthread_t thread;
160 } console_pvt = {
161         .__lock = AST_MUTEX_INIT_VALUE,
162         .thread = AST_PTHREADT_NULL,
163 };
164
165 /*! 
166  * \brief Global jitterbuffer configuration 
167  *
168  * \note Disabled by default.
169  */
170 static struct ast_jb_conf default_jbconf = {
171         .flags = 0,
172         .max_size = -1,
173         .resync_threshold = -1,
174         .impl = ""
175 };
176 static struct ast_jb_conf global_jbconf;
177
178 /*! Channel Technology Callbacks @{ */
179 static struct ast_channel *console_request(const char *type, int format, 
180         void *data, int *cause);
181 static int console_digit_begin(struct ast_channel *c, char digit);
182 static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration);
183 static int console_text(struct ast_channel *c, const char *text);
184 static int console_hangup(struct ast_channel *c);
185 static int console_answer(struct ast_channel *c);
186 static struct ast_frame *console_read(struct ast_channel *chan);
187 static int console_call(struct ast_channel *c, char *dest, int timeout);
188 static int console_write(struct ast_channel *chan, struct ast_frame *f);
189 static int console_indicate(struct ast_channel *chan, int cond, 
190         const void *data, size_t datalen);
191 static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
192 /*! @} */
193
194 /*!
195  * \brief Formats natively supported by this module.
196  */
197 #define SUPPORTED_FORMATS ( AST_FORMAT_SLINEAR16 )
198
199 static const struct ast_channel_tech console_tech = {
200         .type = "Console",
201         .description = "Console Channel Driver",
202         .capabilities = SUPPORTED_FORMATS,
203         .requester = console_request,
204         .send_digit_begin = console_digit_begin,
205         .send_digit_end = console_digit_end,
206         .send_text = console_text,
207         .hangup = console_hangup,
208         .answer = console_answer,
209         .read = console_read,
210         .call = console_call,
211         .write = console_write,
212         .indicate = console_indicate,
213         .fixup = console_fixup,
214 };
215
216 /*! \brief lock a console_pvt struct */
217 #define console_pvt_lock(pvt) ast_mutex_lock(&(pvt)->__lock)
218
219 /*! \brief unlock a console_pvt struct */
220 #define console_pvt_unlock(pvt) ast_mutex_unlock(&(pvt)->__lock)
221
222 /*!
223  * \brief Stream monitor thread 
224  *
225  * \arg data A pointer to the console_pvt structure that contains the portaudio
226  *      stream that needs to be monitored.
227  *
228  * This function runs in its own thread to monitor data coming in from a
229  * portaudio stream.  When enough data is available, it is queued up to
230  * be read from the Asterisk channel.
231  */
232 static void *stream_monitor(void *data)
233 {
234         struct console_pvt *pvt = data;
235         char buf[NUM_SAMPLES * sizeof(int16_t)];
236         PaError res;
237         struct ast_frame f = {
238                 .frametype = AST_FRAME_VOICE,
239                 .subclass = AST_FORMAT_SLINEAR16,
240                 .src = "console_stream_monitor",
241                 .data = buf,
242                 .datalen = sizeof(buf),
243                 .samples = sizeof(buf) / sizeof(int16_t),
244         };
245
246         for (;;) {
247                 pthread_testcancel();
248                 res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
249                 pthread_testcancel();
250
251                 if (res == paNoError)
252                         ast_queue_frame(pvt->owner, &f);
253         }
254
255         return NULL;
256 }
257
258 static int start_stream(struct console_pvt *pvt)
259 {
260         PaError res;
261         int ret_val = 0;
262
263         console_pvt_lock(pvt);
264
265         if (pvt->streamstate)
266                 goto return_unlock;
267
268         pvt->streamstate = 1;
269         ast_debug(1, "Starting stream\n");
270
271         res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS, 
272                 paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
273         if (res != paNoError) {
274                 ast_log(LOG_WARNING, "Failed to open default audio device - (%d) %s\n",
275                         res, Pa_GetErrorText(res));
276                 ret_val = -1;
277                 goto return_unlock;
278         }
279
280         res = Pa_StartStream(pvt->stream);
281         if (res != paNoError) {
282                 ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
283                         res, Pa_GetErrorText(res));
284                 ret_val = -1;
285                 goto return_unlock;
286         }
287
288         if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
289                 ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
290                 ret_val = -1;
291         }
292
293 return_unlock:
294         console_pvt_unlock(pvt);
295
296         return ret_val;
297 }
298
299 static int stop_stream(struct console_pvt *pvt)
300 {
301         if (!pvt->streamstate)
302                 return 0;
303
304         pthread_cancel(pvt->thread);
305         pthread_kill(pvt->thread, SIGURG);
306         pthread_join(pvt->thread, NULL);
307
308         console_pvt_lock(pvt);
309         Pa_AbortStream(pvt->stream);
310         Pa_CloseStream(pvt->stream);
311         pvt->stream = NULL;
312         pvt->streamstate = 0;
313         console_pvt_unlock(pvt);
314
315         return 0;
316 }
317
318 /*!
319  * \note Called with the pvt struct locked
320  */
321 static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state)
322 {
323         struct ast_channel *chan;
324
325         if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL, 
326                 ext, ctx, 0, "Console/%s", pvt->name))) {
327                 return NULL;
328         }
329
330         chan->tech = &console_tech;
331         chan->nativeformats = AST_FORMAT_SLINEAR16;
332         chan->readformat = AST_FORMAT_SLINEAR16;
333         chan->writeformat = AST_FORMAT_SLINEAR16;
334         chan->tech_pvt = pvt;
335
336         pvt->owner = chan;
337
338         if (!ast_strlen_zero(pvt->language))
339                 ast_string_field_set(chan, language, pvt->language);
340
341         ast_jb_configure(chan, &global_jbconf);
342
343         if (state != AST_STATE_DOWN) {
344                 if (ast_pbx_start(chan)) {
345                         chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
346                         ast_hangup(chan);
347                         chan = NULL;
348                 } else
349                         start_stream(pvt);
350         }
351
352         return chan;
353 }
354
355 static struct ast_channel *console_request(const char *type, int format, void *data, int *cause)
356 {
357         int oldformat = format;
358         struct ast_channel *chan;
359         struct console_pvt *pvt = &console_pvt;
360
361         format &= SUPPORTED_FORMATS;
362         if (!format) {
363                 ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%d'\n", oldformat);
364                 return NULL;
365         }
366
367         if (pvt->owner) {
368                 ast_log(LOG_NOTICE, "Console channel already active!\n");
369                 *cause = AST_CAUSE_BUSY;
370                 return NULL;
371         }
372
373         console_pvt_lock(pvt);
374         chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN);
375         console_pvt_unlock(pvt);
376
377         if (!chan)
378                 ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
379
380         return chan;
381 }
382
383 static int console_digit_begin(struct ast_channel *c, char digit)
384 {
385         ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
386
387         return -1; /* non-zero to request inband audio */
388 }
389
390 static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
391 {
392         ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END, 
393                 digit, duration);
394
395         return -1; /* non-zero to request inband audio */
396 }
397
398 static int console_text(struct ast_channel *c, const char *text)
399 {
400         ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
401
402         return 0;
403 }
404
405 static int console_hangup(struct ast_channel *c)
406 {
407         struct console_pvt *pvt = &console_pvt;
408
409         ast_verb(1, V_BEGIN "Hangup on Console" V_END);
410
411         pvt->hookstate = 0;
412         c->tech_pvt = NULL;
413         pvt->owner = NULL;
414
415         stop_stream(pvt);
416
417         return 0;
418 }
419
420 static int console_answer(struct ast_channel *c)
421 {
422         struct console_pvt *pvt = &console_pvt;
423
424         ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
425
426         ast_setstate(c, AST_STATE_UP);
427
428         return start_stream(pvt);
429 }
430
431 /*
432  * \brief Implementation of the ast_channel_tech read() callback
433  *
434  * Calling this function is harmless.  However, if it does get called, it
435  * is an indication that something weird happened that really shouldn't
436  * have and is worth looking into.
437  * 
438  * Why should this function not get called?  Well, let me explain.  There are
439  * a couple of ways to pass on audio that has come from this channel.  The way
440  * that this channel driver uses is that once the audio is available, it is
441  * wrapped in an ast_frame and queued onto the channel using ast_queue_frame().
442  *
443  * The other method would be signalling to the core that there is audio waiting,
444  * and that it needs to call the channel's read() callback to get it.  The way
445  * the channel gets signalled is that one or more file descriptors are placed
446  * in the fds array on the ast_channel which the core will poll() on.  When the
447  * fd indicates that input is available, the read() callback is called.  This
448  * is especially useful when there is a dedicated file descriptor where the
449  * audio is read from.  An example would be the socket for an RTP stream.
450  */
451 static struct ast_frame *console_read(struct ast_channel *chan)
452 {
453         ast_debug(1, "I should not be called ...\n");
454
455         return &ast_null_frame;
456 }
457
458 static int console_call(struct ast_channel *c, char *dest, int timeout)
459 {
460         struct ast_frame f = { 0, };
461         struct console_pvt *pvt = &console_pvt;
462
463         ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
464                 dest, c->cid.cid_name, c->cid.cid_num);
465
466         console_pvt_lock(pvt);
467
468         if (pvt->autoanswer) {
469                 ast_verb(1, V_BEGIN "Auto-answered" V_END);
470                 pvt->hookstate = 1;
471                 f.frametype = AST_FRAME_CONTROL;
472                 f.subclass = AST_CONTROL_ANSWER;
473         } else {
474                 ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
475                                 "for future calls" V_END);
476                 f.frametype = AST_FRAME_CONTROL;
477                 f.subclass = AST_CONTROL_RINGING;
478         }
479
480         console_pvt_unlock(pvt);
481
482         ast_queue_frame(c, &f);
483
484         return start_stream(pvt);
485 }
486
487 static int console_write(struct ast_channel *chan, struct ast_frame *f)
488 {
489         struct console_pvt *pvt = &console_pvt;
490
491         Pa_WriteStream(pvt->stream, f->data, f->samples);
492
493         return 0;
494 }
495
496 static int console_indicate(struct ast_channel *chan, int cond, const void *data, size_t datalen)
497 {
498         struct console_pvt *pvt = chan->tech_pvt;
499         int res = 0;
500
501         switch (cond) {
502         case AST_CONTROL_BUSY:
503         case AST_CONTROL_CONGESTION:
504         case AST_CONTROL_RINGING:
505                 res = -1;  /* Ask for inband indications */
506                 break;
507         case AST_CONTROL_PROGRESS:
508         case AST_CONTROL_PROCEEDING:
509         case AST_CONTROL_VIDUPDATE:
510         case -1:
511                 break;
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);
515                 break;
516         case AST_CONTROL_UNHOLD:
517                 ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
518                 ast_moh_stop(chan);
519                 break;
520         default:
521                 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", 
522                         cond, chan->name);
523                 /* The core will play inband indications for us if appropriate */
524                 res = -1;
525         }
526
527         return res;
528 }
529
530 static int console_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
531 {
532         struct console_pvt *pvt = &console_pvt;
533
534         pvt->owner = newchan;
535
536         return 0;
537 }
538
539 /*!
540  * split a string in extension-context, returns pointers to malloc'ed
541  * strings.
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.
547  *
548  * \note came from chan_oss
549  */
550 static char *ast_ext_ctx(struct console_pvt *pvt, const char *src, char **ext, char **ctx)
551 {
552         if (ext == NULL || ctx == NULL)
553                 return NULL;                    /* error */
554
555         *ext = *ctx = NULL;
556
557         if (src && *src != '\0')
558                 *ext = ast_strdup(src);
559
560         if (*ext == NULL)
561                 return NULL;
562
563         if (!pvt->overridecontext) {
564                 /* parse from the right */
565                 *ctx = strrchr(*ext, '@');
566                 if (*ctx)
567                         *(*ctx)++ = '\0';
568         }
569
570         return *ext;
571 }
572
573 static char *cli_console_autoanswer(struct ast_cli_entry *e, int cmd, 
574         struct ast_cli_args *a)
575 {
576         struct console_pvt *pvt = &console_pvt;
577
578         switch (cmd) {
579         case CLI_INIT:
580                 e->command = "console set autoanswer [on|off]";
581                 e->usage =
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";
586                 return NULL;
587
588         case CLI_GENERATE:
589                 return NULL;
590         }
591
592         if (a->argc == e->args - 1) {
593                 ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
594                 return CLI_SUCCESS;
595         }
596
597         if (a->argc != e->args)
598                 return CLI_SHOWUSAGE;
599
600         if (!pvt) {
601                 ast_log(LOG_WARNING, "Cannot find device %s (should not happen!)\n",
602                         pvt->name);
603                 return CLI_FAILURE;
604         }
605
606         if (!strcasecmp(a->argv[e->args-1], "on"))
607                 pvt->autoanswer = 1;
608         else if (!strcasecmp(a->argv[e->args - 1], "off"))
609                 pvt->autoanswer = 0;
610         else
611                 return CLI_SHOWUSAGE;
612
613         return CLI_SUCCESS;
614 }
615
616 static char *cli_console_flash(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
617 {
618         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
619         struct console_pvt *pvt = &console_pvt;
620
621         if (cmd == CLI_INIT) {
622                 e->command = "console flash";
623                 e->usage =
624                         "Usage: console flash\n"
625                         "       Flashes the call currently placed on the console.\n";
626                 return NULL;
627         } else if (cmd == CLI_GENERATE)
628                 return NULL;
629
630         if (a->argc != e->args)
631                 return CLI_SHOWUSAGE;
632
633         if (!pvt->owner) {
634                 ast_cli(a->fd, "No call to flash\n");
635                 return CLI_FAILURE;
636         }
637
638         pvt->hookstate = 0;
639
640         ast_queue_frame(pvt->owner, &f);
641
642         return CLI_SUCCESS;
643 }
644
645 static char *cli_console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
646 {
647         char *s = NULL;
648         const char *mye = NULL, *myc = NULL; 
649         struct console_pvt *pvt = &console_pvt;
650
651         if (cmd == CLI_INIT) {
652                 e->command = "console dial";
653                 e->usage =
654                         "Usage: console dial [extension[@context]]\n"
655                         "       Dials a given extension (and context if specified)\n";
656                 return NULL;
657         } else if (cmd == CLI_GENERATE)
658                 return NULL;
659
660         if (a->argc > e->args + 1)
661                 return CLI_SHOWUSAGE;
662
663         if (pvt->owner) {       /* already in a call */
664                 int i;
665                 struct ast_frame f = { AST_FRAME_DTMF, 0 };
666
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");
669                         return CLI_FAILURE;
670                 }
671                 s = a->argv[e->args];
672                 /* send the string one char at a time */
673                 for (i = 0; i < strlen(s); i++) {
674                         f.subclass = s[i];
675                         ast_queue_frame(pvt->owner, &f);
676                 }
677                 return CLI_SUCCESS;
678         }
679
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);
686                 mye = ext;
687                 myc = con;
688         }
689
690         /* supply default values if needed */
691         if (ast_strlen_zero(mye))
692                 mye = pvt->exten;
693         if (ast_strlen_zero(myc))
694                 myc = pvt->context;
695
696         if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
697                 console_pvt_lock(pvt);
698                 pvt->hookstate = 1;
699                 console_new(pvt, mye, myc, AST_STATE_RINGING);
700                 console_pvt_unlock(pvt);
701         } else
702                 ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
703
704         if (s)
705                 free(s);
706
707         return CLI_SUCCESS;
708 }
709
710 static char *cli_console_hangup(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
711 {
712         struct console_pvt *pvt = &console_pvt;
713
714         if (cmd == CLI_INIT) {
715                 e->command = "console hangup";
716                 e->usage =
717                         "Usage: console hangup\n"
718                         "       Hangs up any call currently placed on the console.\n";
719                 return NULL;
720         } else if (cmd == CLI_GENERATE)
721                 return NULL;
722
723         if (a->argc != e->args)
724                 return CLI_SHOWUSAGE;
725
726         if (!pvt->owner && !pvt->hookstate) {
727                 ast_cli(a->fd, "No call to hang up\n");
728                 return CLI_FAILURE;
729         }
730
731         pvt->hookstate = 0;
732         if (pvt->owner)
733                 ast_queue_hangup(pvt->owner);
734
735         return CLI_SUCCESS;
736 }
737
738 static char *cli_console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
739 {
740         char *s;
741         struct console_pvt *pvt = &console_pvt;
742         
743         if (cmd == CLI_INIT) {
744                 e->command = "console {mute|unmute}";
745                 e->usage =
746                         "Usage: console {mute|unmute}\n"
747                         "       Mute/unmute the microphone.\n";
748                 return NULL;
749         } else if (cmd == CLI_GENERATE)
750                 return NULL;
751
752         if (a->argc != e->args)
753                 return CLI_SHOWUSAGE;
754
755         s = a->argv[e->args-1];
756         if (!strcasecmp(s, "mute"))
757                 pvt->muted = 1;
758         else if (!strcasecmp(s, "unmute"))
759                 pvt->muted = 0;
760         else
761                 return CLI_SHOWUSAGE;
762
763         ast_verb(1, V_BEGIN "The Console is now %s" V_END, 
764                 pvt->muted ? "Muted" : "Unmuted");
765
766         return CLI_SUCCESS;
767 }
768
769 static char *cli_list_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
770 {
771         PaDeviceIndex index, num, def_input, def_output;
772
773         if (cmd == CLI_INIT) {
774                 e->command = "console list devices";
775                 e->usage =
776                         "Usage: console list devices\n"
777                         "       List all available devices.\n";
778                 return NULL;
779         } else if (cmd == CLI_GENERATE)
780                 return NULL;
781
782         if (a->argc != e->args)
783                 return CLI_SHOWUSAGE;
784
785         ast_cli(a->fd, "Available Devices:\n---------------------------------\n");
786
787         num = Pa_GetDeviceCount();
788         if (!num) {
789                 ast_cli(a->fd, "(None)\n");
790                 return CLI_SUCCESS;
791         }
792
793         def_input = Pa_GetDefaultInputDevice();
794         def_output = Pa_GetDefaultOutputDevice();
795         for (index = 0; index < num; index++) {
796                 const PaDeviceInfo *dev = Pa_GetDeviceInfo(index);
797                 if (!dev)
798                         continue;
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");
804         }
805
806         return CLI_SUCCESS;
807 }
808
809 /*!
810  * \brief answer command from the console
811  */
812 static char *cli_console_answer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
813 {
814         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
815         struct console_pvt *pvt = &console_pvt;
816
817         switch (cmd) {
818         case CLI_INIT:
819                 e->command = "console answer";
820                 e->usage =
821                         "Usage: console answer\n"
822                         "       Answers an incoming call on the console channel.\n";
823                 return NULL;
824
825         case CLI_GENERATE:
826                 return NULL;    /* no completion */
827         }
828
829         if (a->argc != e->args)
830                 return CLI_SHOWUSAGE;
831
832         if (!pvt->owner) {
833                 ast_cli(a->fd, "No one is calling us\n");
834                 return CLI_FAILURE;
835         }
836
837         pvt->hookstate = 1;
838         ast_queue_frame(pvt->owner, &f);
839
840         return CLI_SUCCESS;
841 }
842
843 /*!
844  * \brief Console send text CLI command
845  *
846  * \note concatenate all arguments into a single string. argv is NULL-terminated
847  * so we can use it right away
848  */
849 static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
850 {
851         char buf[TEXT_SIZE];
852         struct console_pvt *pvt = &console_pvt;
853         struct ast_frame f = {
854                 .frametype = AST_FRAME_TEXT,
855                 .data = buf,
856                 .src = "console_send_text",
857         };
858         int len;
859
860         if (cmd == CLI_INIT) {
861                 e->command = "console send text";
862                 e->usage =
863                         "Usage: console send text <message>\n"
864                         "       Sends a text message for display on the remote terminal.\n";
865                 return NULL;
866         } else if (cmd == CLI_GENERATE)
867                 return NULL;
868
869         if (a->argc < e->args + 1)
870                 return CLI_SHOWUSAGE;
871
872         if (!pvt->owner) {
873                 ast_cli(a->fd, "Not in a call\n");
874                 return CLI_FAILURE;
875         }
876
877         ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
878         if (ast_strlen_zero(buf))
879                 return CLI_SHOWUSAGE;
880
881         len = strlen(buf);
882         buf[len] = '\n';
883         f.datalen = len + 1;
884
885         ast_queue_frame(pvt->owner, &f);
886
887         return CLI_SUCCESS;
888 }
889
890 static struct ast_cli_entry cli_console[] = {
891         AST_CLI_DEFINE(cli_console_dial,       "Dial an extension from the console"),
892         AST_CLI_DEFINE(cli_console_hangup,     "Hangup a call on the console"),
893         AST_CLI_DEFINE(cli_console_mute,       "Disable/Enable mic input"),
894         AST_CLI_DEFINE(cli_console_answer,     "Answer an incoming console call"),
895         AST_CLI_DEFINE(cli_console_sendtext,   "Send text to a connected party"),
896         AST_CLI_DEFINE(cli_console_flash,      "Send a flash to the connected party"),
897         AST_CLI_DEFINE(cli_console_autoanswer, "Turn autoanswer on or off"),
898         AST_CLI_DEFINE(cli_list_devices,       "List available devices"),
899 };
900
901 /*!
902  * \brief Set default values for a pvt struct
903  *
904  * \note This function expects the pvt lock to be held.
905  */
906 static void set_pvt_defaults(struct console_pvt *pvt, int reload)
907 {
908         if (!reload) {
909                 /* This should be changed for multiple device support.  Right now,
910                  * there is no way to change the name of a device.  The default
911                  * input and output sound devices are the only ones supported. */
912                 ast_string_field_set(pvt, name, "default");
913         }
914
915         ast_string_field_set(pvt, mohinterpret, "default");
916         ast_string_field_set(pvt, context, "default");
917         ast_string_field_set(pvt, exten, "s");
918         ast_string_field_set(pvt, language, "");
919         ast_string_field_set(pvt, cid_num, "");
920         ast_string_field_set(pvt, cid_name, "");
921
922         pvt->overridecontext = 0;
923         pvt->autoanswer = 0;
924 }
925
926 static void store_callerid(struct console_pvt *pvt, const char *value)
927 {
928         char cid_name[256];
929         char cid_num[256];
930
931         ast_callerid_split(value, cid_name, sizeof(cid_name), 
932                 cid_num, sizeof(cid_num));
933
934         ast_string_field_set(pvt, cid_name, cid_name);
935         ast_string_field_set(pvt, cid_num, cid_num);
936 }
937
938 /*!
939  * \brief Store a configuration parameter in a pvt struct
940  *
941  * \note This function expects the pvt lock to be held.
942  */
943 static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
944 {
945         if (!ast_jb_read_conf(&global_jbconf, var, value))
946                 return;
947
948         CV_START(var, value);
949
950         CV_STRFIELD("context", pvt, context);
951         CV_STRFIELD("extension", pvt, exten);
952         CV_STRFIELD("mohinterpret", pvt, mohinterpret);
953         CV_STRFIELD("language", pvt, language);
954         CV_F("callerid", store_callerid(pvt, value));
955         CV_BOOL("overridecontext", pvt->overridecontext);
956         CV_BOOL("autoanswer", pvt->autoanswer);
957         
958         ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
959
960         CV_END;
961 }
962
963 /*!
964  * \brief Load the configuration
965  * \param reload if this was called due to a reload
966  * \retval 0 succcess
967  * \retval -1 failure
968  */
969 static int load_config(int reload)
970 {
971         struct ast_config *cfg;
972         struct ast_variable *v;
973         struct console_pvt *pvt = &console_pvt;
974         struct ast_flags config_flags = { 0 };
975         int res = -1;
976
977         /* default values */
978         memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
979
980         console_pvt_lock(pvt);
981
982         set_pvt_defaults(pvt, reload);
983
984         if (!(cfg = ast_config_load(config_file, config_flags))) {
985                 ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
986                 goto return_unlock;
987         }
988
989         for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
990                 store_config_core(pvt, v->name, v->value);
991
992         ast_config_destroy(cfg);
993
994         res = 0;
995
996 return_unlock:
997         console_pvt_unlock(pvt);
998         return res;
999 }
1000
1001 static int init_pvt(struct console_pvt *pvt)
1002 {
1003         if (ast_string_field_init(pvt, 32))
1004                 return -1;
1005         
1006         if (ast_mutex_init(&pvt->__lock)) {
1007                 ast_log(LOG_ERROR, "Failed to initialize mutex\n");
1008                 return -1;
1009         }
1010
1011         return 0;
1012 }
1013
1014 static void destroy_pvt(struct console_pvt *pvt)
1015 {
1016         ast_string_field_free_memory(pvt);
1017         
1018         ast_mutex_destroy(&pvt->__lock);
1019 }
1020
1021 static int unload_module(void)
1022 {
1023         struct console_pvt *pvt = &console_pvt;
1024
1025         if (pvt->hookstate)
1026                 stop_stream(pvt);
1027
1028         Pa_Terminate();
1029
1030         ast_channel_unregister(&console_tech);
1031         ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
1032
1033         destroy_pvt(pvt);
1034
1035         return 0;
1036 }
1037
1038 static int load_module(void)
1039 {
1040         PaError res;
1041         struct console_pvt *pvt = &console_pvt;
1042
1043         if (init_pvt(pvt))
1044                 goto return_error;
1045
1046         if (load_config(0))
1047                 goto return_error;
1048
1049         res = Pa_Initialize();
1050         if (res != paNoError) {
1051                 ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
1052                         res, Pa_GetErrorText(res));
1053                 goto return_error_pa_init;
1054         }
1055
1056         if (ast_channel_register(&console_tech)) {
1057                 ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
1058                 goto return_error_chan_reg;
1059         }
1060
1061         if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
1062                 goto return_error_cli_reg;
1063
1064         return AST_MODULE_LOAD_SUCCESS;
1065
1066 return_error_cli_reg:
1067         ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
1068 return_error_chan_reg:
1069         ast_channel_unregister(&console_tech);
1070 return_error_pa_init:
1071         Pa_Terminate();
1072 return_error:
1073         destroy_pvt(pvt);
1074
1075         return AST_MODULE_LOAD_DECLINE;
1076 }
1077
1078 static int reload(void)
1079 {
1080         return load_config(1);
1081 }
1082
1083 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Console Channel Driver",
1084                 .load = load_module,
1085                 .unload = unload_module,
1086                 .reload = reload,
1087 );