b6dbeae22b5d4fad4c2aa0b4c3fd6b0e3d9a465c
[asterisk/asterisk.git] / channels / chan_oss.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Use /dev/dsp as a channel, and the console to command it :).
5  *
6  * The full-duplex "simulation" is pretty weak.  This is generally a 
7  * VERY BADLY WRITTEN DRIVER so please don't use it as a model for
8  * writing a driver.
9  * 
10  * Copyright (C) 1999 - 2005, Digium, Inc.
11  *
12  * Mark Spencer <markster@digium.com>
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License
16  */
17
18 #include <asterisk/lock.h>
19 #include <asterisk/frame.h>
20 #include <asterisk/logger.h>
21 #include <asterisk/channel.h>
22 #include <asterisk/module.h>
23 #include <asterisk/channel_pvt.h>
24 #include <asterisk/options.h>
25 #include <asterisk/pbx.h>
26 #include <asterisk/config.h>
27 #include <asterisk/cli.h>
28 #include <asterisk/utils.h>
29 #include <asterisk/causes.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <errno.h>
33 #include <sys/ioctl.h>
34 #include <sys/time.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #ifdef __linux
39 #include <linux/soundcard.h>
40 #elif defined(__FreeBSD__)
41 #include <sys/soundcard.h>
42 #else
43 #include <soundcard.h>
44 #endif
45 #include "busy.h"
46 #include "ringtone.h"
47 #include "ring10.h"
48 #include "answer.h"
49
50 /* Which device to use */
51 #if defined( __OpenBSD__ ) || defined( __NetBSD__ )
52 #define DEV_DSP "/dev/audio"
53 #else
54 #define DEV_DSP "/dev/dsp"
55 #endif
56
57 /* Lets use 160 sample frames, just like GSM.  */
58 #define FRAME_SIZE 160
59
60 /* When you set the frame size, you have to come up with
61    the right buffer format as well. */
62 /* 5 64-byte frames = one frame */
63 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
64
65 /* Don't switch between read/write modes faster than every 300 ms */
66 #define MIN_SWITCH_TIME 600
67
68 static struct timeval lasttime;
69
70 static int usecnt;
71 static int silencesuppression = 0;
72 static int silencethreshold = 1000;
73 static int playbackonly = 0;
74
75
76 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
77
78 static char *type = "Console";
79 static char *desc = "OSS Console Channel Driver";
80 static char *tdesc = "OSS Console Channel Driver";
81 static char *config = "oss.conf";
82
83 static char context[AST_MAX_EXTENSION] = "default";
84 static char language[MAX_LANGUAGE] = "";
85 static char exten[AST_MAX_EXTENSION] = "s";
86
87 static int hookstate=0;
88
89 static short silence[FRAME_SIZE] = {0, };
90
91 struct sound {
92         int ind;
93         short *data;
94         int datalen;
95         int samplen;
96         int silencelen;
97         int repeat;
98 };
99
100 static struct sound sounds[] = {
101         { AST_CONTROL_RINGING, ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
102         { AST_CONTROL_BUSY, busy, sizeof(busy)/2, 4000, 4000, 1 },
103         { AST_CONTROL_CONGESTION, busy, sizeof(busy)/2, 2000, 2000, 1 },
104         { AST_CONTROL_RING, ring10, sizeof(ring10)/2, 16000, 32000, 1 },
105         { AST_CONTROL_ANSWER, answer, sizeof(answer)/2, 2200, 0, 0 },
106 };
107
108 /* Sound command pipe */
109 static int sndcmd[2];
110
111 static struct chan_oss_pvt {
112         /* We only have one OSS structure -- near sighted perhaps, but it
113            keeps this driver as simple as possible -- as it should be. */
114         struct ast_channel *owner;
115         char exten[AST_MAX_EXTENSION];
116         char context[AST_MAX_EXTENSION];
117 } oss;
118
119 static int time_has_passed(void)
120 {
121         struct timeval tv;
122         int ms;
123         gettimeofday(&tv, NULL);
124         ms = (tv.tv_sec - lasttime.tv_sec) * 1000 +
125                         (tv.tv_usec - lasttime.tv_usec) / 1000;
126         if (ms > MIN_SWITCH_TIME)
127                 return -1;
128         return 0;
129 }
130
131 /* Number of buffers...  Each is FRAMESIZE/8 ms long.  For example
132    with 160 sample frames, and a buffer size of 3, we have a 60ms buffer, 
133    usually plenty. */
134
135 static pthread_t sthread;
136
137 #define MAX_BUFFER_SIZE 100
138 static int buffersize = 3;
139
140 static int full_duplex = 0;
141
142 /* Are we reading or writing (simulated full duplex) */
143 static int readmode = 1;
144
145 /* File descriptor for sound device */
146 static int sounddev = -1;
147
148 static int autoanswer = 1;
149  
150 #if 0
151 static int calc_loudness(short *frame)
152 {
153         int sum = 0;
154         int x;
155         for (x=0;x<FRAME_SIZE;x++) {
156                 if (frame[x] < 0)
157                         sum -= frame[x];
158                 else
159                         sum += frame[x];
160         }
161         sum = sum/FRAME_SIZE;
162         return sum;
163 }
164 #endif
165
166 static int cursound = -1;
167 static int sampsent = 0;
168 static int silencelen=0;
169 static int offset=0;
170 static int nosound=0;
171
172 static int send_sound(void)
173 {
174         short myframe[FRAME_SIZE];
175         int total = FRAME_SIZE;
176         short *frame = NULL;
177         int amt=0;
178         int res;
179         int myoff;
180         audio_buf_info abi;
181         if (cursound > -1) {
182                 res = ioctl(sounddev, SNDCTL_DSP_GETOSPACE ,&abi);
183                 if (res) {
184                         ast_log(LOG_WARNING, "Unable to read output space\n");
185                         return -1;
186                 }
187                 /* Calculate how many samples we can send, max */
188                 if (total > (abi.fragments * abi.fragsize / 2)) 
189                         total = abi.fragments * abi.fragsize / 2;
190                 res = total;
191                 if (sampsent < sounds[cursound].samplen) {
192                         myoff=0;
193                         while(total) {
194                                 amt = total;
195                                 if (amt > (sounds[cursound].datalen - offset)) 
196                                         amt = sounds[cursound].datalen - offset;
197                                 memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2);
198                                 total -= amt;
199                                 offset += amt;
200                                 sampsent += amt;
201                                 myoff += amt;
202                                 if (offset >= sounds[cursound].datalen)
203                                         offset = 0;
204                         }
205                         /* Set it up for silence */
206                         if (sampsent >= sounds[cursound].samplen) 
207                                 silencelen = sounds[cursound].silencelen;
208                         frame = myframe;
209                 } else {
210                         if (silencelen > 0) {
211                                 frame = silence;
212                                 silencelen -= res;
213                         } else {
214                                 if (sounds[cursound].repeat) {
215                                         /* Start over */
216                                         sampsent = 0;
217                                         offset = 0;
218                                 } else {
219                                         cursound = -1;
220                                         nosound = 0;
221                                 }
222                         }
223                 }
224                 if (frame)
225                         res = write(sounddev, frame, res * 2);
226                 if (res > 0)
227                         return 0;
228                 return res;
229         }
230         return 0;
231 }
232
233 static void *sound_thread(void *unused)
234 {
235         fd_set rfds;
236         fd_set wfds;
237         int max;
238         int res;
239         char ign[4096];
240         if (read(sounddev, ign, sizeof(sounddev)) < 0)
241                 ast_log(LOG_WARNING, "Read error on sound device: %s\n", strerror(errno));
242         for(;;) {
243                 FD_ZERO(&rfds);
244                 FD_ZERO(&wfds);
245                 max = sndcmd[0];
246                 FD_SET(sndcmd[0], &rfds);
247                 if (!oss.owner) {
248                         FD_SET(sounddev, &rfds);
249                         if (sounddev > max)
250                                 max = sounddev;
251                 }
252                 if (cursound > -1) {
253                         FD_SET(sounddev, &wfds);
254                         if (sounddev > max)
255                                 max = sounddev;
256                 }
257                 res = ast_select(max + 1, &rfds, &wfds, NULL, NULL);
258                 if (res < 1) {
259                         ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
260                         continue;
261                 }
262                 if (FD_ISSET(sndcmd[0], &rfds)) {
263                         read(sndcmd[0], &cursound, sizeof(cursound));
264                         silencelen = 0;
265                         offset = 0;
266                         sampsent = 0;
267                 }
268                 if (FD_ISSET(sounddev, &rfds)) {
269                         /* Ignore read */
270                         if (read(sounddev, ign, sizeof(ign)) < 0)
271                                 ast_log(LOG_WARNING, "Read error on sound device: %s\n", strerror(errno));
272                 }
273                 if (FD_ISSET(sounddev, &wfds))
274                         if (send_sound())
275                                 ast_log(LOG_WARNING, "Failed to write sound\n");
276         }
277         /* Never reached */
278         return NULL;
279 }
280
281 #if 0
282 static int silence_suppress(short *buf)
283 {
284 #define SILBUF 3
285         int loudness;
286         static int silentframes = 0;
287         static char silbuf[FRAME_SIZE * 2 * SILBUF];
288         static int silbufcnt=0;
289         if (!silencesuppression)
290                 return 0;
291         loudness = calc_loudness((short *)(buf));
292         if (option_debug)
293                 ast_log(LOG_DEBUG, "loudness is %d\n", loudness);
294         if (loudness < silencethreshold) {
295                 silentframes++;
296                 silbufcnt++;
297                 /* Keep track of the last few bits of silence so we can play
298                    them as lead-in when the time is right */
299                 if (silbufcnt >= SILBUF) {
300                         /* Make way for more buffer */
301                         memmove(silbuf, silbuf + FRAME_SIZE * 2, FRAME_SIZE * 2 * (SILBUF - 1));
302                         silbufcnt--;
303                 }
304                 memcpy(silbuf + FRAME_SIZE * 2 * silbufcnt, buf, FRAME_SIZE * 2);
305                 if (silentframes > 10) {
306                         /* We've had plenty of silence, so compress it now */
307                         return 1;
308                 }
309         } else {
310                 silentframes=0;
311                 /* Write any buffered silence we have, it may have something
312                    important */
313                 if (silbufcnt) {
314                         write(sounddev, silbuf, silbufcnt * FRAME_SIZE);
315                         silbufcnt = 0;
316                 }
317         }
318         return 0;
319 }
320 #endif
321
322 static int setformat(void)
323 {
324         int fmt, desired, res, fd = sounddev;
325         static int warnedalready = 0;
326         static int warnedalready2 = 0;
327         fmt = AFMT_S16_LE;
328         res = ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
329         if (res < 0) {
330                 ast_log(LOG_WARNING, "Unable to set format to 16-bit signed\n");
331                 return -1;
332         }
333         res = ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
334         
335         /* Check to see if duplex set (FreeBSD Bug)*/
336         res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
337         
338         if ((fmt & DSP_CAP_DUPLEX) && !res) {
339                 if (option_verbose > 1) 
340                         ast_verbose(VERBOSE_PREFIX_2 "Console is full duplex\n");
341                 full_duplex = -1;
342         }
343         fmt = 0;
344         res = ioctl(fd, SNDCTL_DSP_STEREO, &fmt);
345         if (res < 0) {
346                 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
347                 return -1;
348         }
349         /* 8000 Hz desired */
350         desired = 8000;
351         fmt = desired;
352         res = ioctl(fd, SNDCTL_DSP_SPEED, &fmt);
353         if (res < 0) {
354                 ast_log(LOG_WARNING, "Failed to set audio device to mono\n");
355                 return -1;
356         }
357         if (fmt != desired) {
358                 if (!warnedalready++)
359                         ast_log(LOG_WARNING, "Requested %d Hz, got %d Hz -- sound may be choppy\n", desired, fmt);
360         }
361 #if 1
362         fmt = BUFFER_FMT;
363         res = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fmt);
364         if (res < 0) {
365                 if (!warnedalready2++)
366                         ast_log(LOG_WARNING, "Unable to set fragment size -- sound may be choppy\n");
367         }
368 #endif
369         return 0;
370 }
371
372 static int soundcard_setoutput(int force)
373 {
374         /* Make sure the soundcard is in output mode.  */
375         int fd = sounddev;
376         if (full_duplex || (!readmode && !force))
377                 return 0;
378         readmode = 0;
379         if (force || time_has_passed()) {
380                 ioctl(sounddev, SNDCTL_DSP_RESET, 0);
381                 /* Keep the same fd reserved by closing the sound device and copying stdin at the same
382                    time. */
383                 /* dup2(0, sound); */ 
384                 close(sounddev);
385                 fd = open(DEV_DSP, O_WRONLY |O_NONBLOCK);
386                 if (fd < 0) {
387                         ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
388                         return -1;
389                 }
390                 /* dup2 will close the original and make fd be sound */
391                 if (dup2(fd, sounddev) < 0) {
392                         ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
393                         return -1;
394                 }
395                 if (setformat()) {
396                         return -1;
397                 }
398                 return 0;
399         }
400         return 1;
401 }
402
403 static int soundcard_setinput(int force)
404 {
405         int fd = sounddev;
406         if (full_duplex || (readmode && !force))
407                 return 0;
408         readmode = -1;
409         if (force || time_has_passed()) {
410                 ioctl(sounddev, SNDCTL_DSP_RESET, 0);
411                 close(sounddev);
412                 /* dup2(0, sound); */
413                 fd = open(DEV_DSP, O_RDONLY | O_NONBLOCK);
414                 if (fd < 0) {
415                         ast_log(LOG_WARNING, "Unable to re-open DSP device: %s\n", strerror(errno));
416                         return -1;
417                 }
418                 /* dup2 will close the original and make fd be sound */
419                 if (dup2(fd, sounddev) < 0) {
420                         ast_log(LOG_WARNING, "dup2() failed: %s\n", strerror(errno));
421                         return -1;
422                 }
423                 if (setformat()) {
424                         return -1;
425                 }
426                 return 0;
427         }
428         return 1;
429 }
430
431 static int soundcard_init(void)
432 {
433         /* Assume it's full duplex for starters */
434         int fd = open(DEV_DSP,  O_RDWR | O_NONBLOCK);
435         if (fd < 0) {
436                 ast_log(LOG_WARNING, "Unable to open %s: %s\n", DEV_DSP, strerror(errno));
437                 return fd;
438         }
439         gettimeofday(&lasttime, NULL);
440         sounddev = fd;
441         setformat();
442         if (!full_duplex) 
443                 soundcard_setinput(1);
444         return sounddev;
445 }
446
447 static int oss_digit(struct ast_channel *c, char digit)
448 {
449         ast_verbose( " << Console Received digit %c >> \n", digit);
450         return 0;
451 }
452
453 static int oss_text(struct ast_channel *c, char *text)
454 {
455         ast_verbose( " << Console Received text %s >> \n", text);
456         return 0;
457 }
458
459 static int oss_call(struct ast_channel *c, char *dest, int timeout)
460 {
461         int res = 3;
462         struct ast_frame f = { 0, };
463         ast_verbose( " << Call placed to '%s' on console >> \n", dest);
464         if (autoanswer) {
465                 ast_verbose( " << Auto-answered >> \n" );
466                 f.frametype = AST_FRAME_CONTROL;
467                 f.subclass = AST_CONTROL_ANSWER;
468                 ast_queue_frame(c, &f);
469         } else {
470                 nosound = 1;
471                 ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
472                 f.frametype = AST_FRAME_CONTROL;
473                 f.subclass = AST_CONTROL_RINGING;
474                 ast_queue_frame(c, &f);
475                 write(sndcmd[1], &res, sizeof(res));
476         }
477         return 0;
478 }
479
480 static void answer_sound(void)
481 {
482         int res;
483         nosound = 1;
484         res = 4;
485         write(sndcmd[1], &res, sizeof(res));
486         
487 }
488
489 static int oss_answer(struct ast_channel *c)
490 {
491         ast_verbose( " << Console call has been answered >> \n");
492         answer_sound();
493         ast_setstate(c, AST_STATE_UP);
494         cursound = -1;
495         nosound=0;
496         return 0;
497 }
498
499 static int oss_hangup(struct ast_channel *c)
500 {
501         int res = 0;
502         cursound = -1;
503         c->pvt->pvt = NULL;
504         oss.owner = NULL;
505         ast_verbose( " << Hangup on console >> \n");
506         ast_mutex_lock(&usecnt_lock);
507         usecnt--;
508         ast_mutex_unlock(&usecnt_lock);
509         if (hookstate) {
510                 if (autoanswer) {
511                         /* Assume auto-hangup too */
512                         hookstate = 0;
513                 } else {
514                         /* Make congestion noise */
515                         res = 2;
516                         write(sndcmd[1], &res, sizeof(res));
517                 }
518         }
519         return 0;
520 }
521
522 static int soundcard_writeframe(short *data)
523 {       
524         /* Write an exactly FRAME_SIZE sized of frame */
525         static int bufcnt = 0;
526         static short buffer[FRAME_SIZE * MAX_BUFFER_SIZE * 5];
527         struct audio_buf_info info;
528         int res;
529         int fd = sounddev;
530         static int warned=0;
531         if (ioctl(fd, SNDCTL_DSP_GETOSPACE, &info)) {
532                 if (!warned)
533                         ast_log(LOG_WARNING, "Error reading output space\n");
534                 bufcnt = buffersize;
535                 warned++;
536         }
537         if ((info.fragments >= buffersize * 5) && (bufcnt == buffersize)) {
538                 /* We've run out of stuff, buffer again */
539                 bufcnt = 0;
540         }
541         if (bufcnt == buffersize) {
542                 /* Write sample immediately */
543                 res = write(fd, ((void *)data), FRAME_SIZE * 2);
544         } else {
545                 /* Copy the data into our buffer */
546                 res = FRAME_SIZE * 2;
547                 memcpy(buffer + (bufcnt * FRAME_SIZE), data, FRAME_SIZE * 2);
548                 bufcnt++;
549                 if (bufcnt == buffersize) {
550                         res = write(fd, ((void *)buffer), FRAME_SIZE * 2 * buffersize);
551                 }
552         }
553         return res;
554 }
555
556
557 static int oss_write(struct ast_channel *chan, struct ast_frame *f)
558 {
559         int res;
560         static char sizbuf[8000];
561         static int sizpos = 0;
562         int len = sizpos;
563         int pos;
564         /* Immediately return if no sound is enabled */
565         if (nosound)
566                 return 0;
567         /* Stop any currently playing sound */
568         cursound = -1;
569         if (!full_duplex && !playbackonly) {
570                 /* If we're half duplex, we have to switch to read mode
571                    to honor immediate needs if necessary.  But if we are in play
572                    back only mode, then we don't switch because the console
573                    is only being used one way -- just to playback something. */
574                 res = soundcard_setinput(1);
575                 if (res < 0) {
576                         ast_log(LOG_WARNING, "Unable to set device to input mode\n");
577                         return -1;
578                 }
579                 return 0;
580         }
581         res = soundcard_setoutput(0);
582         if (res < 0) {
583                 ast_log(LOG_WARNING, "Unable to set output device\n");
584                 return -1;
585         } else if (res > 0) {
586                 /* The device is still in read mode, and it's too soon to change it,
587                    so just pretend we wrote it */
588                 return 0;
589         }
590         /* We have to digest the frame in 160-byte portions */
591         if (f->datalen > sizeof(sizbuf) - sizpos) {
592                 ast_log(LOG_WARNING, "Frame too large\n");
593                 return -1;
594         }
595         memcpy(sizbuf + sizpos, f->data, f->datalen);
596         len += f->datalen;
597         pos = 0;
598         while(len - pos > FRAME_SIZE * 2) {
599                 soundcard_writeframe((short *)(sizbuf + pos));
600                 pos += FRAME_SIZE * 2;
601         }
602         if (len - pos) 
603                 memmove(sizbuf, sizbuf + pos, len - pos);
604         sizpos = len - pos;
605         return 0;
606 }
607
608 static struct ast_frame *oss_read(struct ast_channel *chan)
609 {
610         static struct ast_frame f;
611         static char buf[FRAME_SIZE * 2 + AST_FRIENDLY_OFFSET];
612         static int readpos = 0;
613         int res;
614         
615 #if 0
616         ast_log(LOG_DEBUG, "oss_read()\n");
617 #endif
618                 
619         f.frametype = AST_FRAME_NULL;
620         f.subclass = 0;
621         f.samples = 0;
622         f.datalen = 0;
623         f.data = NULL;
624         f.offset = 0;
625         f.src = type;
626         f.mallocd = 0;
627         f.delivery.tv_sec = 0;
628         f.delivery.tv_usec = 0;
629         
630         res = soundcard_setinput(0);
631         if (res < 0) {
632                 ast_log(LOG_WARNING, "Unable to set input mode\n");
633                 return NULL;
634         }
635         if (res > 0) {
636                 /* Theoretically shouldn't happen, but anyway, return a NULL frame */
637                 return &f;
638         }
639         res = read(sounddev, buf + AST_FRIENDLY_OFFSET + readpos, FRAME_SIZE * 2 - readpos);
640         if (res < 0) {
641                 ast_log(LOG_WARNING, "Error reading from sound device (If you're running 'artsd' then kill it): %s\n", strerror(errno));
642 #if 0
643                 CRASH;
644 #endif          
645                 return NULL;
646         }
647         readpos += res;
648         
649         if (readpos >= FRAME_SIZE * 2) {
650                 /* A real frame */
651                 readpos = 0;
652                 if (chan->_state != AST_STATE_UP) {
653                         /* Don't transmit unless it's up */
654                         return &f;
655                 }
656                 f.frametype = AST_FRAME_VOICE;
657                 f.subclass = AST_FORMAT_SLINEAR;
658                 f.samples = FRAME_SIZE;
659                 f.datalen = FRAME_SIZE * 2;
660                 f.data = buf + AST_FRIENDLY_OFFSET;
661                 f.offset = AST_FRIENDLY_OFFSET;
662                 f.src = type;
663                 f.mallocd = 0;
664                 f.delivery.tv_sec = 0;
665                 f.delivery.tv_usec = 0;
666 #if 0
667                 { static int fd = -1;
668                   if (fd < 0)
669                         fd = open("output.raw", O_RDWR | O_TRUNC | O_CREAT);
670                   write(fd, f.data, f.datalen);
671                 }
672 #endif          
673         }
674         return &f;
675 }
676
677 static int oss_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
678 {
679         struct chan_oss_pvt *p = newchan->pvt->pvt;
680         p->owner = newchan;
681         return 0;
682 }
683
684 static int oss_indicate(struct ast_channel *chan, int cond)
685 {
686         int res;
687         switch(cond) {
688         case AST_CONTROL_BUSY:
689                 res = 1;
690                 break;
691         case AST_CONTROL_CONGESTION:
692                 res = 2;
693                 break;
694         case AST_CONTROL_RINGING:
695                 res = 0;
696                 break;
697         case -1:
698                 cursound = -1;
699                 return 0;
700         default:
701                 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);
702                 return -1;
703         }
704         if (res > -1) {
705                 write(sndcmd[1], &res, sizeof(res));
706         }
707         return 0;       
708 }
709
710 static struct ast_channel *oss_new(struct chan_oss_pvt *p, int state)
711 {
712         struct ast_channel *tmp;
713         tmp = ast_channel_alloc(1);
714         if (tmp) {
715                 snprintf(tmp->name, sizeof(tmp->name), "OSS/%s", DEV_DSP + 5);
716                 tmp->type = type;
717                 tmp->fds[0] = sounddev;
718                 tmp->nativeformats = AST_FORMAT_SLINEAR;
719                 tmp->readformat = AST_FORMAT_SLINEAR;
720                 tmp->writeformat = AST_FORMAT_SLINEAR;
721                 tmp->pvt->pvt = p;
722                 tmp->pvt->send_digit = oss_digit;
723                 tmp->pvt->send_text = oss_text;
724                 tmp->pvt->hangup = oss_hangup;
725                 tmp->pvt->answer = oss_answer;
726                 tmp->pvt->read = oss_read;
727                 tmp->pvt->call = oss_call;
728                 tmp->pvt->write = oss_write;
729                 tmp->pvt->indicate = oss_indicate;
730                 tmp->pvt->fixup = oss_fixup;
731                 if (strlen(p->context))
732                         strncpy(tmp->context, p->context, sizeof(tmp->context)-1);
733                 if (strlen(p->exten))
734                         strncpy(tmp->exten, p->exten, sizeof(tmp->exten)-1);
735                 if (strlen(language))
736                         strncpy(tmp->language, language, sizeof(tmp->language)-1);
737                 p->owner = tmp;
738                 ast_setstate(tmp, state);
739                 ast_mutex_lock(&usecnt_lock);
740                 usecnt++;
741                 ast_mutex_unlock(&usecnt_lock);
742                 ast_update_use_count();
743                 if (state != AST_STATE_DOWN) {
744                         if (ast_pbx_start(tmp)) {
745                                 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
746                                 ast_hangup(tmp);
747                                 tmp = NULL;
748                         }
749                 }
750         }
751         return tmp;
752 }
753
754 static struct ast_channel *oss_request(const char *type, int format, void *data, int *cause)
755 {
756         int oldformat = format;
757         struct ast_channel *tmp;
758         format &= AST_FORMAT_SLINEAR;
759         if (!format) {
760                 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
761                 return NULL;
762         }
763         if (oss.owner) {
764                 ast_log(LOG_NOTICE, "Already have a call on the OSS channel\n");
765                 *cause = AST_CAUSE_BUSY;
766                 return NULL;
767         }
768         tmp= oss_new(&oss, AST_STATE_DOWN);
769         if (!tmp) {
770                 ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
771         }
772         return tmp;
773 }
774
775 static int console_autoanswer(int fd, int argc, char *argv[])
776 {
777         if ((argc != 1) && (argc != 2))
778                 return RESULT_SHOWUSAGE;
779         if (argc == 1) {
780                 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
781                 return RESULT_SUCCESS;
782         } else {
783                 if (!strcasecmp(argv[1], "on"))
784                         autoanswer = -1;
785                 else if (!strcasecmp(argv[1], "off"))
786                         autoanswer = 0;
787                 else
788                         return RESULT_SHOWUSAGE;
789         }
790         return RESULT_SUCCESS;
791 }
792
793 static char *autoanswer_complete(char *line, char *word, int pos, int state)
794 {
795 #ifndef MIN
796 #define MIN(a,b) ((a) < (b) ? (a) : (b))
797 #endif
798         switch(state) {
799         case 0:
800                 if (strlen(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
801                         return strdup("on");
802         case 1:
803                 if (strlen(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
804                         return strdup("off");
805         default:
806                 return NULL;
807         }
808         return NULL;
809 }
810
811 static char autoanswer_usage[] =
812 "Usage: autoanswer [on|off]\n"
813 "       Enables or disables autoanswer feature.  If used without\n"
814 "       argument, displays the current on/off status of autoanswer.\n"
815 "       The default value of autoanswer is in 'oss.conf'.\n";
816
817 static int console_answer(int fd, int argc, char *argv[])
818 {
819         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
820         if (argc != 1)
821                 return RESULT_SHOWUSAGE;
822         if (!oss.owner) {
823                 ast_cli(fd, "No one is calling us\n");
824                 return RESULT_FAILURE;
825         }
826         hookstate = 1;
827         cursound = -1;
828         ast_queue_frame(oss.owner, &f);
829         answer_sound();
830         return RESULT_SUCCESS;
831 }
832
833 static char sendtext_usage[] =
834 "Usage: send text <message>\n"
835 "       Sends a text message for display on the remote terminal.\n";
836
837 static int console_sendtext(int fd, int argc, char *argv[])
838 {
839         int tmparg = 2;
840         char text2send[256] = "";
841         struct ast_frame f = { 0, };
842         if (argc < 2)
843                 return RESULT_SHOWUSAGE;
844         if (!oss.owner) {
845                 ast_cli(fd, "No one is calling us\n");
846                 return RESULT_FAILURE;
847         }
848         if (strlen(text2send))
849                 ast_cli(fd, "Warning: message already waiting to be sent, overwriting\n");
850         text2send[0] = '\0';
851         while(tmparg < argc) {
852                 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
853                 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
854         }
855         if (strlen(text2send)) {
856                 f.frametype = AST_FRAME_TEXT;
857                 f.subclass = 0;
858                 f.data = text2send;
859                 f.datalen = strlen(text2send);
860                 ast_queue_frame(oss.owner, &f);
861         }
862         return RESULT_SUCCESS;
863 }
864
865 static char answer_usage[] =
866 "Usage: answer\n"
867 "       Answers an incoming call on the console (OSS) channel.\n";
868
869 static int console_hangup(int fd, int argc, char *argv[])
870 {
871         if (argc != 1)
872                 return RESULT_SHOWUSAGE;
873         cursound = -1;
874         if (!oss.owner && !hookstate) {
875                 ast_cli(fd, "No call to hangup up\n");
876                 return RESULT_FAILURE;
877         }
878         hookstate = 0;
879         if (oss.owner) {
880                 ast_queue_hangup(oss.owner);
881         }
882         return RESULT_SUCCESS;
883 }
884
885 static int console_flash(int fd, int argc, char *argv[])
886 {
887         struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
888         if (argc != 1)
889                 return RESULT_SHOWUSAGE;
890         cursound = -1;
891         if (!oss.owner) {
892                 ast_cli(fd, "No call to flash\n");
893                 return RESULT_FAILURE;
894         }
895         hookstate = 0;
896         if (oss.owner) {
897                 ast_queue_frame(oss.owner, &f);
898         }
899         return RESULT_SUCCESS;
900 }
901
902 static char hangup_usage[] =
903 "Usage: hangup\n"
904 "       Hangs up any call currently placed on the console.\n";
905
906
907 static char flash_usage[] =
908 "Usage: flash\n"
909 "       Flashes the call currently placed on the console.\n";
910
911 static int console_dial(int fd, int argc, char *argv[])
912 {
913         char tmp[256], *tmp2;
914         char *mye, *myc;
915         int x;
916         struct ast_frame f = { AST_FRAME_DTMF, 0 };
917         if ((argc != 1) && (argc != 2))
918                 return RESULT_SHOWUSAGE;
919         if (oss.owner) {
920                 if (argc == 2) {
921                         for (x=0;x<strlen(argv[1]);x++) {
922                                 f.subclass = argv[1][x];
923                                 ast_queue_frame(oss.owner, &f);
924                         }
925                 } else {
926                         ast_cli(fd, "You're already in a call.  You can use this only to dial digits until you hangup\n");
927                         return RESULT_FAILURE;
928                 }
929                 return RESULT_SUCCESS;
930         }
931         mye = exten;
932         myc = context;
933         if (argc == 2) {
934                 char *stringp=NULL;
935                 strncpy(tmp, argv[1], sizeof(tmp)-1);
936                 stringp=tmp;
937                 strsep(&stringp, "@");
938                 tmp2 = strsep(&stringp, "@");
939                 if (strlen(tmp))
940                         mye = tmp;
941                 if (tmp2 && strlen(tmp2))
942                         myc = tmp2;
943         }
944         if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
945                 strncpy(oss.exten, mye, sizeof(oss.exten)-1);
946                 strncpy(oss.context, myc, sizeof(oss.context)-1);
947                 hookstate = 1;
948                 oss_new(&oss, AST_STATE_RINGING);
949         } else
950                 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
951         return RESULT_SUCCESS;
952 }
953
954 static char dial_usage[] =
955 "Usage: dial [extension[@context]]\n"
956 "       Dials a given extensison (and context if specified)\n";
957
958 static int console_transfer(int fd, int argc, char *argv[])
959 {
960         char tmp[256];
961         char *context;
962         if (argc != 2)
963                 return RESULT_SHOWUSAGE;
964         if (oss.owner && ast_bridged_channel(oss.owner)) {
965                 strncpy(tmp, argv[1], sizeof(tmp) - 1);
966                 context = strchr(tmp, '@');
967                 if (context) {
968                         *context = '\0';
969                         context++;
970                 } else
971                         context = oss.owner->context;
972                 if (ast_exists_extension(ast_bridged_channel(oss.owner), context, tmp, 1, ast_bridged_channel(oss.owner)->cid.cid_num)) {
973                         ast_cli(fd, "Whee, transferring %s to %s@%s.\n", 
974                                         ast_bridged_channel(oss.owner)->name, tmp, context);
975                         if (ast_async_goto(ast_bridged_channel(oss.owner), context, tmp, 1))
976                                 ast_cli(fd, "Failed to transfer :(\n");
977                 } else {
978                         ast_cli(fd, "No such extension exists\n");
979                 }
980         } else {
981                 ast_cli(fd, "There is no call to transfer\n");
982         }
983         return RESULT_SUCCESS;
984 }
985
986 static char transfer_usage[] =
987 "Usage: transfer <extension>[@context]\n"
988 "       Transfers the currently connected call to the given extension (and\n"
989 "context if specified)\n";
990
991 static struct ast_cli_entry myclis[] = {
992         { { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage },
993         { { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage },
994         { { "flash", NULL }, console_flash, "Flash a call on the console", flash_usage },
995         { { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage },
996         { { "transfer", NULL }, console_transfer, "Transfer a call to a different extension", transfer_usage },
997         { { "send", "text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage },
998         { { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete }
999 };
1000
1001 int load_module()
1002 {
1003         int res;
1004         int x;
1005         struct ast_config *cfg;
1006         struct ast_variable *v;
1007         res = pipe(sndcmd);
1008         if (res) {
1009                 ast_log(LOG_ERROR, "Unable to create pipe\n");
1010                 return -1;
1011         }
1012         res = soundcard_init();
1013         if (res < 0) {
1014                 if (option_verbose > 1) {
1015                         ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n");
1016                         ast_verbose(VERBOSE_PREFIX_2 "Turn off OSS support by adding 'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
1017                 }
1018                 return 0;
1019         }
1020         if (!full_duplex)
1021                 ast_log(LOG_WARNING, "XXX I don't work right with non-full duplex sound cards XXX\n");
1022         res = ast_channel_register(type, tdesc, AST_FORMAT_SLINEAR, oss_request);
1023         if (res < 0) {
1024                 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type);
1025                 return -1;
1026         }
1027         for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
1028                 ast_cli_register(myclis + x);
1029         if ((cfg = ast_config_load(config))) {
1030                 v = ast_variable_browse(cfg, "general");
1031                 while(v) {
1032                         if (!strcasecmp(v->name, "autoanswer"))
1033                                 autoanswer = ast_true(v->value);
1034                         else if (!strcasecmp(v->name, "silencesuppression"))
1035                                 silencesuppression = ast_true(v->value);
1036                         else if (!strcasecmp(v->name, "silencethreshold"))
1037                                 silencethreshold = atoi(v->value);
1038                         else if (!strcasecmp(v->name, "context"))
1039                                 strncpy(context, v->value, sizeof(context)-1);
1040                         else if (!strcasecmp(v->name, "language"))
1041                                 strncpy(language, v->value, sizeof(language)-1);
1042                         else if (!strcasecmp(v->name, "extension"))
1043                                 strncpy(exten, v->value, sizeof(exten)-1);
1044                         else if (!strcasecmp(v->name, "playbackonly"))
1045                                 playbackonly = ast_true(v->value);
1046                         v=v->next;
1047                 }
1048                 ast_config_destroy(cfg);
1049         }
1050         ast_pthread_create(&sthread, NULL, sound_thread, NULL);
1051         return 0;
1052 }
1053
1054
1055
1056 int unload_module()
1057 {
1058         int x;
1059         for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
1060                 ast_cli_unregister(myclis + x);
1061         close(sounddev);
1062         if (sndcmd[0] > 0) {
1063                 close(sndcmd[0]);
1064                 close(sndcmd[1]);
1065         }
1066         if (oss.owner)
1067                 ast_softhangup(oss.owner, AST_SOFTHANGUP_APPUNLOAD);
1068         if (oss.owner)
1069                 return -1;
1070         return 0;
1071 }
1072
1073 char *description()
1074 {
1075         return desc;
1076 }
1077
1078 int usecount()
1079 {
1080         int res;
1081         ast_mutex_lock(&usecnt_lock);
1082         res = usecnt;
1083         ast_mutex_unlock(&usecnt_lock);
1084         return res;
1085 }
1086
1087 char *key()
1088 {
1089         return ASTERISK_GPL_KEY;
1090 }