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