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