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