1bdd836eaedbd4b9529d3280373bc8bdff06ff0c
[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  */
46
47 /*** MODULEINFO
48         <depend>portaudio</depend>
49  ***/
50
51 #include "asterisk.h"
52
53 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
54
55 #include <sys/signal.h>  /* SIGURG */
56
57 #include <portaudio.h>
58
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"
66
67 /*! 
68  * \brief The sample rate to request from PortAudio 
69  *
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.
72  */
73 #define SAMPLE_RATE      16000
74
75 /*! 
76  * \brief The number of samples to configure the portaudio stream for
77  *
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.
84  */
85 #define NUM_SAMPLES      320
86
87 /*! \brief Mono Input */
88 #define INPUT_CHANNELS   1
89
90 /*! \brief Mono Output */
91 #define OUTPUT_CHANNELS  1
92
93 /*! 
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.
97  */
98 #define TEXT_SIZE       256
99
100 #ifndef MIN
101 #define MIN(a,b) ((a) < (b) ? (a) : (b))
102 #endif
103 #ifndef MAX
104 #define MAX(a,b) ((a) > (b) ? (a) : (b))
105 #endif
106
107 /*! \brief Dance, Kirby, Dance! @{ */
108 #define V_BEGIN " --- <(\"<) --- "
109 #define V_END   " --- (>\")> ---\n"
110 /*! @} */
111
112 static const char config_file[] = "console.conf";
113
114 /*!
115  * \brief Console pvt structure
116  *
117  * Currently, this is a singleton object.  However, multiple instances will be
118  * needed when this module is updated for multiple device support.
119  */
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);
138         );
139         /*! Current channel for this device */
140         struct ast_channel *owner;
141         /*! Current PortAudio stream for this device */
142         PaStream *stream;
143         /*! A frame for preparing to queue on to the channel */
144         struct ast_frame fr;
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 */
156         ast_mutex_t __lock;
157         /*! ID for the stream monitor thread */
158         pthread_t thread;
159 } console_pvt = {
160         .__lock = AST_MUTEX_INIT_VALUE,
161         .thread = AST_PTHREADT_NULL,
162 };
163
164 /*! 
165  * \brief Global jitterbuffer configuration 
166  *
167  * \note Disabled by default.
168  */
169 static struct ast_jb_conf default_jbconf = {
170         .flags = 0,
171         .max_size = -1,
172         .resync_threshold = -1,
173         .impl = ""
174 };
175 static struct ast_jb_conf global_jbconf;
176
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);
191 /*! @} */
192
193 /*!
194  * \brief Formats natively supported by this module.
195  */
196 #define SUPPORTED_FORMATS ( AST_FORMAT_SLINEAR16 )
197
198 static const struct ast_channel_tech console_tech = {
199         .type = "Console",
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,
213 };
214
215 /*! \brief lock a console_pvt struct */
216 #define console_pvt_lock(pvt) ast_mutex_lock(&(pvt)->__lock)
217
218 /*! \brief unlock a console_pvt struct */
219 #define console_pvt_unlock(pvt) ast_mutex_unlock(&(pvt)->__lock)
220
221 /*!
222  * \brief Stream monitor thread 
223  *
224  * \arg data A pointer to the console_pvt structure that contains the portaudio
225  *      stream that needs to be monitored.
226  *
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.
230  */
231 static void *stream_monitor(void *data)
232 {
233         struct console_pvt *pvt = data;
234         char buf[NUM_SAMPLES * sizeof(int16_t)];
235         PaError res;
236         struct ast_frame f = {
237                 .frametype = AST_FRAME_VOICE,
238                 .subclass = AST_FORMAT_SLINEAR16,
239                 .src = "console_stream_monitor",
240                 .data = buf,
241                 .datalen = sizeof(buf),
242                 .samples = sizeof(buf) / sizeof(int16_t),
243         };
244
245         for (;;) {
246                 pthread_testcancel();
247                 res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
248                 pthread_testcancel();
249
250                 if (res == paNoError)
251                         ast_queue_frame(pvt->owner, &f);
252         }
253
254         return NULL;
255 }
256
257 static int start_stream(struct console_pvt *pvt)
258 {
259         PaError res;
260         int ret_val = 0;
261
262         console_pvt_lock(pvt);
263
264         if (pvt->streamstate)
265                 goto return_unlock;
266
267         pvt->streamstate = 1;
268         ast_debug(1, "Starting stream\n");
269
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));
275                 ret_val = -1;
276                 goto return_unlock;
277         }
278
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));
283                 ret_val = -1;
284                 goto return_unlock;
285         }
286
287         if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
288                 ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
289                 ret_val = -1;
290         }
291
292 return_unlock:
293         console_pvt_unlock(pvt);
294
295         return ret_val;
296 }
297
298 static int stop_stream(struct console_pvt *pvt)
299 {
300         if (!pvt->streamstate)
301                 return 0;
302
303         pthread_cancel(pvt->thread);
304         pthread_kill(pvt->thread, SIGURG);
305         pthread_join(pvt->thread, NULL);
306
307         console_pvt_lock(pvt);
308         Pa_AbortStream(pvt->stream);
309         Pa_CloseStream(pvt->stream);
310         pvt->stream = NULL;
311         pvt->streamstate = 0;
312         console_pvt_unlock(pvt);
313
314         return 0;
315 }
316
317 /*!
318  * \note Called with the pvt struct locked
319  */
320 static struct ast_channel *console_new(struct console_pvt *pvt, const char *ext, const char *ctx, int state)
321 {
322         struct ast_channel *chan;
323
324         if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL, 
325                 ext, ctx, 0, "Console/%s", pvt->name))) {
326                 return NULL;
327         }
328
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;
334
335         pvt->owner = chan;
336
337         if (!ast_strlen_zero(pvt->language))
338                 ast_string_field_set(chan, language, pvt->language);
339
340         ast_jb_configure(chan, &global_jbconf);
341
342         if (state != AST_STATE_DOWN) {
343                 if (ast_pbx_start(chan)) {
344                         chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
345                         ast_hangup(chan);
346                         chan = NULL;
347                 } else
348                         start_stream(pvt);
349         }
350
351         return chan;
352 }
353
354 static struct ast_channel *console_request(const char *type, int format, void *data, int *cause)
355 {
356         int oldformat = format;
357         struct ast_channel *chan;
358         struct console_pvt *pvt = &console_pvt;
359
360         format &= SUPPORTED_FORMATS;
361         if (!format) {
362                 ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%d'\n", oldformat);
363                 return NULL;
364         }
365
366         if (pvt->owner) {
367                 ast_log(LOG_NOTICE, "Console channel already active!\n");
368                 *cause = AST_CAUSE_BUSY;
369                 return NULL;
370         }
371
372         console_pvt_lock(pvt);
373         chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN);
374         console_pvt_unlock(pvt);
375
376         if (!chan)
377                 ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
378
379         return chan;
380 }
381
382 static int console_digit_begin(struct ast_channel *c, char digit)
383 {
384         ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
385
386         return -1; /* non-zero to request inband audio */
387 }
388
389 static int console_digit_end(struct ast_channel *c, char digit, unsigned int duration)
390 {
391         ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END, 
392                 digit, duration);
393
394         return -1; /* non-zero to request inband audio */
395 }
396
397 static int console_text(struct ast_channel *c, const char *text)
398 {
399         ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
400
401         return 0;
402 }
403
404 static int console_hangup(struct ast_channel *c)
405 {
406         struct console_pvt *pvt = &console_pvt;
407
408         ast_verb(1, V_BEGIN "Hangup on Console" V_END);
409
410         pvt->hookstate = 0;
411         c->tech_pvt = NULL;
412         pvt->owner = NULL;
413
414         stop_stream(pvt);
415
416         return 0;
417 }
418
419 static int console_answer(struct ast_channel *c)
420 {
421         struct console_pvt *pvt = &console_pvt;
422
423         ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
424
425         ast_setstate(c, AST_STATE_UP);
426
427         return start_stream(pvt);
428 }
429
430 /*
431  * \brief Implementation of the ast_channel_tech read() callback
432  *
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.
436  * 
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().
441  *
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.
449  */
450 static struct ast_frame *console_read(struct ast_channel *chan)
451 {
452         ast_debug(1, "I should not be called ...\n");
453
454         return &ast_null_frame;
455 }
456
457 static int console_call(struct ast_channel *c, char *dest, int timeout)
458 {
459         struct ast_frame f = { 0, };
460         struct console_pvt *pvt = &console_pvt;
461
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);
464
465         console_pvt_lock(pvt);
466
467         if (pvt->autoanswer) {
468                 pvt->hookstate = 1;
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;
473         } else {
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);
480         }
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         case -1:
506                 res = -1;  /* Ask for inband indications */
507                 break;
508         case AST_CONTROL_PROGRESS:
509         case AST_CONTROL_PROCEEDING:
510         case AST_CONTROL_VIDUPDATE:
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
839         ast_indicate(pvt->owner, -1);
840
841         ast_queue_frame(pvt->owner, &f);
842
843         return CLI_SUCCESS;
844 }
845
846 /*!
847  * \brief Console send text CLI command
848  *
849  * \note concatenate all arguments into a single string. argv is NULL-terminated
850  * so we can use it right away
851  */
852 static char *cli_console_sendtext(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
853 {
854         char buf[TEXT_SIZE];
855         struct console_pvt *pvt = &console_pvt;
856         struct ast_frame f = {
857                 .frametype = AST_FRAME_TEXT,
858                 .data = buf,
859                 .src = "console_send_text",
860         };
861         int len;
862
863         if (cmd == CLI_INIT) {
864                 e->command = "console send text";
865                 e->usage =
866                         "Usage: console send text <message>\n"
867                         "       Sends a text message for display on the remote terminal.\n";
868                 return NULL;
869         } else if (cmd == CLI_GENERATE)
870                 return NULL;
871
872         if (a->argc < e->args + 1)
873                 return CLI_SHOWUSAGE;
874
875         if (!pvt->owner) {
876                 ast_cli(a->fd, "Not in a call\n");
877                 return CLI_FAILURE;
878         }
879
880         ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
881         if (ast_strlen_zero(buf))
882                 return CLI_SHOWUSAGE;
883
884         len = strlen(buf);
885         buf[len] = '\n';
886         f.datalen = len + 1;
887
888         ast_queue_frame(pvt->owner, &f);
889
890         return CLI_SUCCESS;
891 }
892
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"),
902 };
903
904 /*!
905  * \brief Set default values for a pvt struct
906  *
907  * \note This function expects the pvt lock to be held.
908  */
909 static void set_pvt_defaults(struct console_pvt *pvt, int reload)
910 {
911         if (!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");
916         }
917
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, "");
924
925         pvt->overridecontext = 0;
926         pvt->autoanswer = 0;
927 }
928
929 static void store_callerid(struct console_pvt *pvt, const char *value)
930 {
931         char cid_name[256];
932         char cid_num[256];
933
934         ast_callerid_split(value, cid_name, sizeof(cid_name), 
935                 cid_num, sizeof(cid_num));
936
937         ast_string_field_set(pvt, cid_name, cid_name);
938         ast_string_field_set(pvt, cid_num, cid_num);
939 }
940
941 /*!
942  * \brief Store a configuration parameter in a pvt struct
943  *
944  * \note This function expects the pvt lock to be held.
945  */
946 static void store_config_core(struct console_pvt *pvt, const char *var, const char *value)
947 {
948         if (!ast_jb_read_conf(&global_jbconf, var, value))
949                 return;
950
951         CV_START(var, value);
952
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);
960         
961         ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
962
963         CV_END;
964 }
965
966 /*!
967  * \brief Load the configuration
968  * \param reload if this was called due to a reload
969  * \retval 0 succcess
970  * \retval -1 failure
971  */
972 static int load_config(int reload)
973 {
974         struct ast_config *cfg;
975         struct ast_variable *v;
976         struct console_pvt *pvt = &console_pvt;
977         struct ast_flags config_flags = { 0 };
978         int res = -1;
979
980         /* default values */
981         memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
982
983         console_pvt_lock(pvt);
984
985         set_pvt_defaults(pvt, reload);
986
987         if (!(cfg = ast_config_load(config_file, config_flags))) {
988                 ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
989                 goto return_unlock;
990         }
991
992         for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
993                 store_config_core(pvt, v->name, v->value);
994
995         ast_config_destroy(cfg);
996
997         res = 0;
998
999 return_unlock:
1000         console_pvt_unlock(pvt);
1001         return res;
1002 }
1003
1004 static int init_pvt(struct console_pvt *pvt)
1005 {
1006         if (ast_string_field_init(pvt, 32))
1007                 return -1;
1008         
1009         if (ast_mutex_init(&pvt->__lock)) {
1010                 ast_log(LOG_ERROR, "Failed to initialize mutex\n");
1011                 return -1;
1012         }
1013
1014         return 0;
1015 }
1016
1017 static void destroy_pvt(struct console_pvt *pvt)
1018 {
1019         ast_string_field_free_memory(pvt);
1020         
1021         ast_mutex_destroy(&pvt->__lock);
1022 }
1023
1024 static int unload_module(void)
1025 {
1026         struct console_pvt *pvt = &console_pvt;
1027
1028         if (pvt->hookstate)
1029                 stop_stream(pvt);
1030
1031         Pa_Terminate();
1032
1033         ast_channel_unregister(&console_tech);
1034         ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
1035
1036         destroy_pvt(pvt);
1037
1038         return 0;
1039 }
1040
1041 static int load_module(void)
1042 {
1043         PaError res;
1044         struct console_pvt *pvt = &console_pvt;
1045
1046         if (init_pvt(pvt))
1047                 goto return_error;
1048
1049         if (load_config(0))
1050                 goto return_error;
1051
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;
1057         }
1058
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;
1062         }
1063
1064         if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
1065                 goto return_error_cli_reg;
1066
1067         return AST_MODULE_LOAD_SUCCESS;
1068
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:
1074         Pa_Terminate();
1075 return_error:
1076         destroy_pvt(pvt);
1077
1078         return AST_MODULE_LOAD_DECLINE;
1079 }
1080
1081 static int reload(void)
1082 {
1083         return load_config(1);
1084 }
1085
1086 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Console Channel Driver",
1087                 .load = load_module,
1088                 .unload = unload_module,
1089                 .reload = reload,
1090 );