![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
chan_alsa.c File Reference
Definition in file chan_alsa.c.
#include "asterisk.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/endian.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/musiconhold.h"
#include "busy.h"
#include "ringtone.h"
#include "ring10.h"
#include "answer.h"
Include dependency graph for chan_alsa.c:

Go to the source code of this file.
Data Structures | |
| struct | chan_alsa_pvt |
| struct | sound |
Defines | |
| #define | ALSA_INDEV "hw:0,0" |
| #define | ALSA_OUTDEV "hw:0,0" |
| #define | ALSA_PCM_NEW_HW_PARAMS_API |
| #define | ALSA_PCM_NEW_SW_PARAMS_API |
| #define | BUFFER_FMT ((buffersize * 10) << 16) | (0x0006); |
| #define | DEBUG 0 |
| #define | DESIRED_RATE 8000 |
| #define | FRAME_SIZE 160 |
| #define | MAX_BUFFER_SIZE 100 |
| #define | MIN(a, b) ((a) < (b) ? (a) : (b)) |
| #define | MIN_SWITCH_TIME 600 |
| #define | PERIOD_FRAMES 80 |
Functions | |
| static int | alsa_answer (struct ast_channel *c) |
| static int | alsa_call (struct ast_channel *c, char *dest, int timeout) |
| static snd_pcm_t * | alsa_card_init (char *dev, snd_pcm_stream_t stream) |
| static int | alsa_digit (struct ast_channel *c, char digit, unsigned int duration) |
| static int | alsa_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static int | alsa_hangup (struct ast_channel *c) |
| static int | alsa_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen) |
| static struct ast_channel * | alsa_new (struct chan_alsa_pvt *p, int state) |
| static struct ast_frame * | alsa_read (struct ast_channel *chan) |
| static struct ast_channel * | alsa_request (const char *type, int format, void *data, int *cause) |
| static int | alsa_text (struct ast_channel *c, const char *text) |
| static int | alsa_write (struct ast_channel *chan, struct ast_frame *f) |
| static void | answer_sound (void) |
| AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"ALSA Console Channel Driver") | |
| AST_MUTEX_DEFINE_STATIC (alsalock) | |
| static char * | autoanswer_complete (const char *line, const char *word, int pos, int state) |
| static int | console_answer (int fd, int argc, char *argv[]) |
| static int | console_autoanswer (int fd, int argc, char *argv[]) |
| static int | console_dial (int fd, int argc, char *argv[]) |
| static int | console_hangup (int fd, int argc, char *argv[]) |
| static int | console_sendtext (int fd, int argc, char *argv[]) |
| static void | grab_owner (void) |
| static int | load_module (void) |
| static int | send_sound (void) |
| static void * | sound_thread (void *unused) |
| static int | soundcard_init (void) |
| static int | unload_module (void) |
Variables | |
| static struct chan_alsa_pvt | alsa |
| static const struct ast_channel_tech | alsa_tech |
| static const char | answer_usage [] |
| static int | autoanswer = 1 |
| static const char | autoanswer_usage [] |
| static struct ast_cli_entry | cli_alsa [] |
| static const char | config [] = "alsa.conf" |
| static char | context [AST_MAX_CONTEXT] = "default" |
| static int | cursound = -1 |
| static struct ast_jb_conf | default_jbconf |
| static const char | dial_usage [] |
| static char | exten [AST_MAX_EXTENSION] = "s" |
| static snd_pcm_format_t | format = SND_PCM_FORMAT_S16_LE |
| static struct ast_jb_conf | global_jbconf |
| static const char | hangup_usage [] |
| static int | hookstate = 0 |
| static char | indevname [50] = ALSA_INDEV |
| static char | language [MAX_LANGUAGE] = "" |
| static char | mohinterpret [MAX_MUSICCLASS] |
| static int | nosound = 0 |
| static int | offset = 0 |
| static char | outdevname [50] = ALSA_OUTDEV |
| static int | readdev = -1 |
| static int | sampsent = 0 |
| static const char | sendtext_usage [] |
| static short | silence [FRAME_SIZE] = { 0, } |
| static int | silencelen = 0 |
| static int | silencesuppression = 0 |
| static int | silencethreshold = 1000 |
| static int | sndcmd [2] |
| static struct sound | sounds [] |
| pthread_t | sthread |
| static const char | tdesc [] = "ALSA Console Channel Driver" |
| static int | writedev = -1 |
|
|
Definition at line 86 of file chan_alsa.c. |
|
|
Definition at line 87 of file chan_alsa.c. |
|
|
Definition at line 47 of file chan_alsa.c. |
|
|
Definition at line 48 of file chan_alsa.c. |
|
|
Definition at line 97 of file chan_alsa.c. |
|
|
Definition at line 84 of file chan_alsa.c. |
|
|
Definition at line 88 of file chan_alsa.c. Referenced by alsa_card_init(). |
|
|
Definition at line 91 of file chan_alsa.c. Referenced by alsa_read(), oss_read(), send_sound(), sound_thread(), and soundcard_writeframe(). |
|
|
Definition at line 172 of file chan_alsa.c. |
|
|
Referenced by autoanswer_complete(), and send_sound(). |
|
|
Definition at line 100 of file chan_alsa.c. |
|
|
Definition at line 92 of file chan_alsa.c. Referenced by alsa_card_init(). |
|
|
Definition at line 562 of file chan_alsa.c. References alsa, answer_sound(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verbose(), cursound, and chan_alsa_pvt::icard. 00563 { 00564 ast_mutex_lock(&alsalock); 00565 ast_verbose(" << Console call has been answered >> \n"); 00566 answer_sound(); 00567 ast_setstate(c, AST_STATE_UP); 00568 cursound = -1; 00569 snd_pcm_prepare(alsa.icard); 00570 snd_pcm_start(alsa.icard); 00571 ast_mutex_unlock(&alsalock); 00572 return 0; 00573 }
|
|
||||||||||||||||
|
Definition at line 523 of file chan_alsa.c. References alsa, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_verbose(), autoanswer, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, chan_alsa_pvt::owner, sndcmd, and ast_frame::subclass. 00524 { 00525 int res = 3; 00526 struct ast_frame f = { AST_FRAME_CONTROL }; 00527 ast_mutex_lock(&alsalock); 00528 ast_verbose(" << Call placed to '%s' on console >> \n", dest); 00529 if (autoanswer) { 00530 ast_verbose(" << Auto-answered >> \n"); 00531 grab_owner(); 00532 if (alsa.owner) { 00533 f.subclass = AST_CONTROL_ANSWER; 00534 ast_queue_frame(alsa.owner, &f); 00535 ast_mutex_unlock(&alsa.owner->lock); 00536 } 00537 } else { 00538 ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00539 grab_owner(); 00540 if (alsa.owner) { 00541 f.subclass = AST_CONTROL_RINGING; 00542 ast_queue_frame(alsa.owner, &f); 00543 ast_mutex_unlock(&alsa.owner->lock); 00544 } 00545 write(sndcmd[1], &res, sizeof(res)); 00546 } 00547 snd_pcm_prepare(alsa.icard); 00548 snd_pcm_start(alsa.icard); 00549 ast_mutex_unlock(&alsalock); 00550 return 0; 00551 }
|
|
||||||||||||
|
Definition at line 344 of file chan_alsa.c. References ast_log(), DESIRED_RATE, pollfd::fd, LOG_DEBUG, LOG_ERROR, LOG_WARNING, option_debug, PERIOD_FRAMES, readdev, and writedev. Referenced by soundcard_init(). 00345 { 00346 int err; 00347 int direction; 00348 snd_pcm_t *handle = NULL; 00349 snd_pcm_hw_params_t *hwparams = NULL; 00350 snd_pcm_sw_params_t *swparams = NULL; 00351 struct pollfd pfd; 00352 snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4; 00353 /* int period_bytes = 0; */ 00354 snd_pcm_uframes_t buffer_size = 0; 00355 00356 unsigned int rate = DESIRED_RATE; 00357 #if 0 00358 unsigned int per_min = 1; 00359 #endif 00360 /* unsigned int per_max = 8; */ 00361 snd_pcm_uframes_t start_threshold, stop_threshold; 00362 00363 err = snd_pcm_open(&handle, dev, stream, O_NONBLOCK); 00364 if (err < 0) { 00365 ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err)); 00366 return NULL; 00367 } else { 00368 if (option_debug) 00369 ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write"); 00370 } 00371 00372 snd_pcm_hw_params_alloca(&hwparams); 00373 snd_pcm_hw_params_any(handle, hwparams); 00374 00375 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); 00376 if (err < 0) 00377 ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err)); 00378 00379 err = snd_pcm_hw_params_set_format(handle, hwparams, format); 00380 if (err < 0) 00381 ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err)); 00382 00383 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1); 00384 if (err < 0) 00385 ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err)); 00386 00387 direction = 0; 00388 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction); 00389 if (rate != DESIRED_RATE) 00390 ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate); 00391 00392 direction = 0; 00393 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction); 00394 if (err < 0) 00395 ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err)); 00396 else { 00397 if (option_debug) 00398 ast_log(LOG_DEBUG, "Period size is %d\n", err); 00399 } 00400 00401 buffer_size = 4096 * 2; /* period_size * 16; */ 00402 err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); 00403 if (err < 0) 00404 ast_log(LOG_WARNING, "Problem setting buffer size of %ld: %s\n", buffer_size, snd_strerror(err)); 00405 else { 00406 if (option_debug) 00407 ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err); 00408 } 00409 00410 #if 0 00411 direction = 0; 00412 err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction); 00413 if (err < 0) 00414 ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err)); 00415 00416 err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0); 00417 if (err < 0) 00418 ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err)); 00419 #endif 00420 00421 err = snd_pcm_hw_params(handle, hwparams); 00422 if (err < 0) 00423 ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err)); 00424 00425 snd_pcm_sw_params_alloca(&swparams); 00426 snd_pcm_sw_params_current(handle, swparams); 00427 00428 #if 1 00429 if (stream == SND_PCM_STREAM_PLAYBACK) 00430 start_threshold = period_size; 00431 else 00432 start_threshold = 1; 00433 00434 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); 00435 if (err < 0) 00436 ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err)); 00437 #endif 00438 00439 #if 1 00440 if (stream == SND_PCM_STREAM_PLAYBACK) 00441 stop_threshold = buffer_size; 00442 else 00443 stop_threshold = buffer_size; 00444 00445 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); 00446 if (err < 0) 00447 ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err)); 00448 #endif 00449 #if 0 00450 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, PERIOD_FRAMES); 00451 if (err < 0) 00452 ast_log(LOG_ERROR, "Unable to set xfer alignment: %s\n", snd_strerror(err)); 00453 #endif 00454 00455 #if 0 00456 err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold); 00457 if (err < 0) 00458 ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err)); 00459 #endif 00460 err = snd_pcm_sw_params(handle, swparams); 00461 if (err < 0) 00462 ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err)); 00463 00464 err = snd_pcm_poll_descriptors_count(handle); 00465 if (err <= 0) 00466 ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err)); 00467 if (err != 1) { 00468 if (option_debug) 00469 ast_log(LOG_DEBUG, "Can't handle more than one device\n"); 00470 } 00471 00472 snd_pcm_poll_descriptors(handle, &pfd, err); 00473 if (option_debug) 00474 ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd); 00475 00476 if (stream == SND_PCM_STREAM_CAPTURE) 00477 readdev = pfd.fd; 00478 else 00479 writedev = pfd.fd; 00480 00481 return handle; 00482 }
|
|
||||||||||||||||
|
Definition at line 497 of file chan_alsa.c. References ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose(). 00498 { 00499 ast_mutex_lock(&alsalock); 00500 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00501 digit, duration); 00502 ast_mutex_unlock(&alsalock); 00503 return 0; 00504 }
|
|
||||||||||||
|
Definition at line 738 of file chan_alsa.c. References ast_mutex_lock(), ast_mutex_unlock(), chan_alsa_pvt::owner, and ast_channel::tech_pvt. 00739 { 00740 struct chan_alsa_pvt *p = newchan->tech_pvt; 00741 ast_mutex_lock(&alsalock); 00742 p->owner = newchan; 00743 ast_mutex_unlock(&alsalock); 00744 return 0; 00745 }
|
|
|
Definition at line 575 of file chan_alsa.c. References alsa, ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), autoanswer, cursound, chan_alsa_pvt::icard, chan_alsa_pvt::owner, sndcmd, and ast_channel::tech_pvt. 00576 { 00577 int res; 00578 ast_mutex_lock(&alsalock); 00579 cursound = -1; 00580 c->tech_pvt = NULL; 00581 alsa.owner = NULL; 00582 ast_verbose(" << Hangup on console >> \n"); 00583 ast_module_unref(ast_module_info->self); 00584 if (hookstate) { 00585 hookstate = 0; 00586 if (!autoanswer) { 00587 /* Congestion noise */ 00588 res = 2; 00589 write(sndcmd[1], &res, sizeof(res)); 00590 } 00591 } 00592 snd_pcm_drop(alsa.icard); 00593 ast_mutex_unlock(&alsalock); 00594 return 0; 00595 }
|
|
||||||||||||||||||||
|
Definition at line 747 of file chan_alsa.c. References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), LOG_WARNING, and sndcmd. 00748 { 00749 int res = 0; 00750 00751 ast_mutex_lock(&alsalock); 00752 00753 switch (cond) { 00754 case AST_CONTROL_BUSY: 00755 res = 1; 00756 break; 00757 case AST_CONTROL_CONGESTION: 00758 res = 2; 00759 break; 00760 case AST_CONTROL_RINGING: 00761 break; 00762 case -1: 00763 res = -1; 00764 break; 00765 case AST_CONTROL_VIDUPDATE: 00766 res = -1; 00767 break; 00768 case AST_CONTROL_HOLD: 00769 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00770 ast_moh_start(chan, data, mohinterpret); 00771 break; 00772 case AST_CONTROL_UNHOLD: 00773 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00774 ast_moh_stop(chan); 00775 break; 00776 default: 00777 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name); 00778 res = -1; 00779 } 00780 00781 if (res > -1) 00782 write(sndcmd[1], &res, sizeof(res)); 00783 00784 ast_mutex_unlock(&alsalock); 00785 00786 return res; 00787 }
|
|
||||||||||||
|
|
Definition at line 663 of file chan_alsa.c. References ast_channel::_state, alsa, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, ast_frame::data, ast_frame::datalen, ast_frame::delivery, FRAME_SIZE, ast_frame::frametype, chan_alsa_pvt::icard, LOG_ERROR, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, ast_frame::src, and ast_frame::subclass. 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 /* Acknowledge any pending cmd */ 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 = "Console"; 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) && (state != SND_PCM_STATE_RUNNING)) { 00689 snd_pcm_prepare(alsa.icard); 00690 } 00691 00692 buf = __buf + AST_FRIENDLY_OFFSET / 2; 00693 00694 r = snd_pcm_readi(alsa.icard, buf + readpos, left); 00695 if (r == -EPIPE) { 00696 #if DEBUG 00697 ast_log(LOG_ERROR, "XRUN read\n"); 00698 #endif 00699 snd_pcm_prepare(alsa.icard); 00700 } else if (r == -ESTRPIPE) { 00701 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00702 snd_pcm_prepare(alsa.icard); 00703 } else if (r < 0) { 00704 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00705 } else if (r >= 0) { 00706 off -= r; 00707 } 00708 /* Update positions */ 00709 readpos += r; 00710 left -= r; 00711 00712 if (readpos >= FRAME_SIZE) { 00713 /* A real frame */ 00714 readpos = 0; 00715 left = FRAME_SIZE; 00716 if (chan->_state != AST_STATE_UP) { 00717 /* Don't transmit unless it's up */ 00718 ast_mutex_unlock(&alsalock); 00719 return &f; 00720 } 00721 f.frametype = AST_FRAME_VOICE; 00722 f.subclass = AST_FORMAT_SLINEAR; 00723 f.samples = FRAME_SIZE; 00724 f.datalen = FRAME_SIZE * 2; 00725 f.data = buf; 00726 f.offset = AST_FRIENDLY_OFFSET; 00727 f.src = "Console"; 00728 f.mallocd = 0; 00729 #ifdef ALSA_MONITOR 00730 alsa_monitor_read((char *) buf, FRAME_SIZE * 2); 00731 #endif 00732 00733 } 00734 ast_mutex_unlock(&alsalock); 00735 return &f; 00736 }
|
|
||||||||||||||||||||
|
Definition at line 822 of file chan_alsa.c. References alsa, alsa_new(), AST_CAUSE_BUSY, AST_FORMAT_SLINEAR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::owner. 00823 { 00824 int oldformat = format; 00825 struct ast_channel *tmp = NULL; 00826 00827 format &= AST_FORMAT_SLINEAR; 00828 if (!format) { 00829 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat); 00830 return NULL; 00831 } 00832 00833 ast_mutex_lock(&alsalock); 00834 00835 if (alsa.owner) { 00836 ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n"); 00837 *cause = AST_CAUSE_BUSY; 00838 } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN))) 00839 ast_log(LOG_WARNING, "Unable to create new ALSA channel\n"); 00840 00841 ast_mutex_unlock(&alsalock); 00842 00843 return tmp; 00844 }
|
|
||||||||||||
|
Definition at line 506 of file chan_alsa.c. References ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose(). 00507 { 00508 ast_mutex_lock(&alsalock); 00509 ast_verbose(" << Console Received text %s >> \n", text); 00510 ast_mutex_unlock(&alsalock); 00511 return 0; 00512 }
|
|
||||||||||||
|
Definition at line 597 of file chan_alsa.c. References alsa, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), cursound, ast_frame::data, ast_frame::datalen, len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, nosound, chan_alsa_pvt::ocard, and option_debug. 00598 { 00599 static char sizbuf[8000]; 00600 static int sizpos = 0; 00601 int len = sizpos; 00602 int pos; 00603 int res = 0; 00604 /* size_t frames = 0; */ 00605 snd_pcm_state_t state; 00606 00607 /* Immediately return if no sound is enabled */ 00608 if (nosound) 00609 return 0; 00610 00611 ast_mutex_lock(&alsalock); 00612 /* Stop any currently playing sound */ 00613 if (cursound != -1) { 00614 snd_pcm_drop(alsa.ocard); 00615 snd_pcm_prepare(alsa.ocard); 00616 cursound = -1; 00617 } 00618 00619 00620 /* We have to digest the frame in 160-byte portions */ 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 res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2); 00635 if (res == -EPIPE) { 00636 #if DEBUG 00637 if (option_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 }
|
|
|
Definition at line 553 of file chan_alsa.c. References nosound, and sndcmd. Referenced by alsa_answer(), and console_answer(). 00554 { 00555 int res; 00556 nosound = 1; 00557 res = 4; 00558 write(sndcmd[1], &res, sizeof(res)); 00559 00560 }
|
|
||||||||||||
|
|
|
|
|
|
||||||||||||||||||||
|
Definition at line 866 of file chan_alsa.c. References ast_strdup, ast_strlen_zero(), and MIN. 00867 { 00868 #ifndef MIN 00869 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00870 #endif 00871 switch (state) { 00872 case 0: 00873 if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2))) 00874 return ast_strdup("on"); 00875 case 1: 00876 if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3))) 00877 return ast_strdup("off"); 00878 default: 00879 return NULL; 00880 } 00881 return NULL; 00882 }
|
|
||||||||||||||||
|
||||||||||||||||
|
Definition at line 846 of file chan_alsa.c. References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), autoanswer, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 00847 { 00848 int res = RESULT_SUCCESS;; 00849 if ((argc != 2) && (argc != 3)) 00850 return RESULT_SHOWUSAGE; 00851 ast_mutex_lock(&alsalock); 00852 if (argc == 2) { 00853 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off"); 00854 } else { 00855 if (!strcasecmp(argv[2], "on")) 00856 autoanswer = -1; 00857 else if (!strcasecmp(argv[2], "off")) 00858 autoanswer = 0; 00859 else 00860 res = RESULT_SHOWUSAGE; 00861 } 00862 ast_mutex_unlock(&alsalock); 00863 return res; 00864 }
|
|
||||||||||||||||
|
Definition at line 1003 of file chan_alsa.c. References alsa, alsa_new(), ast_cli(), ast_exists_extension(), AST_FRAME_DTMF, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), AST_STATE_RINGING, ast_strlen_zero(), chan_alsa_pvt::context, chan_alsa_pvt::exten, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, strsep(), and ast_frame::subclass. 01004 { 01005 char tmp[256], *tmp2; 01006 char *mye, *myc; 01007 char *d; 01008 int res = RESULT_SUCCESS; 01009 01010 if ((argc != 2) && (argc != 3)) 01011 return RESULT_SHOWUSAGE; 01012 01013 ast_mutex_lock(&alsalock); 01014 01015 if (alsa.owner) { 01016 if (argc == 3) { 01017 d = argv[2]; 01018 grab_owner(); 01019 if (alsa.owner) { 01020 struct ast_frame f = { AST_FRAME_DTMF }; 01021 while (*d) { 01022 f.subclass = *d; 01023 ast_queue_frame(alsa.owner, &f); 01024 d++; 01025 } 01026 ast_mutex_unlock(&alsa.owner->lock); 01027 } 01028 } else { 01029 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n"); 01030 res = RESULT_FAILURE; 01031 } 01032 } else { 01033 mye = exten; 01034 myc = context; 01035 if (argc == 3) { 01036 char *stringp = NULL; 01037 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01038 stringp = tmp; 01039 strsep(&stringp, "@"); 01040 tmp2 = strsep(&stringp, "@"); 01041 if (!ast_strlen_zero(tmp)) 01042 mye = tmp; 01043 if (!ast_strlen_zero(tmp2)) 01044 myc = tmp2; 01045 } 01046 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01047 ast_copy_string(alsa.exten, mye, sizeof(alsa.exten)); 01048 ast_copy_string(alsa.context, myc, sizeof(alsa.context)); 01049 hookstate = 1; 01050 alsa_new(&alsa, AST_STATE_RINGING); 01051 } else 01052 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc); 01053 } 01054 01055 ast_mutex_unlock(&alsalock); 01056 01057 return res; 01058 }
|
|
||||||||||||||||
|
Definition at line 971 of file chan_alsa.c. References alsa, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), cursound, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS. 00972 { 00973 int res = RESULT_SUCCESS; 00974 00975 if (argc != 2) 00976 return RESULT_SHOWUSAGE; 00977 00978 cursound = -1; 00979 00980 ast_mutex_lock(&alsalock); 00981 00982 if (!alsa.owner && !hookstate) { 00983 ast_cli(fd, "No call to hangup up\n"); 00984 res = RESULT_FAILURE; 00985 } else { 00986 hookstate = 0; 00987 grab_owner(); 00988 if (alsa.owner) { 00989 ast_queue_hangup(alsa.owner); 00990 ast_mutex_unlock(&alsa.owner->lock); 00991 } 00992 } 00993 00994 ast_mutex_unlock(&alsalock); 00995 00996 return res; 00997 }
|
|
||||||||||||||||
|
Definition at line 926 of file chan_alsa.c. References alsa, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_frame::subclass. 00927 { 00928 int tmparg = 3; 00929 int res = RESULT_SUCCESS; 00930 00931 if (argc < 3) 00932 return RESULT_SHOWUSAGE; 00933 00934 ast_mutex_lock(&alsalock); 00935 00936 if (!alsa.owner) { 00937 ast_cli(fd, "No one is calling us\n"); 00938 res = RESULT_FAILURE; 00939 } else { 00940 struct ast_frame f = { AST_FRAME_TEXT, 0 }; 00941 char text2send[256] = ""; 00942 text2send[0] = '\0'; 00943 while (tmparg < argc) { 00944 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1); 00945 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1); 00946 } 00947 text2send[strlen(text2send) - 1] = '\n'; 00948 f.data = text2send; 00949 f.datalen = strlen(text2send) + 1; 00950 grab_owner(); 00951 if (alsa.owner) { 00952 ast_queue_frame(alsa.owner, &f); 00953 f.frametype = AST_FRAME_CONTROL; 00954 f.subclass = AST_CONTROL_ANSWER; 00955 f.data = NULL; 00956 f.datalen = 0; 00957 ast_queue_frame(alsa.owner, &f); 00958 ast_mutex_unlock(&alsa.owner->lock); 00959 } 00960 } 00961 00962 ast_mutex_unlock(&alsalock); 00963 00964 return res; 00965 }
|
|
|
Definition at line 514 of file chan_alsa.c. References alsa, ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_channel::lock, and chan_alsa_pvt::owner. Referenced by alsa_call(), console_answer(), console_dial(), console_hangup(), and console_sendtext(). 00515 { 00516 while (alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) { 00517 ast_mutex_unlock(&alsalock); 00518 usleep(1); 00519 ast_mutex_lock(&alsalock); 00520 } 00521 }
|
|
|
Definition at line 1086 of file chan_alsa.c. References ast_config_load(), ast_jb_read_conf(), AST_MODULE_LOAD_DECLINE, ast_true(), ast_variable_browse(), autoanswer, default_jbconf, global_jbconf, ast_variable::name, ast_variable::next, and ast_variable::value. 01087 { 01088 struct ast_config *cfg; 01089 struct ast_variable *v; 01090 01091 /* Copy the default jb config over global_jbconf */ 01092 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01093 01094 strcpy(mohinterpret, "default"); 01095 01096 if (!(cfg = ast_config_load(config))) 01097 return AST_MODULE_LOAD_DECLINE; 01098 01099 v = ast_variable_browse(cfg, "general"); 01100 for (; v; v = v->next) { 01101 /* handle jb conf */ 01102 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 01103 continue; 01104 01105 if (!strcasecmp(v->name, "autoanswer")) 01106 autoanswer = ast_true(v->value); 01107 else if (!strcasecmp(v->name, "silencesuppression")) 01108 silencesuppression = ast_true(v->value); 01109 else if (!strcasecmp(v->name, "silencethreshold")) 01110 silencethreshold = atoi(v->value); 01111 else if (!strcasecmp(v->name, "context")) 01112 ast_copy_string(context, v->value, sizeof(context)); 01113 else if (!strcasecmp(v->name, "language")) 01114 ast_copy_string(language, v->value, sizeof(language)); 01115 else if (!strcasecmp(v->name, "extension")) 01116 ast_copy_string(exten, v->value, sizeof(exten)); 01117 else if (!strcasecmp(v->name, "input_device")) 01118 ast_copy_string(indevname, v->value, sizeof(indevname)); 01119 else if (!strcasecmp(v->name, "output_device")) 01120 ast_copy_string(outdevname, v->value, sizeof(outdevname)); 01121 else if (!strcasecmp(v->name, "mohinterpret")) 01122 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 01123 } 01124 ast_config_destroy(cfg); 01125 01126 if (pipe(sndcmd)) { 01127 ast_log(LOG_ERROR, "Unable to create pipe\n"); 01128 return AST_MODULE_LOAD_FAILURE; 01129 } 01130 01131 if (soundcard_init() < 0) { 01132 if (option_verbose > 1) { 01133 ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n"); 01134 ast_verbose(VERBOSE_PREFIX_2 "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n"); 01135 } 01136 return AST_MODULE_LOAD_DECLINE; 01137 } 01138 01139 if (ast_channel_register(&alsa_tech)) { 01140 ast_log(LOG_ERROR, "Unable to register channel class 'Console'\n"); 01141 return AST_MODULE_LOAD_FAILURE; 01142 } 01143 01144 ast_cli_register_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry)); 01145 01146 ast_pthread_create_background(&sthread, NULL, sound_thread, NULL); 01147 #ifdef ALSA_MONITOR 01148 if (alsa_monitor_start()) 01149 ast_log(LOG_ERROR, "Problem starting Monitoring\n"); 01150 #endif 01151 return AST_MODULE_LOAD_SUCCESS; 01152 }
|
|
|
Definition at line 214 of file chan_alsa.c. References alsa, sound::datalen, FRAME_SIZE, chan_alsa_pvt::ocard, sound::silencelen, sounds, and total. Referenced by sound_thread(). 00215 { 00216 short myframe[FRAME_SIZE]; 00217 int total = FRAME_SIZE; 00218 short *frame = NULL; 00219 int amt = 0, res, myoff; 00220 snd_pcm_state_t state; 00221 00222 if (cursound == -1) 00223 return 0; 00224 00225 res = total; 00226 if (sampsent < sounds[cursound].samplen) { 00227 myoff = 0; 00228 while (total) { 00229 amt = total; 00230 if (amt > (sounds[cursound].datalen - offset)) 00231 amt = sounds[cursound].datalen - offset; 00232 memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2); 00233 total -= amt; 00234 offset += amt; 00235 sampsent += amt; 00236 myoff += amt; 00237 if (offset >= sounds[cursound].datalen) 00238 offset = 0; 00239 } 00240 /* Set it up for silence */ 00241 if (sampsent >= sounds[cursound].samplen) 00242 silencelen = sounds[cursound].silencelen; 00243 frame = myframe; 00244 } else { 00245 if (silencelen > 0) { 00246 frame = silence; 00247 silencelen -= res; 00248 } else { 00249 if (sounds[cursound].repeat) { 00250 /* Start over */ 00251 sampsent = 0; 00252 offset = 0; 00253 } else { 00254 cursound = -1; 00255 nosound = 0; 00256 } 00257 return 0; 00258 } 00259 } 00260 00261 if (res == 0 || !frame) 00262 return 0; 00263 00264 #ifdef ALSA_MONITOR 00265 alsa_monitor_write((char *) frame, res * 2); 00266 #endif 00267 state = snd_pcm_state(alsa.ocard); 00268 if (state == SND_PCM_STATE_XRUN) 00269 snd_pcm_prepare(alsa.ocard); 00270 res = snd_pcm_writei(alsa.ocard, frame, res); 00271 if (res > 0) 00272 return 0; 00273 return 0; 00274 }
|
|
|
Definition at line 276 of file chan_alsa.c. References alsa, ast_log(), ast_select(), FRAME_SIZE, chan_alsa_pvt::icard, LOG_ERROR, LOG_WARNING, chan_alsa_pvt::ocard, chan_alsa_pvt::owner, ast_channel_tech::read, and send_sound(). 00277 { 00278 fd_set rfds; 00279 fd_set wfds; 00280 int max, res; 00281 00282 for (;;) { 00283 FD_ZERO(&rfds); 00284 FD_ZERO(&wfds); 00285 max = sndcmd[0]; 00286 FD_SET(sndcmd[0], &rfds); 00287 if (cursound > -1) { 00288 FD_SET(writedev, &wfds); 00289 if (writedev > max) 00290 max = writedev; 00291 } 00292 #ifdef ALSA_MONITOR 00293 if (!alsa.owner) { 00294 FD_SET(readdev, &rfds); 00295 if (readdev > max) 00296 max = readdev; 00297 } 00298 #endif 00299 res = ast_select(max + 1, &rfds, &wfds, NULL, NULL); 00300 if (res < 1) { 00301 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); 00302 continue; 00303 } 00304 #ifdef ALSA_MONITOR 00305 if (FD_ISSET(readdev, &rfds)) { 00306 /* Keep the pipe going with read audio */ 00307 snd_pcm_state_t state; 00308 short buf[FRAME_SIZE]; 00309 int r; 00310 00311 state = snd_pcm_state(alsa.ocard); 00312 if (state == SND_PCM_STATE_XRUN) { 00313 snd_pcm_prepare(alsa.ocard); 00314 } 00315 r = snd_pcm_readi(alsa.icard, buf, FRAME_SIZE); 00316 if (r == -EPIPE) { 00317 #if DEBUG 00318 ast_log(LOG_ERROR, "XRUN read\n"); 00319 #endif 00320 snd_pcm_prepare(alsa.icard); 00321 } else if (r == -ESTRPIPE) { 00322 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00323 snd_pcm_prepare(alsa.icard); 00324 } else if (r < 0) { 00325 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00326 } else 00327 alsa_monitor_read((char *) buf, r * 2); 00328 } 00329 #endif 00330 if (FD_ISSET(sndcmd[0], &rfds)) { 00331 read(sndcmd[0], &cursound, sizeof(cursound)); 00332 silencelen = 0; 00333 offset = 0; 00334 sampsent = 0; 00335 } 00336 if (FD_ISSET(writedev, &wfds)) 00337 if (send_sound()) 00338 ast_log(LOG_WARNING, "Failed to write sound\n"); 00339 } 00340 /* Never reached */ 00341 return NULL; 00342 }
|
|
|
Definition at line 484 of file chan_alsa.c. References alsa, alsa_card_init(), ast_log(), chan_alsa_pvt::icard, LOG_ERROR, chan_alsa_pvt::ocard, and readdev. 00485 { 00486 alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE); 00487 alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK); 00488 00489 if (!alsa.icard || !alsa.ocard) { 00490 ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n"); 00491 return -1; 00492 } 00493 00494 return readdev; 00495 }
|
|
|
Definition at line 1154 of file chan_alsa.c. References alsa, alsa_tech, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, chan_alsa_pvt::icard, chan_alsa_pvt::ocard, chan_alsa_pvt::owner, and sndcmd. 01155 { 01156 ast_channel_unregister(&alsa_tech); 01157 ast_cli_unregister_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry)); 01158 01159 if (alsa.icard) 01160 snd_pcm_close(alsa.icard); 01161 if (alsa.ocard) 01162 snd_pcm_close(alsa.ocard); 01163 if (sndcmd[0] > 0) { 01164 close(sndcmd[0]); 01165 close(sndcmd[1]); 01166 } 01167 if (alsa.owner) 01168 ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD); 01169 if (alsa.owner) 01170 return -1; 01171 return 0; 01172 }
|
|
|
|
Definition at line 198 of file chan_alsa.c. Referenced by alsa_new(), and unload_module(). |
|
|
Initial value: "Usage: console answer\n" " Answers an incoming call on the console (ALSA) channel.\n" Definition at line 967 of file chan_alsa.c. |
|
|
Definition at line 178 of file chan_alsa.c. Referenced by alsa_call(), alsa_hangup(), console_autoanswer(), and load_module(). |
|
|
Initial value: "Usage: console autoanswer [on|off]\n" " Enables or disables autoanswer feature. If used without\n" " argument, displays the current on/off status of autoanswer.\n" " The default value of autoanswer is in 'alsa.conf'.\n" Definition at line 884 of file chan_alsa.c. |
|
|
Definition at line 1064 of file chan_alsa.c. |
|
|
Definition at line 122 of file chan_alsa.c. |
|
|
|
Definition at line 180 of file chan_alsa.c. Referenced by alsa_answer(), alsa_hangup(), alsa_write(), console_answer(), and console_hangup(). |
|
|
Global jitterbuffer configuration - by default, jb is disabled Definition at line 76 of file chan_alsa.c. Referenced by gtalk_load_config(), jingle_load_config(), load_module(), reload_config(), and setup_zap(). |
|
|
Initial value: "Usage: console dial [extension[@context]]\n" " Dials a given extension (and context if specified)\n" Definition at line 1060 of file chan_alsa.c. |
|
|
|
|
Definition at line 82 of file chan_alsa.c. Referenced by __oh323_rtp_create(), __oh323_update_info(), alsa_new(), gtalk_load_config(), gtalk_new(), jingle_load_config(), jingle_new(), load_module(), mgcp_new(), oss_new(), process_zap(), reload_config(), setup_zap(), sip_get_rtp_peer(), sip_new(), sip_show_settings(), skinny_new(), and store_config(). |
|
|
Initial value: "Usage: console hangup\n" " Hangs up any call currently placed on the console.\n" Definition at line 999 of file chan_alsa.c. |
|
|
Definition at line 129 of file chan_alsa.c. |
|
|
Definition at line 109 of file chan_alsa.c. |
|
|
Definition at line 125 of file chan_alsa.c. Referenced by agent_new(), begin_dial(), build_device(), build_gateway(), check_peer_ok(), check_user_full(), check_user_ok(), features_call(), gtalk_new(), jingle_new(), local_call(), mgcp_new(), nbs_new(), oss_new(), read_config(), sip_new(), and skinny_new(). |
|
|
Definition at line 127 of file chan_alsa.c. Referenced by build_device(), check_peer_ok(), check_user_full(), check_user_ok(), create_addr_from_peer(), and sip_alloc(). |
|
|
Definition at line 184 of file chan_alsa.c. Referenced by alsa_write(), and answer_sound(). |
|
|
|
Definition at line 110 of file chan_alsa.c. |
|
|
Definition at line 175 of file chan_alsa.c. Referenced by alsa_card_init(), alsa_new(), and soundcard_init(). |
|
|
Definition at line 181 of file chan_alsa.c. |
|
|
Initial value: "Usage: console send text <message>\n" " Sends a text message for display on the remote terminal.\n" Definition at line 922 of file chan_alsa.c. |
|
|
Definition at line 131 of file chan_alsa.c. Referenced by ast_dsp_process(), and handle_recordfile(). |
|
|
Definition at line 182 of file chan_alsa.c. |
|
|
Definition at line 116 of file chan_alsa.c. |
|
|
Definition at line 117 of file chan_alsa.c. Referenced by ast_record_review(). |
|
|
Definition at line 151 of file chan_alsa.c. Referenced by alsa_call(), alsa_hangup(), alsa_indicate(), answer_sound(), and unload_module(). |
|
|
Definition at line 142 of file chan_alsa.c. Referenced by send_sound(), and sound_thread(). |
|
|
Definition at line 170 of file chan_alsa.c. |
|
|
Definition at line 121 of file chan_alsa.c. |
|
|
Definition at line 176 of file chan_alsa.c. Referenced by alsa_card_init(). |