00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <unistd.h>
00030 #include <fcntl.h>
00031 #include <errno.h>
00032 #include <sys/ioctl.h>
00033 #include <sys/time.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <stdio.h>
00037
00038 #define ALSA_PCM_NEW_HW_PARAMS_API
00039 #define ALSA_PCM_NEW_SW_PARAMS_API
00040 #include <alsa/asoundlib.h>
00041
00042 #include "asterisk.h"
00043
00044 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7582 $")
00045
00046 #include "asterisk/frame.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/module.h"
00050 #include "asterisk/options.h"
00051 #include "asterisk/pbx.h"
00052 #include "asterisk/config.h"
00053 #include "asterisk/cli.h"
00054 #include "asterisk/utils.h"
00055 #include "asterisk/causes.h"
00056 #include "asterisk/endian.h"
00057
00058 #include "busy.h"
00059 #include "ringtone.h"
00060 #include "ring10.h"
00061 #include "answer.h"
00062
00063 #ifdef ALSA_MONITOR
00064 #include "alsa-monitor.h"
00065 #endif
00066
00067 #define DEBUG 0
00068
00069 #define ALSA_INDEV "default"
00070 #define ALSA_OUTDEV "default"
00071 #define DESIRED_RATE 8000
00072
00073
00074 #define FRAME_SIZE 160
00075 #define PERIOD_FRAMES 80
00076
00077
00078
00079
00080 #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006);
00081
00082
00083 #define MIN_SWITCH_TIME 600
00084
00085 #if __BYTE_ORDER == __LITTLE_ENDIAN
00086 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
00087 #else
00088 static snd_pcm_format_t format = SND_PCM_FORMAT_S16_BE;
00089 #endif
00090
00091
00092 static char indevname[50] = ALSA_INDEV;
00093 static char outdevname[50] = ALSA_OUTDEV;
00094
00095 #if 0
00096 static struct timeval lasttime;
00097 #endif
00098
00099 static int usecnt;
00100 static int silencesuppression = 0;
00101 static int silencethreshold = 1000;
00102
00103 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00104 AST_MUTEX_DEFINE_STATIC(alsalock);
00105
00106 static const char type[] = "Console";
00107 static const char desc[] = "ALSA Console Channel Driver";
00108 static const char tdesc[] = "ALSA Console Channel Driver";
00109 static const char config[] = "alsa.conf";
00110
00111 static char context[AST_MAX_CONTEXT] = "default";
00112 static char language[MAX_LANGUAGE] = "";
00113 static char exten[AST_MAX_EXTENSION] = "s";
00114
00115 static int hookstate=0;
00116
00117 static short silence[FRAME_SIZE] = {0, };
00118
00119 struct sound {
00120 int ind;
00121 short *data;
00122 int datalen;
00123 int samplen;
00124 int silencelen;
00125 int repeat;
00126 };
00127
00128 static struct sound sounds[] = {
00129 { AST_CONTROL_RINGING, ringtone, sizeof(ringtone)/2, 16000, 32000, 1 },
00130 { AST_CONTROL_BUSY, busy, sizeof(busy)/2, 4000, 4000, 1 },
00131 { AST_CONTROL_CONGESTION, busy, sizeof(busy)/2, 2000, 2000, 1 },
00132 { AST_CONTROL_RING, ring10, sizeof(ring10)/2, 16000, 32000, 1 },
00133 { AST_CONTROL_ANSWER, answer, sizeof(answer)/2, 2200, 0, 0 },
00134 };
00135
00136
00137 static int sndcmd[2];
00138
00139 static struct chan_alsa_pvt {
00140
00141
00142 struct ast_channel *owner;
00143 char exten[AST_MAX_EXTENSION];
00144 char context[AST_MAX_CONTEXT];
00145 #if 0
00146 snd_pcm_t *card;
00147 #endif
00148 snd_pcm_t *icard, *ocard;
00149
00150 } alsa;
00151
00152
00153
00154
00155
00156 pthread_t sthread;
00157
00158 #define MAX_BUFFER_SIZE 100
00159
00160
00161 static int readdev = -1;
00162 static int writedev = -1;
00163
00164 static int autoanswer = 1;
00165
00166 static int cursound = -1;
00167 static int sampsent = 0;
00168 static int silencelen=0;
00169 static int offset=0;
00170 static int nosound=0;
00171
00172
00173 static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause);
00174 static int alsa_digit(struct ast_channel *c, char digit);
00175 static int alsa_text(struct ast_channel *c, const char *text);
00176 static int alsa_hangup(struct ast_channel *c);
00177 static int alsa_answer(struct ast_channel *c);
00178 static struct ast_frame *alsa_read(struct ast_channel *chan);
00179 static int alsa_call(struct ast_channel *c, char *dest, int timeout);
00180 static int alsa_write(struct ast_channel *chan, struct ast_frame *f);
00181 static int alsa_indicate(struct ast_channel *chan, int cond);
00182 static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00183
00184 static const struct ast_channel_tech alsa_tech = {
00185 .type = type,
00186 .description = tdesc,
00187 .capabilities = AST_FORMAT_SLINEAR,
00188 .requester = alsa_request,
00189 .send_digit = alsa_digit,
00190 .send_text = alsa_text,
00191 .hangup = alsa_hangup,
00192 .answer = alsa_answer,
00193 .read = alsa_read,
00194 .call = alsa_call,
00195 .write = alsa_write,
00196 .indicate = alsa_indicate,
00197 .fixup = alsa_fixup,
00198 };
00199
00200 static int send_sound(void)
00201 {
00202 short myframe[FRAME_SIZE];
00203 int total = FRAME_SIZE;
00204 short *frame = NULL;
00205 int amt=0;
00206 int res;
00207 int myoff;
00208 snd_pcm_state_t state;
00209
00210 if (cursound > -1) {
00211 res = total;
00212 if (sampsent < sounds[cursound].samplen) {
00213 myoff=0;
00214 while(total) {
00215 amt = total;
00216 if (amt > (sounds[cursound].datalen - offset))
00217 amt = sounds[cursound].datalen - offset;
00218 memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2);
00219 total -= amt;
00220 offset += amt;
00221 sampsent += amt;
00222 myoff += amt;
00223 if (offset >= sounds[cursound].datalen)
00224 offset = 0;
00225 }
00226
00227 if (sampsent >= sounds[cursound].samplen)
00228 silencelen = sounds[cursound].silencelen;
00229 frame = myframe;
00230 } else {
00231 if (silencelen > 0) {
00232 frame = silence;
00233 silencelen -= res;
00234 } else {
00235 if (sounds[cursound].repeat) {
00236
00237 sampsent = 0;
00238 offset = 0;
00239 } else {
00240 cursound = -1;
00241 nosound = 0;
00242 }
00243 return 0;
00244 }
00245 }
00246
00247 if (res == 0 || !frame) {
00248 return 0;
00249 }
00250 #ifdef ALSA_MONITOR
00251 alsa_monitor_write((char *)frame, res * 2);
00252 #endif
00253 state = snd_pcm_state(alsa.ocard);
00254 if (state == SND_PCM_STATE_XRUN) {
00255 snd_pcm_prepare(alsa.ocard);
00256 }
00257 res = snd_pcm_writei(alsa.ocard, frame, res);
00258 if (res > 0)
00259 return 0;
00260 return 0;
00261 }
00262 return 0;
00263 }
00264
00265 static void *sound_thread(void *unused)
00266 {
00267 fd_set rfds;
00268 fd_set wfds;
00269 int max;
00270 int res;
00271 for(;;) {
00272 FD_ZERO(&rfds);
00273 FD_ZERO(&wfds);
00274 max = sndcmd[0];
00275 FD_SET(sndcmd[0], &rfds);
00276 if (cursound > -1) {
00277 FD_SET(writedev, &wfds);
00278 if (writedev > max)
00279 max = writedev;
00280 }
00281 #ifdef ALSA_MONITOR
00282 if (!alsa.owner) {
00283 FD_SET(readdev, &rfds);
00284 if (readdev > max)
00285 max = readdev;
00286 }
00287 #endif
00288 res = ast_select(max + 1, &rfds, &wfds, NULL, NULL);
00289 if (res < 1) {
00290 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
00291 continue;
00292 }
00293 #ifdef ALSA_MONITOR
00294 if (FD_ISSET(readdev, &rfds)) {
00295
00296 snd_pcm_state_t state;
00297 short buf[FRAME_SIZE];
00298 int r;
00299
00300 state = snd_pcm_state(alsa.ocard);
00301 if (state == SND_PCM_STATE_XRUN) {
00302 snd_pcm_prepare(alsa.ocard);
00303 }
00304 r = snd_pcm_readi(alsa.icard, buf, FRAME_SIZE);
00305 if (r == -EPIPE) {
00306 #if DEBUG
00307 ast_log(LOG_ERROR, "XRUN read\n");
00308 #endif
00309 snd_pcm_prepare(alsa.icard);
00310 } else if (r == -ESTRPIPE) {
00311 ast_log(LOG_ERROR, "-ESTRPIPE\n");
00312 snd_pcm_prepare(alsa.icard);
00313 } else if (r < 0) {
00314 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
00315 } else
00316 alsa_monitor_read((char *)buf, r * 2);
00317 }
00318 #endif
00319 if (FD_ISSET(sndcmd[0], &rfds)) {
00320 read(sndcmd[0], &cursound, sizeof(cursound));
00321 silencelen = 0;
00322 offset = 0;
00323 sampsent = 0;
00324 }
00325 if (FD_ISSET(writedev, &wfds))
00326 if (send_sound())
00327 ast_log(LOG_WARNING, "Failed to write sound\n");
00328 }
00329
00330 return NULL;
00331 }
00332
00333 static snd_pcm_t *alsa_card_init(char *dev, snd_pcm_stream_t stream)
00334 {
00335 int err;
00336 int direction;
00337 snd_pcm_t *handle = NULL;
00338 snd_pcm_hw_params_t *hwparams = NULL;
00339 snd_pcm_sw_params_t *swparams = NULL;
00340 struct pollfd pfd;
00341 snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4;
00342
00343 snd_pcm_uframes_t buffer_size = 0;
00344
00345 unsigned int rate = DESIRED_RATE;
00346 #if 0
00347 unsigned int per_min = 1;
00348 #endif
00349
00350 snd_pcm_uframes_t start_threshold, stop_threshold;
00351
00352 err = snd_pcm_open(&handle, dev, stream, O_NONBLOCK);
00353 if (err < 0) {
00354 ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err));
00355 return NULL;
00356 } else {
00357 ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write");
00358 }
00359
00360 snd_pcm_hw_params_alloca(&hwparams);
00361 snd_pcm_hw_params_any(handle, hwparams);
00362
00363 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
00364 if (err < 0) {
00365 ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err));
00366 }
00367
00368 err = snd_pcm_hw_params_set_format(handle, hwparams, format);
00369 if (err < 0) {
00370 ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err));
00371 }
00372
00373 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
00374 if (err < 0) {
00375 ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err));
00376 }
00377
00378 direction = 0;
00379 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction);
00380 if (rate != DESIRED_RATE) {
00381 ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate);
00382 }
00383
00384 direction = 0;
00385 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction);
00386 if (err < 0) {
00387 ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err));
00388 } else {
00389 ast_log(LOG_DEBUG, "Period size is %d\n", err);
00390 }
00391
00392 buffer_size = 4096 * 2;
00393 err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
00394 if (err < 0) {
00395 ast_log(LOG_WARNING, "Problem setting buffer size of %ld: %s\n", buffer_size, snd_strerror(err));
00396 } else {
00397 ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err);
00398 }
00399
00400 #if 0
00401 direction = 0;
00402 err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction);
00403 if (err < 0) {
00404 ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err));
00405 }
00406
00407 err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0);
00408 if (err < 0) {
00409 ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err));
00410 }
00411 #endif
00412
00413 err = snd_pcm_hw_params(handle, hwparams);
00414 if (err < 0) {
00415 ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err));
00416 }
00417
00418 snd_pcm_sw_params_alloca(&swparams);
00419 snd_pcm_sw_params_current(handle, swparams);
00420
00421 #if 1
00422 if (stream == SND_PCM_STREAM_PLAYBACK) {
00423 start_threshold = period_size;
00424 } else {
00425 start_threshold = 1;
00426 }
00427
00428 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
00429 if (err < 0) {
00430 ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err));
00431 }
00432 #endif
00433
00434 #if 1
00435 if (stream == SND_PCM_STREAM_PLAYBACK) {
00436 stop_threshold = buffer_size;
00437 } else {
00438 stop_threshold = buffer_size;
00439 }
00440 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
00441 if (err < 0) {
00442 ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err));
00443 }
00444 #endif
00445 #if 0
00446 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, PERIOD_FRAMES);
00447 if (err < 0) {
00448 ast_log(LOG_ERROR, "Unable to set xfer alignment: %s\n", snd_strerror(err));
00449 }
00450 #endif
00451
00452 #if 0
00453 err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold);
00454 if (err < 0) {
00455 ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err));
00456 }
00457 #endif
00458 err = snd_pcm_sw_params(handle, swparams);
00459 if (err < 0) {
00460 ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err));
00461 }
00462
00463 err = snd_pcm_poll_descriptors_count(handle);
00464 if (err <= 0) {
00465 ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
00466 }
00467
00468 if (err != 1) {
00469 ast_log(LOG_DEBUG, "Can't handle more than one device\n");
00470 }
00471
00472 snd_pcm_poll_descriptors(handle, &pfd, err);
00473 ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd);
00474
00475 if (stream == SND_PCM_STREAM_CAPTURE)
00476 readdev = pfd.fd;
00477 else
00478 writedev = pfd.fd;
00479
00480 return handle;
00481 }
00482
00483 static int soundcard_init(void)
00484 {
00485 alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
00486 alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);
00487
00488 if (!alsa.icard || !alsa.ocard) {
00489 ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n");
00490 return -1;
00491 }
00492
00493 return readdev;
00494 }
00495
00496 static int alsa_digit(struct ast_channel *c, char digit)
00497 {
00498 ast_mutex_lock(&alsalock);
00499 ast_verbose( " << Console Received digit %c >> \n", digit);
00500 ast_mutex_unlock(&alsalock);
00501 return 0;
00502 }
00503
00504 static int alsa_text(struct ast_channel *c, const char *text)
00505 {
00506 ast_mutex_lock(&alsalock);
00507 ast_verbose( " << Console Received text %s >> \n", text);
00508 ast_mutex_unlock(&alsalock);
00509 return 0;
00510 }
00511
00512 static void grab_owner(void)
00513 {
00514 while(alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) {
00515 ast_mutex_unlock(&alsalock);
00516 usleep(1);
00517 ast_mutex_lock(&alsalock);
00518 }
00519 }
00520
00521 static int alsa_call(struct ast_channel *c, char *dest, int timeout)
00522 {
00523 int res = 3;
00524 struct ast_frame f = { AST_FRAME_CONTROL };
00525 ast_mutex_lock(&alsalock);
00526 ast_verbose( " << Call placed to '%s' on console >> \n", dest);
00527 if (autoanswer) {
00528 ast_verbose( " << Auto-answered >> \n" );
00529 grab_owner();
00530 if (alsa.owner) {
00531 f.subclass = AST_CONTROL_ANSWER;
00532 ast_queue_frame(alsa.owner, &f);
00533 ast_mutex_unlock(&alsa.owner->lock);
00534 }
00535 } else {
00536 ast_verbose( " << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
00537 grab_owner();
00538 if (alsa.owner) {
00539 f.subclass = AST_CONTROL_RINGING;
00540 ast_queue_frame(alsa.owner, &f);
00541 ast_mutex_unlock(&alsa.owner->lock);
00542 }
00543 write(sndcmd[1], &res, sizeof(res));
00544 }
00545 snd_pcm_prepare(alsa.icard);
00546 snd_pcm_start(alsa.icard);
00547 ast_mutex_unlock(&alsalock);
00548 return 0;
00549 }
00550
00551 static void answer_sound(void)
00552 {
00553 int res;
00554 nosound = 1;
00555 res = 4;
00556 write(sndcmd[1], &res, sizeof(res));
00557
00558 }
00559
00560 static int alsa_answer(struct ast_channel *c)
00561 {
00562 ast_mutex_lock(&alsalock);
00563 ast_verbose( " << Console call has been answered >> \n");
00564 answer_sound();
00565 ast_setstate(c, AST_STATE_UP);
00566 cursound = -1;
00567 snd_pcm_prepare(alsa.icard);
00568 snd_pcm_start(alsa.icard);
00569 ast_mutex_unlock(&alsalock);
00570 return 0;
00571 }
00572
00573 static int alsa_hangup(struct ast_channel *c)
00574 {
00575 int res;
00576 ast_mutex_lock(&alsalock);
00577 cursound = -1;
00578 c->tech_pvt = NULL;
00579 alsa.owner = NULL;
00580 ast_verbose( " << Hangup on console >> \n");
00581 ast_mutex_lock(&usecnt_lock);
00582 usecnt--;
00583 ast_mutex_unlock(&usecnt_lock);
00584 if (hookstate) {
00585 if (autoanswer) {
00586 hookstate = 0;
00587 } else {
00588
00589 res = 2;
00590 write(sndcmd[1], &res, sizeof(res));
00591 hookstate = 0;
00592 }
00593 }
00594 snd_pcm_drop(alsa.icard);
00595 ast_mutex_unlock(&alsalock);
00596 return 0;
00597 }
00598
00599 static int alsa_write(struct ast_channel *chan, struct ast_frame *f)
00600 {
00601 static char sizbuf[8000];
00602 static int sizpos = 0;
00603 int len = sizpos;
00604 int pos;
00605 int res = 0;
00606
00607 snd_pcm_state_t state;
00608
00609 if (nosound)
00610 return 0;
00611 ast_mutex_lock(&alsalock);
00612
00613 if (cursound != -1) {
00614 snd_pcm_drop(alsa.ocard);
00615 snd_pcm_prepare(alsa.ocard);
00616 cursound = -1;
00617 }
00618
00619
00620
00621 if (f->datalen > sizeof(sizbuf) - sizpos) {
00622 ast_log(LOG_WARNING, "Frame too large\n");
00623 res = -1;
00624 } else {
00625 memcpy(sizbuf + sizpos, f->data, f->datalen);
00626 len += f->datalen;
00627 pos = 0;
00628 #ifdef ALSA_MONITOR
00629 alsa_monitor_write(sizbuf, len);
00630 #endif
00631 state = snd_pcm_state(alsa.ocard);
00632 if (state == SND_PCM_STATE_XRUN) {
00633 snd_pcm_prepare(alsa.ocard);
00634 }
00635 res = snd_pcm_writei(alsa.ocard, sizbuf, len/2);
00636 if (res == -EPIPE) {
00637 #if DEBUG
00638 ast_log(LOG_DEBUG, "XRUN write\n");
00639 #endif
00640 snd_pcm_prepare(alsa.ocard);
00641 res = snd_pcm_writei(alsa.ocard, sizbuf, len/2);
00642 if (res != len/2) {
00643 ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res));
00644 res = -1;
00645 } else if (res < 0) {
00646 ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res));
00647 res = -1;
00648 }
00649 } else {
00650 if (res == -ESTRPIPE) {
00651 ast_log(LOG_ERROR, "You've got some big problems\n");
00652 } else if (res < 0)
00653 ast_log(LOG_NOTICE, "Error %d on write\n", res);
00654 }
00655 }
00656 ast_mutex_unlock(&alsalock);
00657 if (res > 0)
00658 res = 0;
00659 return res;
00660 }
00661
00662
00663 static struct ast_frame *alsa_read(struct ast_channel *chan)
00664 {
00665 static struct ast_frame f;
00666 static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET/2];
00667 short *buf;
00668 static int readpos = 0;
00669 static int left = FRAME_SIZE;
00670 snd_pcm_state_t state;
00671 int r = 0;
00672 int off = 0;
00673
00674 ast_mutex_lock(&alsalock);
00675
00676 f.frametype = AST_FRAME_NULL;
00677 f.subclass = 0;
00678 f.samples = 0;
00679 f.datalen = 0;
00680 f.data = NULL;
00681 f.offset = 0;
00682 f.src = type;
00683 f.mallocd = 0;
00684 f.delivery.tv_sec = 0;
00685 f.delivery.tv_usec = 0;
00686
00687 state = snd_pcm_state(alsa.icard);
00688 if ((state != SND_PCM_STATE_PREPARED) &&
00689 (state != SND_PCM_STATE_RUNNING)) {
00690 snd_pcm_prepare(alsa.icard);
00691 }
00692
00693 buf = __buf + AST_FRIENDLY_OFFSET/2;
00694
00695 r = snd_pcm_readi(alsa.icard, buf + readpos, left);
00696 if (r == -EPIPE) {
00697 #if DEBUG
00698 ast_log(LOG_ERROR, "XRUN read\n");
00699 #endif
00700 snd_pcm_prepare(alsa.icard);
00701 } else if (r == -ESTRPIPE) {
00702 ast_log(LOG_ERROR, "-ESTRPIPE\n");
00703 snd_pcm_prepare(alsa.icard);
00704 } else if (r < 0) {
00705 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
00706 } else if (r >= 0) {
00707 off -= r;
00708 }
00709
00710 readpos += r;
00711 left -= r;
00712
00713 if (readpos >= FRAME_SIZE) {
00714
00715 readpos = 0;
00716 left = FRAME_SIZE;
00717 if (chan->_state != AST_STATE_UP) {
00718
00719 ast_mutex_unlock(&alsalock);
00720 return &f;
00721 }
00722 f.frametype = AST_FRAME_VOICE;
00723 f.subclass = AST_FORMAT_SLINEAR;
00724 f.samples = FRAME_SIZE;
00725 f.datalen = FRAME_SIZE * 2;
00726 f.data = buf;
00727 f.offset = AST_FRIENDLY_OFFSET;
00728 f.src = type;
00729 f.mallocd = 0;
00730 #ifdef ALSA_MONITOR
00731 alsa_monitor_read((char *)buf, FRAME_SIZE * 2);
00732 #endif
00733
00734 }
00735 ast_mutex_unlock(&alsalock);
00736 return &f;
00737 }
00738
00739 static int alsa_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
00740 {
00741 struct chan_alsa_pvt *p = newchan->tech_pvt;
00742 ast_mutex_lock(&alsalock);
00743 p->owner = newchan;
00744 ast_mutex_unlock(&alsalock);
00745 return 0;
00746 }
00747
00748 static int alsa_indicate(struct ast_channel *chan, int cond)
00749 {
00750 int res = 0;
00751 ast_mutex_lock(&alsalock);
00752 switch(cond) {
00753 case AST_CONTROL_BUSY:
00754 res = 1;
00755 break;
00756 case AST_CONTROL_CONGESTION:
00757 res = 2;
00758 break;
00759 case AST_CONTROL_RINGING:
00760 res = 0;
00761 break;
00762 case -1:
00763 res = -1;
00764 break;
00765 case AST_CONTROL_VIDUPDATE:
00766 res = -1;
00767 break;
00768 default:
00769 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);
00770 res = -1;
00771 }
00772 if (res > -1) {
00773 write(sndcmd[1], &res, sizeof(res));
00774 }
00775 ast_mutex_unlock(&alsalock);
00776 return res;
00777 }
00778
00779 static struct ast_channel *alsa_new(struct chan_alsa_pvt *p, int state)
00780 {
00781 struct ast_channel *tmp;
00782 tmp = ast_channel_alloc(1);
00783 if (tmp) {
00784 tmp->tech = &alsa_tech;
00785 snprintf(tmp->name, sizeof(tmp->name), "ALSA/%s", indevname);
00786 tmp->type = type;
00787 tmp->fds[0] = readdev;
00788 tmp->nativeformats = AST_FORMAT_SLINEAR;
00789 tmp->readformat = AST_FORMAT_SLINEAR;
00790 tmp->writeformat = AST_FORMAT_SLINEAR;
00791 tmp->tech_pvt = p;
00792 if (!ast_strlen_zero(p->context))
00793 ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
00794 if (!ast_strlen_zero(p->exten))
00795 ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten));
00796 if (!ast_strlen_zero(language))
00797 ast_copy_string(tmp->language, language, sizeof(tmp->language));
00798 p->owner = tmp;
00799 ast_setstate(tmp, state);
00800 ast_mutex_lock(&usecnt_lock);
00801 usecnt++;
00802 ast_mutex_unlock(&usecnt_lock);
00803 ast_update_use_count();
00804 if (state != AST_STATE_DOWN) {
00805 if (ast_pbx_start(tmp)) {
00806 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00807 ast_hangup(tmp);
00808 tmp = NULL;
00809 }
00810 }
00811 }
00812 return tmp;
00813 }
00814
00815 static struct ast_channel *alsa_request(const char *type, int format, void *data, int *cause)
00816 {
00817 int oldformat = format;
00818 struct ast_channel *tmp=NULL;
00819 format &= AST_FORMAT_SLINEAR;
00820 if (!format) {
00821 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
00822 return NULL;
00823 }
00824 ast_mutex_lock(&alsalock);
00825 if (alsa.owner) {
00826 ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");
00827 *cause = AST_CAUSE_BUSY;
00828 } else {
00829 tmp= alsa_new(&alsa, AST_STATE_DOWN);
00830 if (!tmp) {
00831 ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");
00832 }
00833 }
00834 ast_mutex_unlock(&alsalock);
00835 return tmp;
00836 }
00837
00838 static int console_autoanswer(int fd, int argc, char *argv[])
00839 {
00840 int res = RESULT_SUCCESS;;
00841 if ((argc != 1) && (argc != 2))
00842 return RESULT_SHOWUSAGE;
00843 ast_mutex_lock(&alsalock);
00844 if (argc == 1) {
00845 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
00846 } else {
00847 if (!strcasecmp(argv[1], "on"))
00848 autoanswer = -1;
00849 else if (!strcasecmp(argv[1], "off"))
00850 autoanswer = 0;
00851 else
00852 res = RESULT_SHOWUSAGE;
00853 }
00854 ast_mutex_unlock(&alsalock);
00855 return res;
00856 }
00857
00858 static char *autoanswer_complete(char *line, char *word, int pos, int state)
00859 {
00860 #ifndef MIN
00861 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00862 #endif
00863 switch(state) {
00864 case 0:
00865 if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
00866 return strdup("on");
00867 case 1:
00868 if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
00869 return strdup("off");
00870 default:
00871 return NULL;
00872 }
00873 return NULL;
00874 }
00875
00876 static char autoanswer_usage[] =
00877 "Usage: autoanswer [on|off]\n"
00878 " Enables or disables autoanswer feature. If used without\n"
00879 " argument, displays the current on/off status of autoanswer.\n"
00880 " The default value of autoanswer is in 'alsa.conf'.\n";
00881
00882 static int console_answer(int fd, int argc, char *argv[])
00883 {
00884 int res = RESULT_SUCCESS;
00885 if (argc != 1)
00886 return RESULT_SHOWUSAGE;
00887 ast_mutex_lock(&alsalock);
00888 if (!alsa.owner) {
00889 ast_cli(fd, "No one is calling us\n");
00890 res = RESULT_FAILURE;
00891 } else {
00892 hookstate = 1;
00893 cursound = -1;
00894 grab_owner();
00895 if (alsa.owner) {
00896 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00897 ast_queue_frame(alsa.owner, &f);
00898 ast_mutex_unlock(&alsa.owner->lock);
00899 }
00900 answer_sound();
00901 }
00902 snd_pcm_prepare(alsa.icard);
00903 snd_pcm_start(alsa.icard);
00904 ast_mutex_unlock(&alsalock);
00905 return RESULT_SUCCESS;
00906 }
00907
00908 static char sendtext_usage[] =
00909 "Usage: send text <message>\n"
00910 " Sends a text message for display on the remote terminal.\n";
00911
00912 static int console_sendtext(int fd, int argc, char *argv[])
00913 {
00914 int tmparg = 2;
00915 int res = RESULT_SUCCESS;
00916 if (argc < 2)
00917 return RESULT_SHOWUSAGE;
00918 ast_mutex_lock(&alsalock);
00919 if (!alsa.owner) {
00920 ast_cli(fd, "No one is calling us\n");
00921 res = RESULT_FAILURE;
00922 } else {
00923 struct ast_frame f = { AST_FRAME_TEXT, 0 };
00924 char text2send[256] = "";
00925 text2send[0] = '\0';
00926 while(tmparg < argc) {
00927 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
00928 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
00929 }
00930 text2send[strlen(text2send) - 1] = '\n';
00931 f.data = text2send;
00932 f.datalen = strlen(text2send) + 1;
00933 grab_owner();
00934 if (alsa.owner) {
00935 ast_queue_frame(alsa.owner, &f);
00936 f.frametype = AST_FRAME_CONTROL;
00937 f.subclass = AST_CONTROL_ANSWER;
00938 f.data = NULL;
00939 f.datalen = 0;
00940 ast_queue_frame(alsa.owner, &f);
00941 ast_mutex_unlock(&alsa.owner->lock);
00942 }
00943 }
00944 ast_mutex_unlock(&alsalock);
00945 return res;
00946 }
00947
00948 static char answer_usage[] =
00949 "Usage: answer\n"
00950 " Answers an incoming call on the console (ALSA) channel.\n";
00951
00952 static int console_hangup(int fd, int argc, char *argv[])
00953 {
00954 int res = RESULT_SUCCESS;
00955 if (argc != 1)
00956 return RESULT_SHOWUSAGE;
00957 cursound = -1;
00958 ast_mutex_lock(&alsalock);
00959 if (!alsa.owner && !hookstate) {
00960 ast_cli(fd, "No call to hangup up\n");
00961 res = RESULT_FAILURE;
00962 } else {
00963 hookstate = 0;
00964 grab_owner();
00965 if (alsa.owner) {
00966 ast_queue_hangup(alsa.owner);
00967 ast_mutex_unlock(&alsa.owner->lock);
00968 }
00969 }
00970 ast_mutex_unlock(&alsalock);
00971 return res;
00972 }
00973
00974 static char hangup_usage[] =
00975 "Usage: hangup\n"
00976 " Hangs up any call currently placed on the console.\n";
00977
00978
00979 static int console_dial(int fd, int argc, char *argv[])
00980 {
00981 char tmp[256], *tmp2;
00982 char *mye, *myc;
00983 char *d;
00984 int res = RESULT_SUCCESS;
00985 if ((argc != 1) && (argc != 2))
00986 return RESULT_SHOWUSAGE;
00987 ast_mutex_lock(&alsalock);
00988 if (alsa.owner) {
00989 if (argc == 2) {
00990 d = argv[1];
00991 grab_owner();
00992 if (alsa.owner) {
00993 struct ast_frame f = { AST_FRAME_DTMF };
00994 while(*d) {
00995 f.subclass = *d;
00996 ast_queue_frame(alsa.owner, &f);
00997 d++;
00998 }
00999 ast_mutex_unlock(&alsa.owner->lock);
01000 }
01001 } else {
01002 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n");
01003 res = RESULT_FAILURE;
01004 }
01005 } else {
01006 mye = exten;
01007 myc = context;
01008 if (argc == 2) {
01009 char *stringp=NULL;
01010 strncpy(tmp, argv[1], sizeof(tmp)-1);
01011 stringp=tmp;
01012 strsep(&stringp, "@");
01013 tmp2 = strsep(&stringp, "@");
01014 if (!ast_strlen_zero(tmp))
01015 mye = tmp;
01016 if (!ast_strlen_zero(tmp2))
01017 myc = tmp2;
01018 }
01019 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
01020 strncpy(alsa.exten, mye, sizeof(alsa.exten)-1);
01021 strncpy(alsa.context, myc, sizeof(alsa.context)-1);
01022 hookstate = 1;
01023 alsa_new(&alsa, AST_STATE_RINGING);
01024 } else
01025 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
01026 }
01027 ast_mutex_unlock(&alsalock);
01028 return res;
01029 }
01030
01031 static char dial_usage[] =
01032 "Usage: dial [extension[@context]]\n"
01033 " Dials a given extension (and context if specified)\n";
01034
01035
01036 static struct ast_cli_entry myclis[] = {
01037 { { "answer", NULL }, console_answer, "Answer an incoming console call", answer_usage },
01038 { { "hangup", NULL }, console_hangup, "Hangup a call on the console", hangup_usage },
01039 { { "dial", NULL }, console_dial, "Dial an extension on the console", dial_usage },
01040 { { "send", "text", NULL }, console_sendtext, "Send text to the remote device", sendtext_usage },
01041 { { "autoanswer", NULL }, console_autoanswer, "Sets/displays autoanswer", autoanswer_usage, autoanswer_complete }
01042 };
01043
01044 int load_module()
01045 {
01046 int res;
01047 int x;
01048 struct ast_config *cfg;
01049 struct ast_variable *v;
01050 if ((cfg = ast_config_load(config))) {
01051 v = ast_variable_browse(cfg, "general");
01052 while(v) {
01053 if (!strcasecmp(v->name, "autoanswer"))
01054 autoanswer = ast_true(v->value);
01055 else if (!strcasecmp(v->name, "silencesuppression"))
01056 silencesuppression = ast_true(v->value);
01057 else if (!strcasecmp(v->name, "silencethreshold"))
01058 silencethreshold = atoi(v->value);
01059 else if (!strcasecmp(v->name, "context"))
01060 strncpy(context, v->value, sizeof(context)-1);
01061 else if (!strcasecmp(v->name, "language"))
01062 strncpy(language, v->value, sizeof(language)-1);
01063 else if (!strcasecmp(v->name, "extension"))
01064 strncpy(exten, v->value, sizeof(exten)-1);
01065 else if (!strcasecmp(v->name, "input_device"))
01066 strncpy(indevname, v->value, sizeof(indevname)-1);
01067 else if (!strcasecmp(v->name, "output_device"))
01068 strncpy(outdevname, v->value, sizeof(outdevname)-1);
01069 v=v->next;
01070 }
01071 ast_config_destroy(cfg);
01072 }
01073 res = pipe(sndcmd);
01074 if (res) {
01075 ast_log(LOG_ERROR, "Unable to create pipe\n");
01076 return -1;
01077 }
01078 res = soundcard_init();
01079 if (res < 0) {
01080 if (option_verbose > 1) {
01081 ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n");
01082 ast_verbose(VERBOSE_PREFIX_2 "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
01083 }
01084 return 0;
01085 }
01086
01087 res = ast_channel_register(&alsa_tech);
01088 if (res < 0) {
01089 ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type);
01090 return -1;
01091 }
01092 for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
01093 ast_cli_register(myclis + x);
01094 ast_pthread_create(&sthread, NULL, sound_thread, NULL);
01095 #ifdef ALSA_MONITOR
01096 if (alsa_monitor_start()) {
01097 ast_log(LOG_ERROR, "Problem starting Monitoring\n");
01098 }
01099 #endif
01100 return 0;
01101 }
01102
01103
01104
01105 int unload_module()
01106 {
01107 int x;
01108
01109 ast_channel_unregister(&alsa_tech);
01110 for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
01111 ast_cli_unregister(myclis + x);
01112 if (alsa.icard)
01113 snd_pcm_close(alsa.icard);
01114 if (alsa.ocard)
01115 snd_pcm_close(alsa.ocard);
01116 if (sndcmd[0] > 0) {
01117 close(sndcmd[0]);
01118 close(sndcmd[1]);
01119 }
01120 if (alsa.owner)
01121 ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD);
01122 if (alsa.owner)
01123 return -1;
01124 return 0;
01125 }
01126
01127 char *description()
01128 {
01129 return (char *) desc;
01130 }
01131
01132 int usecount()
01133 {
01134 return usecnt;
01135 }
01136
01137 char *key()
01138 {
01139 return ASTERISK_GPL_KEY;
01140 }