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