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