#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_tone.h"
#include "ring_tone.h"
#include "ring10.h"
#include "answer.h"
Go to the source code of this file.
Data Structures | |
struct | chan_alsa_pvt |
struct | sound |
Defines | |
#define | ALSA_INDEV "default" |
#define | ALSA_OUTDEV "default" |
#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 void | __reg_module (void) |
static void | __unreg_module (void) |
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) |
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_answer_deprecated (int fd, int argc, char *argv[]) |
static int | console_autoanswer (int fd, int argc, char *argv[]) |
static int | console_autoanswer_deprecated (int fd, int argc, char *argv[]) |
static int | console_dial (int fd, int argc, char *argv[]) |
static int | console_dial_deprecated (int fd, int argc, char *argv[]) |
static int | console_hangup (int fd, int argc, char *argv[]) |
static int | console_hangup_deprecated (int fd, int argc, char *argv[]) |
static int | console_sendtext (int fd, int argc, char *argv[]) |
static int | console_sendtext_deprecated (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 ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ALSA Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } |
static struct chan_alsa_pvt | alsa |
static struct ast_channel_tech | alsa_tech |
static ast_mutex_t | alsalock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
static char | answer_usage [] |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static int | autoanswer = 1 |
static const char | autoanswer_usage [] |
static struct ast_cli_entry | cli_alsa [] |
static struct ast_cli_entry | cli_alsa_answer_deprecated |
static struct ast_cli_entry | cli_alsa_autoanswer_deprecated |
static struct ast_cli_entry | cli_alsa_dial_deprecated |
static struct ast_cli_entry | cli_alsa_hangup_deprecated |
static struct ast_cli_entry | cli_alsa_send_text_deprecated |
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 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 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 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 in file chan_alsa.c.
#define ALSA_INDEV "default" |
Definition at line 86 of file chan_alsa.c.
#define ALSA_OUTDEV "default" |
Definition at line 87 of file chan_alsa.c.
#define ALSA_PCM_NEW_HW_PARAMS_API |
Definition at line 47 of file chan_alsa.c.
#define ALSA_PCM_NEW_SW_PARAMS_API |
Definition at line 48 of file chan_alsa.c.
#define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006); |
Definition at line 97 of file chan_alsa.c.
#define DEBUG 0 |
Definition at line 84 of file chan_alsa.c.
#define DESIRED_RATE 8000 |
#define FRAME_SIZE 160 |
Definition at line 91 of file chan_alsa.c.
Referenced by alsa_read(), oss_read(), send_sound(), sound_thread(), and soundcard_writeframe().
#define MAX_BUFFER_SIZE 100 |
Definition at line 171 of file chan_alsa.c.
#define MIN | ( | a, | |||
b | ) | ((a) < (b) ? (a) : (b)) |
Referenced by autoanswer_complete().
#define MIN_SWITCH_TIME 600 |
Definition at line 100 of file chan_alsa.c.
#define PERIOD_FRAMES 80 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1391 of file chan_alsa.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1391 of file chan_alsa.c.
static int alsa_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 560 of file chan_alsa.c.
References alsa, alsalock, answer_sound(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verbose(), and chan_alsa_pvt::icard.
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 }
static int alsa_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 517 of file chan_alsa.c.
References alsa, alsalock, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_verbose(), errno, f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, LOG_WARNING, and chan_alsa_pvt::owner.
00518 { 00519 int res = 3; 00520 struct ast_frame f = { AST_FRAME_CONTROL }; 00521 ast_mutex_lock(&alsalock); 00522 ast_verbose(" << Call placed to '%s' on console >> \n", dest); 00523 if (autoanswer) { 00524 ast_verbose(" << Auto-answered >> \n"); 00525 grab_owner(); 00526 if (alsa.owner) { 00527 f.subclass = AST_CONTROL_ANSWER; 00528 ast_queue_frame(alsa.owner, &f); 00529 ast_mutex_unlock(&alsa.owner->lock); 00530 } 00531 } else { 00532 ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00533 grab_owner(); 00534 if (alsa.owner) { 00535 f.subclass = AST_CONTROL_RINGING; 00536 ast_queue_frame(alsa.owner, &f); 00537 ast_mutex_unlock(&alsa.owner->lock); 00538 } 00539 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00540 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00541 } 00542 } 00543 snd_pcm_prepare(alsa.icard); 00544 snd_pcm_start(alsa.icard); 00545 ast_mutex_unlock(&alsalock); 00546 return 0; 00547 }
static snd_pcm_t* alsa_card_init | ( | char * | dev, | |
snd_pcm_stream_t | stream | |||
) | [static] |
Definition at line 347 of file chan_alsa.c.
References ast_log(), DESIRED_RATE, pollfd::fd, LOG_DEBUG, LOG_ERROR, LOG_WARNING, and PERIOD_FRAMES.
Referenced by soundcard_init().
00348 { 00349 int err; 00350 int direction; 00351 snd_pcm_t *handle = NULL; 00352 snd_pcm_hw_params_t *hwparams = NULL; 00353 snd_pcm_sw_params_t *swparams = NULL; 00354 struct pollfd pfd; 00355 snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4; 00356 /* int period_bytes = 0; */ 00357 snd_pcm_uframes_t buffer_size = 0; 00358 00359 unsigned int rate = DESIRED_RATE; 00360 #if 0 00361 unsigned int per_min = 1; 00362 #endif 00363 /* unsigned int per_max = 8; */ 00364 snd_pcm_uframes_t start_threshold, stop_threshold; 00365 00366 err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK); 00367 if (err < 0) { 00368 ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err)); 00369 return NULL; 00370 } else 00371 ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write"); 00372 00373 hwparams = alloca(snd_pcm_hw_params_sizeof()); 00374 memset(hwparams, 0, snd_pcm_hw_params_sizeof()); 00375 snd_pcm_hw_params_any(handle, hwparams); 00376 00377 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); 00378 if (err < 0) 00379 ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err)); 00380 00381 err = snd_pcm_hw_params_set_format(handle, hwparams, format); 00382 if (err < 0) 00383 ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err)); 00384 00385 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1); 00386 if (err < 0) 00387 ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err)); 00388 00389 direction = 0; 00390 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction); 00391 if (rate != DESIRED_RATE) 00392 ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate); 00393 00394 direction = 0; 00395 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction); 00396 if (err < 0) 00397 ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err)); 00398 else 00399 ast_log(LOG_DEBUG, "Period size is %d\n", err); 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 ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err); 00407 00408 #if 0 00409 direction = 0; 00410 err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction); 00411 if (err < 0) 00412 ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err)); 00413 00414 err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0); 00415 if (err < 0) 00416 ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err)); 00417 #endif 00418 00419 err = snd_pcm_hw_params(handle, hwparams); 00420 if (err < 0) 00421 ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err)); 00422 00423 swparams = alloca(snd_pcm_sw_params_sizeof()); 00424 memset(swparams, 0, snd_pcm_sw_params_sizeof()); 00425 snd_pcm_sw_params_current(handle, swparams); 00426 00427 #if 1 00428 if (stream == SND_PCM_STREAM_PLAYBACK) 00429 start_threshold = period_size; 00430 else 00431 start_threshold = 1; 00432 00433 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); 00434 if (err < 0) 00435 ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err)); 00436 #endif 00437 00438 #if 1 00439 if (stream == SND_PCM_STREAM_PLAYBACK) 00440 stop_threshold = buffer_size; 00441 else 00442 stop_threshold = buffer_size; 00443 00444 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); 00445 if (err < 0) 00446 ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err)); 00447 #endif 00448 #if 0 00449 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, PERIOD_FRAMES); 00450 if (err < 0) 00451 ast_log(LOG_ERROR, "Unable to set xfer alignment: %s\n", snd_strerror(err)); 00452 #endif 00453 00454 #if 0 00455 err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold); 00456 if (err < 0) 00457 ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err)); 00458 #endif 00459 err = snd_pcm_sw_params(handle, swparams); 00460 if (err < 0) 00461 ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err)); 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 if (err != 1) 00467 ast_log(LOG_DEBUG, "Can't handle more than one device\n"); 00468 00469 snd_pcm_poll_descriptors(handle, &pfd, err); 00470 ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd); 00471 00472 if (stream == SND_PCM_STREAM_CAPTURE) 00473 readdev = pfd.fd; 00474 else 00475 writedev = pfd.fd; 00476 00477 return handle; 00478 }
static int alsa_digit | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 493 of file chan_alsa.c.
References alsalock, ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().
00494 { 00495 ast_mutex_lock(&alsalock); 00496 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00497 digit, duration); 00498 ast_mutex_unlock(&alsalock); 00499 return 0; 00500 }
static int alsa_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 741 of file chan_alsa.c.
References alsalock, ast_mutex_lock(), ast_mutex_unlock(), chan_alsa_pvt::owner, and ast_channel::tech_pvt.
00742 { 00743 struct chan_alsa_pvt *p = newchan->tech_pvt; 00744 ast_mutex_lock(&alsalock); 00745 p->owner = newchan; 00746 ast_mutex_unlock(&alsalock); 00747 return 0; 00748 }
static int alsa_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 573 of file chan_alsa.c.
References alsa, alsalock, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, chan_alsa_pvt::icard, LOG_WARNING, chan_alsa_pvt::owner, and ast_channel::tech_pvt.
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_module_unref(ast_module_info->self); 00582 if (hookstate) { 00583 hookstate = 0; 00584 if (!autoanswer) { 00585 /* Congestion noise */ 00586 res = 2; 00587 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00588 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00589 } 00590 } 00591 } 00592 snd_pcm_drop(alsa.icard); 00593 ast_mutex_unlock(&alsalock); 00594 return 0; 00595 }
static int alsa_indicate | ( | struct ast_channel * | chan, | |
int | cond, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 750 of file chan_alsa.c.
References alsalock, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_WARNING, and ast_channel::name.
00751 { 00752 int res = 0; 00753 00754 ast_mutex_lock(&alsalock); 00755 00756 switch (cond) { 00757 case AST_CONTROL_BUSY: 00758 res = 1; 00759 break; 00760 case AST_CONTROL_CONGESTION: 00761 res = 2; 00762 break; 00763 case AST_CONTROL_RINGING: 00764 case AST_CONTROL_PROGRESS: 00765 break; 00766 case -1: 00767 res = -1; 00768 break; 00769 case AST_CONTROL_VIDUPDATE: 00770 res = -1; 00771 break; 00772 case AST_CONTROL_HOLD: 00773 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00774 ast_moh_start(chan, data, mohinterpret); 00775 break; 00776 case AST_CONTROL_UNHOLD: 00777 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00778 ast_moh_stop(chan); 00779 break; 00780 case AST_CONTROL_SRCUPDATE: 00781 break; 00782 default: 00783 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name); 00784 res = -1; 00785 } 00786 00787 if (res > -1) { 00788 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00789 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00790 } 00791 } 00792 00793 ast_mutex_unlock(&alsalock); 00794 00795 return res; 00796 }
static struct ast_channel* alsa_new | ( | struct chan_alsa_pvt * | p, | |
int | state | |||
) | [static] |
Definition at line 798 of file chan_alsa.c.
References alsa_tech, ast_channel_alloc(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, ast_string_field_set, ast_strlen_zero(), ast_channel::context, chan_alsa_pvt::context, ast_channel::exten, chan_alsa_pvt::exten, ast_channel::fds, global_jbconf, LOG_WARNING, ast_channel::nativeformats, chan_alsa_pvt::owner, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by alsa_request(), console_dial(), and console_dial_deprecated().
00799 { 00800 struct ast_channel *tmp = NULL; 00801 00802 if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "ALSA/%s", indevname))) 00803 return NULL; 00804 00805 tmp->tech = &alsa_tech; 00806 tmp->fds[0] = readdev; 00807 tmp->nativeformats = AST_FORMAT_SLINEAR; 00808 tmp->readformat = AST_FORMAT_SLINEAR; 00809 tmp->writeformat = AST_FORMAT_SLINEAR; 00810 tmp->tech_pvt = p; 00811 if (!ast_strlen_zero(p->context)) 00812 ast_copy_string(tmp->context, p->context, sizeof(tmp->context)); 00813 if (!ast_strlen_zero(p->exten)) 00814 ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten)); 00815 if (!ast_strlen_zero(language)) 00816 ast_string_field_set(tmp, language, language); 00817 p->owner = tmp; 00818 ast_module_ref(ast_module_info->self); 00819 ast_jb_configure(tmp, &global_jbconf); 00820 if (state != AST_STATE_DOWN) { 00821 if (ast_pbx_start(tmp)) { 00822 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00823 ast_hangup(tmp); 00824 tmp = NULL; 00825 } 00826 } 00827 00828 return tmp; 00829 }
static struct ast_frame * alsa_read | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 666 of file chan_alsa.c.
References ast_channel::_state, alsa, alsalock, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, f, FRAME_SIZE, chan_alsa_pvt::icard, and LOG_ERROR.
00667 { 00668 static struct ast_frame f; 00669 static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2]; 00670 short *buf; 00671 static int readpos = 0; 00672 static int left = FRAME_SIZE; 00673 snd_pcm_state_t state; 00674 int r = 0; 00675 int off = 0; 00676 00677 ast_mutex_lock(&alsalock); 00678 /* Acknowledge any pending cmd */ 00679 f.frametype = AST_FRAME_NULL; 00680 f.subclass = 0; 00681 f.samples = 0; 00682 f.datalen = 0; 00683 f.data = NULL; 00684 f.offset = 0; 00685 f.src = "Console"; 00686 f.mallocd = 0; 00687 f.delivery.tv_sec = 0; 00688 f.delivery.tv_usec = 0; 00689 00690 state = snd_pcm_state(alsa.icard); 00691 if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) { 00692 snd_pcm_prepare(alsa.icard); 00693 } 00694 00695 buf = __buf + AST_FRIENDLY_OFFSET / 2; 00696 00697 r = snd_pcm_readi(alsa.icard, buf + readpos, left); 00698 if (r == -EPIPE) { 00699 #if DEBUG 00700 ast_log(LOG_ERROR, "XRUN read\n"); 00701 #endif 00702 snd_pcm_prepare(alsa.icard); 00703 } else if (r == -ESTRPIPE) { 00704 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00705 snd_pcm_prepare(alsa.icard); 00706 } else if (r < 0) { 00707 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00708 } else if (r >= 0) { 00709 off -= r; 00710 } 00711 /* Update positions */ 00712 readpos += r; 00713 left -= r; 00714 00715 if (readpos >= FRAME_SIZE) { 00716 /* A real frame */ 00717 readpos = 0; 00718 left = FRAME_SIZE; 00719 if (chan->_state != AST_STATE_UP) { 00720 /* Don't transmit unless it's up */ 00721 ast_mutex_unlock(&alsalock); 00722 return &f; 00723 } 00724 f.frametype = AST_FRAME_VOICE; 00725 f.subclass = AST_FORMAT_SLINEAR; 00726 f.samples = FRAME_SIZE; 00727 f.datalen = FRAME_SIZE * 2; 00728 f.data = buf; 00729 f.offset = AST_FRIENDLY_OFFSET; 00730 f.src = "Console"; 00731 f.mallocd = 0; 00732 #ifdef ALSA_MONITOR 00733 alsa_monitor_read((char *) buf, FRAME_SIZE * 2); 00734 #endif 00735 00736 } 00737 ast_mutex_unlock(&alsalock); 00738 return &f; 00739 }
static struct ast_channel * alsa_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 831 of file chan_alsa.c.
References alsa, alsa_new(), alsalock, 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.
00832 { 00833 int oldformat = format; 00834 struct ast_channel *tmp = NULL; 00835 00836 format &= AST_FORMAT_SLINEAR; 00837 if (!format) { 00838 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat); 00839 return NULL; 00840 } 00841 00842 ast_mutex_lock(&alsalock); 00843 00844 if (alsa.owner) { 00845 ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n"); 00846 *cause = AST_CAUSE_BUSY; 00847 } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN))) 00848 ast_log(LOG_WARNING, "Unable to create new ALSA channel\n"); 00849 00850 ast_mutex_unlock(&alsalock); 00851 00852 return tmp; 00853 }
static int alsa_text | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 502 of file chan_alsa.c.
References alsalock, ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().
00503 { 00504 ast_mutex_lock(&alsalock); 00505 ast_verbose(" << Console Received text %s >> \n", text); 00506 ast_mutex_unlock(&alsalock); 00507 return 0; 00508 }
static int alsa_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 597 of file chan_alsa.c.
References alsa, alsalock, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, len(), LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::ocard.
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 while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) { 00635 usleep(1); 00636 } 00637 if (res == -EPIPE) { 00638 #if DEBUG 00639 ast_log(LOG_DEBUG, "XRUN write\n"); 00640 #endif 00641 snd_pcm_prepare(alsa.ocard); 00642 while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) { 00643 usleep(1); 00644 } 00645 if (res != len / 2) { 00646 ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res)); 00647 res = -1; 00648 } else if (res < 0) { 00649 ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res)); 00650 res = -1; 00651 } 00652 } else { 00653 if (res == -ESTRPIPE) 00654 ast_log(LOG_ERROR, "You've got some big problems\n"); 00655 else if (res < 0) 00656 ast_log(LOG_NOTICE, "Error %d on write\n", res); 00657 } 00658 } 00659 ast_mutex_unlock(&alsalock); 00660 if (res > 0) 00661 res = 0; 00662 return res; 00663 }
static void answer_sound | ( | void | ) | [static] |
Definition at line 549 of file chan_alsa.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by alsa_answer(), console_answer(), and console_answer_deprecated().
00550 { 00551 int res; 00552 00553 nosound = 1; 00554 res = 4; 00555 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00556 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00557 } 00558 }
static char* autoanswer_complete | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 900 of file chan_alsa.c.
References ast_strdup, ast_strlen_zero(), and MIN.
00901 { 00902 #ifndef MIN 00903 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00904 #endif 00905 switch (state) { 00906 case 0: 00907 if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2))) 00908 return ast_strdup("on"); 00909 case 1: 00910 if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3))) 00911 return ast_strdup("off"); 00912 default: 00913 return NULL; 00914 } 00915 return NULL; 00916 }
static int console_answer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 956 of file chan_alsa.c.
References alsa, alsalock, answer_sound(), ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00957 { 00958 int res = RESULT_SUCCESS; 00959 00960 if (argc != 2) 00961 return RESULT_SHOWUSAGE; 00962 00963 ast_mutex_lock(&alsalock); 00964 00965 if (!alsa.owner) { 00966 ast_cli(fd, "No one is calling us\n"); 00967 res = RESULT_FAILURE; 00968 } else { 00969 hookstate = 1; 00970 cursound = -1; 00971 grab_owner(); 00972 if (alsa.owner) { 00973 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00974 ast_queue_frame(alsa.owner, &f); 00975 ast_mutex_unlock(&alsa.owner->lock); 00976 } 00977 answer_sound(); 00978 } 00979 00980 snd_pcm_prepare(alsa.icard); 00981 snd_pcm_start(alsa.icard); 00982 00983 ast_mutex_unlock(&alsalock); 00984 00985 return RESULT_SUCCESS; 00986 }
static int console_answer_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 924 of file chan_alsa.c.
References alsa, alsalock, answer_sound(), ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00925 { 00926 int res = RESULT_SUCCESS; 00927 00928 if (argc != 1) 00929 return RESULT_SHOWUSAGE; 00930 00931 ast_mutex_lock(&alsalock); 00932 00933 if (!alsa.owner) { 00934 ast_cli(fd, "No one is calling us\n"); 00935 res = RESULT_FAILURE; 00936 } else { 00937 hookstate = 1; 00938 cursound = -1; 00939 grab_owner(); 00940 if (alsa.owner) { 00941 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00942 ast_queue_frame(alsa.owner, &f); 00943 ast_mutex_unlock(&alsa.owner->lock); 00944 } 00945 answer_sound(); 00946 } 00947 00948 snd_pcm_prepare(alsa.icard); 00949 snd_pcm_start(alsa.icard); 00950 00951 ast_mutex_unlock(&alsalock); 00952 00953 return RESULT_SUCCESS; 00954 }
static int console_autoanswer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 880 of file chan_alsa.c.
References alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00881 { 00882 int res = RESULT_SUCCESS;; 00883 if ((argc != 2) && (argc != 3)) 00884 return RESULT_SHOWUSAGE; 00885 ast_mutex_lock(&alsalock); 00886 if (argc == 2) { 00887 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off"); 00888 } else { 00889 if (!strcasecmp(argv[2], "on")) 00890 autoanswer = -1; 00891 else if (!strcasecmp(argv[2], "off")) 00892 autoanswer = 0; 00893 else 00894 res = RESULT_SHOWUSAGE; 00895 } 00896 ast_mutex_unlock(&alsalock); 00897 return res; 00898 }
static int console_autoanswer_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 855 of file chan_alsa.c.
References alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00856 { 00857 int res = RESULT_SUCCESS; 00858 00859 if ((argc != 1) && (argc != 2)) 00860 return RESULT_SHOWUSAGE; 00861 00862 ast_mutex_lock(&alsalock); 00863 00864 if (argc == 1) { 00865 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off"); 00866 } else { 00867 if (!strcasecmp(argv[1], "on")) 00868 autoanswer = -1; 00869 else if (!strcasecmp(argv[1], "off")) 00870 autoanswer = 0; 00871 else 00872 res = RESULT_SHOWUSAGE; 00873 } 00874 00875 ast_mutex_unlock(&alsalock); 00876 00877 return res; 00878 }
static int console_dial | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1195 of file chan_alsa.c.
References alsa, alsa_new(), alsalock, ast_cli(), ast_copy_string(), 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, f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01196 { 01197 char tmp[256], *tmp2; 01198 char *mye, *myc; 01199 char *d; 01200 int res = RESULT_SUCCESS; 01201 01202 if ((argc != 2) && (argc != 3)) 01203 return RESULT_SHOWUSAGE; 01204 01205 ast_mutex_lock(&alsalock); 01206 01207 if (alsa.owner) { 01208 if (argc == 3) { 01209 d = argv[2]; 01210 grab_owner(); 01211 if (alsa.owner) { 01212 struct ast_frame f = { AST_FRAME_DTMF }; 01213 while (*d) { 01214 f.subclass = *d; 01215 ast_queue_frame(alsa.owner, &f); 01216 d++; 01217 } 01218 ast_mutex_unlock(&alsa.owner->lock); 01219 } 01220 } else { 01221 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n"); 01222 res = RESULT_FAILURE; 01223 } 01224 } else { 01225 mye = exten; 01226 myc = context; 01227 if (argc == 3) { 01228 char *stringp = NULL; 01229 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01230 stringp = tmp; 01231 strsep(&stringp, "@"); 01232 tmp2 = strsep(&stringp, "@"); 01233 if (!ast_strlen_zero(tmp)) 01234 mye = tmp; 01235 if (!ast_strlen_zero(tmp2)) 01236 myc = tmp2; 01237 } 01238 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01239 ast_copy_string(alsa.exten, mye, sizeof(alsa.exten)); 01240 ast_copy_string(alsa.context, myc, sizeof(alsa.context)); 01241 hookstate = 1; 01242 alsa_new(&alsa, AST_STATE_RINGING); 01243 } else 01244 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc); 01245 } 01246 01247 ast_mutex_unlock(&alsalock); 01248 01249 return res; 01250 }
static int console_dial_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1138 of file chan_alsa.c.
References alsa, alsa_new(), alsalock, ast_cli(), ast_copy_string(), 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, f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01139 { 01140 char tmp[256], *tmp2; 01141 char *mye, *myc; 01142 char *d; 01143 int res = RESULT_SUCCESS; 01144 01145 if ((argc != 1) && (argc != 2)) 01146 return RESULT_SHOWUSAGE; 01147 01148 ast_mutex_lock(&alsalock); 01149 01150 if (alsa.owner) { 01151 if (argc == 2) { 01152 d = argv[1]; 01153 grab_owner(); 01154 if (alsa.owner) { 01155 struct ast_frame f = { AST_FRAME_DTMF }; 01156 while (*d) { 01157 f.subclass = *d; 01158 ast_queue_frame(alsa.owner, &f); 01159 d++; 01160 } 01161 ast_mutex_unlock(&alsa.owner->lock); 01162 } 01163 } else { 01164 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n"); 01165 res = RESULT_FAILURE; 01166 } 01167 } else { 01168 mye = exten; 01169 myc = context; 01170 if (argc == 2) { 01171 char *stringp = NULL; 01172 ast_copy_string(tmp, argv[1], sizeof(tmp)); 01173 stringp = tmp; 01174 strsep(&stringp, "@"); 01175 tmp2 = strsep(&stringp, "@"); 01176 if (!ast_strlen_zero(tmp)) 01177 mye = tmp; 01178 if (!ast_strlen_zero(tmp2)) 01179 myc = tmp2; 01180 } 01181 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01182 ast_copy_string(alsa.exten, mye, sizeof(alsa.exten)); 01183 ast_copy_string(alsa.context, myc, sizeof(alsa.context)); 01184 hookstate = 1; 01185 alsa_new(&alsa, AST_STATE_RINGING); 01186 } else 01187 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc); 01188 } 01189 01190 ast_mutex_unlock(&alsalock); 01191 01192 return res; 01193 }
static int console_hangup | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1106 of file chan_alsa.c.
References alsa, alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01107 { 01108 int res = RESULT_SUCCESS; 01109 01110 if (argc != 2) 01111 return RESULT_SHOWUSAGE; 01112 01113 cursound = -1; 01114 01115 ast_mutex_lock(&alsalock); 01116 01117 if (!alsa.owner && !hookstate) { 01118 ast_cli(fd, "No call to hangup up\n"); 01119 res = RESULT_FAILURE; 01120 } else { 01121 hookstate = 0; 01122 grab_owner(); 01123 if (alsa.owner) { 01124 ast_queue_hangup(alsa.owner); 01125 ast_mutex_unlock(&alsa.owner->lock); 01126 } 01127 } 01128 01129 ast_mutex_unlock(&alsalock); 01130 01131 return res; 01132 }
static int console_hangup_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1078 of file chan_alsa.c.
References alsa, alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01079 { 01080 int res = RESULT_SUCCESS; 01081 01082 if (argc != 1) 01083 return RESULT_SHOWUSAGE; 01084 01085 cursound = -1; 01086 01087 ast_mutex_lock(&alsalock); 01088 01089 if (!alsa.owner && !hookstate) { 01090 ast_cli(fd, "No call to hangup up\n"); 01091 res = RESULT_FAILURE; 01092 } else { 01093 hookstate = 0; 01094 grab_owner(); 01095 if (alsa.owner) { 01096 ast_queue_hangup(alsa.owner); 01097 ast_mutex_unlock(&alsa.owner->lock); 01098 } 01099 } 01100 01101 ast_mutex_unlock(&alsalock); 01102 01103 return res; 01104 }
static int console_sendtext | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1033 of file chan_alsa.c.
References alsa, alsalock, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01034 { 01035 int tmparg = 3; 01036 int res = RESULT_SUCCESS; 01037 01038 if (argc < 3) 01039 return RESULT_SHOWUSAGE; 01040 01041 ast_mutex_lock(&alsalock); 01042 01043 if (!alsa.owner) { 01044 ast_cli(fd, "No one is calling us\n"); 01045 res = RESULT_FAILURE; 01046 } else { 01047 struct ast_frame f = { AST_FRAME_TEXT, 0 }; 01048 char text2send[256] = ""; 01049 text2send[0] = '\0'; 01050 while (tmparg < argc) { 01051 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1); 01052 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1); 01053 } 01054 text2send[strlen(text2send) - 1] = '\n'; 01055 f.data = text2send; 01056 f.datalen = strlen(text2send) + 1; 01057 grab_owner(); 01058 if (alsa.owner) { 01059 ast_queue_frame(alsa.owner, &f); 01060 f.frametype = AST_FRAME_CONTROL; 01061 f.subclass = AST_CONTROL_ANSWER; 01062 f.data = NULL; 01063 f.datalen = 0; 01064 ast_queue_frame(alsa.owner, &f); 01065 ast_mutex_unlock(&alsa.owner->lock); 01066 } 01067 } 01068 01069 ast_mutex_unlock(&alsalock); 01070 01071 return res; 01072 }
static int console_sendtext_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 992 of file chan_alsa.c.
References alsa, alsalock, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00993 { 00994 int tmparg = 2; 00995 int res = RESULT_SUCCESS; 00996 00997 if (argc < 2) 00998 return RESULT_SHOWUSAGE; 00999 01000 ast_mutex_lock(&alsalock); 01001 01002 if (!alsa.owner) { 01003 ast_cli(fd, "No one is calling us\n"); 01004 res = RESULT_FAILURE; 01005 } else { 01006 struct ast_frame f = { AST_FRAME_TEXT, 0 }; 01007 char text2send[256] = ""; 01008 text2send[0] = '\0'; 01009 while (tmparg < argc) { 01010 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1); 01011 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1); 01012 } 01013 text2send[strlen(text2send) - 1] = '\n'; 01014 f.data = text2send; 01015 f.datalen = strlen(text2send) + 1; 01016 grab_owner(); 01017 if (alsa.owner) { 01018 ast_queue_frame(alsa.owner, &f); 01019 f.frametype = AST_FRAME_CONTROL; 01020 f.subclass = AST_CONTROL_ANSWER; 01021 f.data = NULL; 01022 f.datalen = 0; 01023 ast_queue_frame(alsa.owner, &f); 01024 ast_mutex_unlock(&alsa.owner->lock); 01025 } 01026 } 01027 01028 ast_mutex_unlock(&alsalock); 01029 01030 return res; 01031 }
static void grab_owner | ( | void | ) | [static] |
Definition at line 510 of file chan_alsa.c.
References alsa, alsalock, ast_mutex_trylock(), DEADLOCK_AVOIDANCE, ast_channel::lock, and chan_alsa_pvt::owner.
Referenced by alsa_call(), console_answer(), console_answer_deprecated(), console_dial(), console_dial_deprecated(), console_hangup(), console_hangup_deprecated(), console_sendtext(), and console_sendtext_deprecated().
00511 { 00512 while (alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) { 00513 DEADLOCK_AVOIDANCE(&alsalock); 00514 } 00515 }
static int load_module | ( | void | ) | [static] |
Definition at line 1303 of file chan_alsa.c.
References alsa_tech, ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_copy_string(), ast_jb_read_conf(), ast_log(), ast_pthread_create_background, ast_true(), ast_variable_browse(), ast_verbose(), cli_alsa, default_jbconf, global_jbconf, LOG_ERROR, ast_variable::name, ast_variable::next, option_verbose, sound_thread(), soundcard_init(), ast_variable::value, and VERBOSE_PREFIX_2.
01304 { 01305 int res; 01306 struct ast_config *cfg; 01307 struct ast_variable *v; 01308 01309 /* Copy the default jb config over global_jbconf */ 01310 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01311 01312 strcpy(mohinterpret, "default"); 01313 01314 if ((cfg = ast_config_load(config))) { 01315 v = ast_variable_browse(cfg, "general"); 01316 for (; v; v = v->next) { 01317 /* handle jb conf */ 01318 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 01319 continue; 01320 01321 if (!strcasecmp(v->name, "autoanswer")) 01322 autoanswer = ast_true(v->value); 01323 else if (!strcasecmp(v->name, "silencesuppression")) 01324 silencesuppression = ast_true(v->value); 01325 else if (!strcasecmp(v->name, "silencethreshold")) 01326 silencethreshold = atoi(v->value); 01327 else if (!strcasecmp(v->name, "context")) 01328 ast_copy_string(context, v->value, sizeof(context)); 01329 else if (!strcasecmp(v->name, "language")) 01330 ast_copy_string(language, v->value, sizeof(language)); 01331 else if (!strcasecmp(v->name, "extension")) 01332 ast_copy_string(exten, v->value, sizeof(exten)); 01333 else if (!strcasecmp(v->name, "input_device")) 01334 ast_copy_string(indevname, v->value, sizeof(indevname)); 01335 else if (!strcasecmp(v->name, "output_device")) 01336 ast_copy_string(outdevname, v->value, sizeof(outdevname)); 01337 else if (!strcasecmp(v->name, "mohinterpret")) 01338 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 01339 } 01340 ast_config_destroy(cfg); 01341 } 01342 res = pipe(sndcmd); 01343 if (res) { 01344 ast_log(LOG_ERROR, "Unable to create pipe\n"); 01345 return -1; 01346 } 01347 res = soundcard_init(); 01348 if (res < 0) { 01349 if (option_verbose > 1) { 01350 ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n"); 01351 ast_verbose(VERBOSE_PREFIX_2 "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n"); 01352 } 01353 return 0; 01354 } 01355 01356 res = ast_channel_register(&alsa_tech); 01357 if (res < 0) { 01358 ast_log(LOG_ERROR, "Unable to register channel class 'Console'\n"); 01359 return -1; 01360 } 01361 ast_cli_register_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry)); 01362 01363 ast_pthread_create_background(&sthread, NULL, sound_thread, NULL); 01364 #ifdef ALSA_MONITOR 01365 if (alsa_monitor_start()) 01366 ast_log(LOG_ERROR, "Problem starting Monitoring\n"); 01367 #endif 01368 return 0; 01369 }
static int send_sound | ( | void | ) | [static] |
Definition at line 213 of file chan_alsa.c.
References alsa, sound::datalen, FRAME_SIZE, chan_alsa_pvt::ocard, sound::silencelen, sounds, and total.
Referenced by sound_thread().
00214 { 00215 short myframe[FRAME_SIZE]; 00216 int total = FRAME_SIZE; 00217 short *frame = NULL; 00218 int amt = 0, res, myoff; 00219 snd_pcm_state_t state; 00220 00221 if (cursound == -1) 00222 return 0; 00223 00224 res = total; 00225 if (sampsent < sounds[cursound].samplen) { 00226 myoff = 0; 00227 while (total) { 00228 amt = total; 00229 if (amt > (sounds[cursound].datalen - offset)) 00230 amt = sounds[cursound].datalen - offset; 00231 memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2); 00232 total -= amt; 00233 offset += amt; 00234 sampsent += amt; 00235 myoff += amt; 00236 if (offset >= sounds[cursound].datalen) 00237 offset = 0; 00238 } 00239 /* Set it up for silence */ 00240 if (sampsent >= sounds[cursound].samplen) 00241 silencelen = sounds[cursound].silencelen; 00242 frame = myframe; 00243 } else { 00244 if (silencelen > 0) { 00245 frame = silence; 00246 silencelen -= res; 00247 } else { 00248 if (sounds[cursound].repeat) { 00249 /* Start over */ 00250 sampsent = 0; 00251 offset = 0; 00252 } else { 00253 cursound = -1; 00254 nosound = 0; 00255 } 00256 return 0; 00257 } 00258 } 00259 00260 if (res == 0 || !frame) 00261 return 0; 00262 00263 #ifdef ALSA_MONITOR 00264 alsa_monitor_write((char *) frame, res * 2); 00265 #endif 00266 state = snd_pcm_state(alsa.ocard); 00267 if (state == SND_PCM_STATE_XRUN) 00268 snd_pcm_prepare(alsa.ocard); 00269 while ((res = snd_pcm_writei(alsa.ocard, frame, res)) == -EAGAIN) { 00270 usleep(1); 00271 } 00272 if (res > 0) 00273 return 0; 00274 return 0; 00275 }
static void* sound_thread | ( | void * | unused | ) | [static] |
Definition at line 277 of file chan_alsa.c.
References alsa, ast_log(), ast_select(), errno, 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().
Referenced by load_module().
00278 { 00279 fd_set rfds; 00280 fd_set wfds; 00281 int max, res; 00282 00283 for (;;) { 00284 FD_ZERO(&rfds); 00285 FD_ZERO(&wfds); 00286 max = sndcmd[0]; 00287 FD_SET(sndcmd[0], &rfds); 00288 if (cursound > -1) { 00289 FD_SET(writedev, &wfds); 00290 if (writedev > max) 00291 max = writedev; 00292 } 00293 #ifdef ALSA_MONITOR 00294 if (!alsa.owner) { 00295 FD_SET(readdev, &rfds); 00296 if (readdev > max) 00297 max = readdev; 00298 } 00299 #endif 00300 res = ast_select(max + 1, &rfds, &wfds, NULL, NULL); 00301 if (res < 1) { 00302 ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno)); 00303 continue; 00304 } 00305 #ifdef ALSA_MONITOR 00306 if (FD_ISSET(readdev, &rfds)) { 00307 /* Keep the pipe going with read audio */ 00308 snd_pcm_state_t state; 00309 short buf[FRAME_SIZE]; 00310 int r; 00311 00312 state = snd_pcm_state(alsa.ocard); 00313 if (state == SND_PCM_STATE_XRUN) { 00314 snd_pcm_prepare(alsa.ocard); 00315 } 00316 r = snd_pcm_readi(alsa.icard, buf, FRAME_SIZE); 00317 if (r == -EPIPE) { 00318 #if DEBUG 00319 ast_log(LOG_ERROR, "XRUN read\n"); 00320 #endif 00321 snd_pcm_prepare(alsa.icard); 00322 } else if (r == -ESTRPIPE) { 00323 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00324 snd_pcm_prepare(alsa.icard); 00325 } else if (r < 0) { 00326 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00327 } else 00328 alsa_monitor_read((char *) buf, r * 2); 00329 } 00330 #endif 00331 if (FD_ISSET(sndcmd[0], &rfds)) { 00332 if (read(sndcmd[0], &cursound, sizeof(cursound)) < 0) { 00333 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 00334 } 00335 silencelen = 0; 00336 offset = 0; 00337 sampsent = 0; 00338 } 00339 if (FD_ISSET(writedev, &wfds)) 00340 if (send_sound()) 00341 ast_log(LOG_WARNING, "Failed to write sound\n"); 00342 } 00343 /* Never reached */ 00344 return NULL; 00345 }
static int soundcard_init | ( | void | ) | [static] |
Definition at line 480 of file chan_alsa.c.
References alsa, alsa_card_init(), ast_log(), chan_alsa_pvt::icard, LOG_ERROR, and chan_alsa_pvt::ocard.
Referenced by load_module().
00481 { 00482 alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE); 00483 alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK); 00484 00485 if (!alsa.icard || !alsa.ocard) { 00486 ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n"); 00487 return -1; 00488 } 00489 00490 return readdev; 00491 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1371 of file chan_alsa.c.
References alsa, alsa_tech, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_alsa, chan_alsa_pvt::icard, chan_alsa_pvt::ocard, and chan_alsa_pvt::owner.
01372 { 01373 ast_channel_unregister(&alsa_tech); 01374 ast_cli_unregister_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry)); 01375 01376 if (alsa.icard) 01377 snd_pcm_close(alsa.icard); 01378 if (alsa.ocard) 01379 snd_pcm_close(alsa.ocard); 01380 if (sndcmd[0] > 0) { 01381 close(sndcmd[0]); 01382 close(sndcmd[1]); 01383 } 01384 if (alsa.owner) 01385 ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD); 01386 if (alsa.owner) 01387 return -1; 01388 return 0; 01389 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ALSA Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 1391 of file chan_alsa.c.
struct chan_alsa_pvt alsa [static] |
Referenced by alsa_answer(), alsa_call(), alsa_hangup(), alsa_read(), alsa_request(), alsa_write(), console_answer(), console_answer_deprecated(), console_dial(), console_dial_deprecated(), console_hangup(), console_hangup_deprecated(), console_sendtext(), console_sendtext_deprecated(), grab_owner(), send_sound(), sound_thread(), soundcard_init(), and unload_module().
struct ast_channel_tech alsa_tech [static] |
Definition at line 197 of file chan_alsa.c.
Referenced by alsa_new(), load_module(), and unload_module().
ast_mutex_t alsalock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
Definition at line 118 of file chan_alsa.c.
Referenced by alsa_answer(), alsa_call(), alsa_digit(), alsa_fixup(), alsa_hangup(), alsa_indicate(), alsa_read(), alsa_request(), alsa_text(), alsa_write(), console_answer(), console_answer_deprecated(), console_autoanswer(), console_autoanswer_deprecated(), console_dial(), console_dial_deprecated(), console_hangup(), console_hangup_deprecated(), console_sendtext(), console_sendtext_deprecated(), and grab_owner().
char answer_usage[] [static] |
Initial value:
"Usage: console answer\n" " Answers an incoming call on the console (ALSA) channel.\n"
Definition at line 1074 of file chan_alsa.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1391 of file chan_alsa.c.
int autoanswer = 1 [static] |
Definition at line 177 of file chan_alsa.c.
const char autoanswer_usage[] [static] |
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 918 of file chan_alsa.c.
struct ast_cli_entry cli_alsa[] [static] |
struct ast_cli_entry cli_alsa_answer_deprecated [static] |
Initial value:
{ { "answer", NULL }, console_answer_deprecated, NULL, NULL }
Definition at line 1256 of file chan_alsa.c.
struct ast_cli_entry cli_alsa_autoanswer_deprecated [static] |
Initial value:
{ { "autoanswer", NULL }, console_autoanswer_deprecated, NULL, NULL, autoanswer_complete }
Definition at line 1276 of file chan_alsa.c.
struct ast_cli_entry cli_alsa_dial_deprecated [static] |
Initial value:
{ { "dial", NULL }, console_dial_deprecated, NULL, NULL }
Definition at line 1266 of file chan_alsa.c.
struct ast_cli_entry cli_alsa_hangup_deprecated [static] |
Initial value:
{ { "hangup", NULL }, console_hangup_deprecated, NULL, NULL }
Definition at line 1261 of file chan_alsa.c.
struct ast_cli_entry cli_alsa_send_text_deprecated [static] |
Initial value:
{ { "send", "text", NULL }, console_sendtext_deprecated, NULL, NULL }
Definition at line 1271 of file chan_alsa.c.
const char config[] = "alsa.conf" [static] |
Definition at line 121 of file chan_alsa.c.
char context[AST_MAX_CONTEXT] = "default" [static] |
Definition at line 123 of file chan_alsa.c.
Referenced by __login_exec(), acf_vmcount_exec(), action_agent_callback_login(), action_atxfer(), action_extensionstate(), action_originate(), action_redirect(), append_mailbox_mapping(), ast_compile_ael2(), ast_get_enum(), ast_get_srv(), ast_get_txt(), asyncgoto_exec(), build_device(), build_gateway(), check_user_full(), cmd_atxfer(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_include(), create_addr_from_peer(), disa_exec(), extenspy_exec(), get_also_info(), get_cid_name(), get_destination(), gtalk_load_config(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), handle_request_bye(), handle_request_invite(), handle_request_options(), handle_request_refer(), handle_show_dialplan(), hasvoicemail_exec(), log_exec(), metermaidstate(), orig_exten(), parkandannounce_exec(), pickup_exec(), process_ast_dsp(), process_weights(), register_peer_exten(), reload_config(), retrydial_exec(), SHA1Input(), SHA1PadMessage(), SHA1ProcessMessageBlock(), SHA1Reset(), SHA1Result(), sip_alloc(), and wait_for_answer().
int cursound = -1 [static] |
Definition at line 179 of file chan_alsa.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 76 of file chan_alsa.c.
Referenced by gtalk_load_config(), load_module(), misdn_cfg_init(), reload_config(), and setup_dahdi().
char dial_usage[] [static] |
Initial value:
"Usage: console dial [extension[@context]]\n" " Dials a given extension (and context if specified)\n"
Definition at line 1252 of file chan_alsa.c.
char exten[AST_MAX_EXTENSION] = "s" [static] |
Definition at line 125 of file chan_alsa.c.
Referenced by action_agent_callback_login(), action_atxfer(), action_extensionstate(), action_originate(), action_redirect(), add_extensions(), ast_compile_ael2(), ast_context_remove_extension_callerid2(), ast_feature_interpret(), ast_get_extension_context(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_ivr_menu_run_internal(), ast_parseable_goto(), ast_walk_context_extensions(), ast_walk_extension_priorities(), asyncgoto_exec(), build_device(), check_access(), check_user_full(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_dpreply(), destroy_extensions(), destroy_station(), disa_exec(), extenspy_exec(), fix_gotos_in_extensions(), gen_prios(), get_cid_name(), get_destination(), gtalk_alloc(), handle_context_add_extension(), handle_context_add_extension_deprecated(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), handle_request_invite(), handle_show_dialplan(), handle_showfeatures(), initreqprep(), leave_voicemail(), linkexten(), linkprio(), metermaidstate(), mgcp_ss(), new_iax(), orig_exten(), osplookup_exec(), park_add_hints(), parkandannounce_exec(), pickup_exec(), register_verify(), remap_feature(), set_priorities(), skinny_answer(), skinny_indicate(), socket_process(), ss_thread(), transmit_register(), unmap_features(), and waitstream_core().
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE [static] |
Definition at line 103 of file chan_alsa.c.
Referenced by acf_sprintf(), acf_strftime(), acf_strptime(), action_originate(), add_codec_to_answer(), ast_codec_pref_getsize(), ast_getformatbyname(), ast_monitor_stop(), ast_openvstream(), ast_parse_allow_disallow(), ast_rtp_lookup_mime_multiple(), build_user(), check_header(), echo_exec(), handle_saydatetime(), handle_showfeatures(), handle_showmancmds(), handle_showmanconn(), process_sdp(), reload_config(), sayunixtime_exec(), set_config(), socket_process(), start_monitor_action(), and start_monitor_exec().
struct ast_jb_conf global_jbconf [static] |
Definition at line 82 of file chan_alsa.c.
Referenced by __oh323_rtp_create(), __oh323_update_info(), _build_general_config(), alsa_new(), dahdi_new(), gtalk_load_config(), gtalk_new(), load_module(), mgcp_new(), misdn_cfg_init(), misdn_get_global_jbconf(), oss_new(), process_dahdi(), reload_config(), setup_dahdi(), sip_get_rtp_peer(), sip_new(), skinny_new(), and store_config().
char hangup_usage[] [static] |
Initial value:
"Usage: console hangup\n" " Hangs up any call currently placed on the console.\n"
Definition at line 1134 of file chan_alsa.c.
int hookstate = 0 [static] |
Definition at line 128 of file chan_alsa.c.
char indevname[50] = ALSA_INDEV [static] |
Definition at line 108 of file chan_alsa.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 124 of file chan_alsa.c.
Referenced by agent_new(), ast_do_masquerade(), begin_dial(), build_device(), build_gateway(), check_user_full(), create_addr_from_peer(), dahdi_new(), features_call(), func_channel_write(), gtalk_new(), language_write(), local_call(), mgcp_new(), nbs_new(), oss_new(), read_config(), sip_new(), skinny_new(), and vm_execmain().
char mohinterpret[MAX_MUSICCLASS] [static] |
Definition at line 126 of file chan_alsa.c.
Referenced by build_device(), check_user_full(), create_addr_from_peer(), and sip_alloc().
int nosound = 0 [static] |
Definition at line 183 of file chan_alsa.c.
int offset = 0 [static] |
Definition at line 182 of file chan_alsa.c.
Referenced by _macro_exec(), ast_dynamic_str_thread_build_va(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_tw(), ast_slinfactory_read(), au_seek(), au_tell(), cliinput(), copy_request(), fileexists_test(), function_remote(), g729_seek(), g729_tell(), gsm_seek(), gsm_tell(), h263_tell(), h264_tell(), ilbc_seek(), ilbc_tell(), mkintf(), mp3_exec(), NBScat_exec(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), pcm_seek(), resynch_jb(), send_waveform_to_channel(), setkenwood(), slinear_seek(), vox_seek(), vox_tell(), wav_seek(), and wav_tell().
char outdevname[50] = ALSA_OUTDEV [static] |
Definition at line 109 of file chan_alsa.c.
int readdev = -1 [static] |
Definition at line 174 of file chan_alsa.c.
int sampsent = 0 [static] |
Definition at line 180 of file chan_alsa.c.
char sendtext_usage[] [static] |
Initial value:
"Usage: console send text <message>\n" " Sends a text message for display on the remote terminal.\n"
Definition at line 988 of file chan_alsa.c.
short silence[FRAME_SIZE] = { 0, } [static] |
Definition at line 130 of file chan_alsa.c.
Referenced by ast_dsp_process(), handle_recordfile(), record_exec(), and send_sound().
int silencelen = 0 [static] |
Definition at line 181 of file chan_alsa.c.
int silencesuppression = 0 [static] |
Definition at line 115 of file chan_alsa.c.
int silencethreshold = 1000 [static] |
int sndcmd[2] [static] |
Definition at line 150 of file chan_alsa.c.
pthread_t sthread |
Definition at line 169 of file chan_alsa.c.
const char tdesc[] = "ALSA Console Channel Driver" [static] |
Definition at line 120 of file chan_alsa.c.
int writedev = -1 [static] |
Definition at line 175 of file chan_alsa.c.