#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 "asterisk/poll-compat.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 = "361d7bb937402d51e4658efb5b4d76e4" , .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 87 of file chan_alsa.c.
#define ALSA_OUTDEV "default" |
Definition at line 88 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 98 of file chan_alsa.c.
#define DEBUG 0 |
Definition at line 85 of file chan_alsa.c.
#define DESIRED_RATE 8000 |
#define FRAME_SIZE 160 |
Definition at line 92 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 172 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 101 of file chan_alsa.c.
#define PERIOD_FRAMES 80 |
static void __reg_module | ( | void | ) | [static] |
Definition at line 1385 of file chan_alsa.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 1385 of file chan_alsa.c.
static int alsa_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 554 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.
00555 { 00556 ast_mutex_lock(&alsalock); 00557 ast_verbose(" << Console call has been answered >> \n"); 00558 answer_sound(); 00559 ast_setstate(c, AST_STATE_UP); 00560 cursound = -1; 00561 snd_pcm_prepare(alsa.icard); 00562 snd_pcm_start(alsa.icard); 00563 ast_mutex_unlock(&alsalock); 00564 return 0; 00565 }
static int alsa_call | ( | struct ast_channel * | c, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 511 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.
00512 { 00513 int res = 3; 00514 struct ast_frame f = { AST_FRAME_CONTROL }; 00515 ast_mutex_lock(&alsalock); 00516 ast_verbose(" << Call placed to '%s' on console >> \n", dest); 00517 if (autoanswer) { 00518 ast_verbose(" << Auto-answered >> \n"); 00519 grab_owner(); 00520 if (alsa.owner) { 00521 f.subclass = AST_CONTROL_ANSWER; 00522 ast_queue_frame(alsa.owner, &f); 00523 ast_mutex_unlock(&alsa.owner->lock); 00524 } 00525 } else { 00526 ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00527 grab_owner(); 00528 if (alsa.owner) { 00529 f.subclass = AST_CONTROL_RINGING; 00530 ast_queue_frame(alsa.owner, &f); 00531 ast_mutex_unlock(&alsa.owner->lock); 00532 } 00533 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00534 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00535 } 00536 } 00537 snd_pcm_prepare(alsa.icard); 00538 snd_pcm_start(alsa.icard); 00539 ast_mutex_unlock(&alsalock); 00540 return 0; 00541 }
static snd_pcm_t* alsa_card_init | ( | char * | dev, | |
snd_pcm_stream_t | stream | |||
) | [static] |
Definition at line 341 of file chan_alsa.c.
References ast_log(), DESIRED_RATE, LOG_DEBUG, LOG_ERROR, LOG_WARNING, and PERIOD_FRAMES.
Referenced by soundcard_init().
00342 { 00343 int err; 00344 int direction; 00345 snd_pcm_t *handle = NULL; 00346 snd_pcm_hw_params_t *hwparams = NULL; 00347 snd_pcm_sw_params_t *swparams = NULL; 00348 struct pollfd pfd; 00349 snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4; 00350 /* int period_bytes = 0; */ 00351 snd_pcm_uframes_t buffer_size = 0; 00352 00353 unsigned int rate = DESIRED_RATE; 00354 #if 0 00355 unsigned int per_min = 1; 00356 #endif 00357 /* unsigned int per_max = 8; */ 00358 snd_pcm_uframes_t start_threshold, stop_threshold; 00359 00360 err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK); 00361 if (err < 0) { 00362 ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err)); 00363 return NULL; 00364 } else 00365 ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write"); 00366 00367 hwparams = alloca(snd_pcm_hw_params_sizeof()); 00368 memset(hwparams, 0, snd_pcm_hw_params_sizeof()); 00369 snd_pcm_hw_params_any(handle, hwparams); 00370 00371 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); 00372 if (err < 0) 00373 ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err)); 00374 00375 err = snd_pcm_hw_params_set_format(handle, hwparams, format); 00376 if (err < 0) 00377 ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err)); 00378 00379 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1); 00380 if (err < 0) 00381 ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err)); 00382 00383 direction = 0; 00384 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction); 00385 if (rate != DESIRED_RATE) 00386 ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate); 00387 00388 direction = 0; 00389 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction); 00390 if (err < 0) 00391 ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err)); 00392 else 00393 ast_log(LOG_DEBUG, "Period size is %d\n", err); 00394 00395 buffer_size = 4096 * 2; /* period_size * 16; */ 00396 err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); 00397 if (err < 0) 00398 ast_log(LOG_WARNING, "Problem setting buffer size of %ld: %s\n", buffer_size, snd_strerror(err)); 00399 else 00400 ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err); 00401 00402 #if 0 00403 direction = 0; 00404 err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction); 00405 if (err < 0) 00406 ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err)); 00407 00408 err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0); 00409 if (err < 0) 00410 ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err)); 00411 #endif 00412 00413 err = snd_pcm_hw_params(handle, hwparams); 00414 if (err < 0) 00415 ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err)); 00416 00417 swparams = alloca(snd_pcm_sw_params_sizeof()); 00418 memset(swparams, 0, snd_pcm_sw_params_sizeof()); 00419 snd_pcm_sw_params_current(handle, swparams); 00420 00421 #if 1 00422 if (stream == SND_PCM_STREAM_PLAYBACK) 00423 start_threshold = period_size; 00424 else 00425 start_threshold = 1; 00426 00427 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); 00428 if (err < 0) 00429 ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err)); 00430 #endif 00431 00432 #if 1 00433 if (stream == SND_PCM_STREAM_PLAYBACK) 00434 stop_threshold = buffer_size; 00435 else 00436 stop_threshold = buffer_size; 00437 00438 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); 00439 if (err < 0) 00440 ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err)); 00441 #endif 00442 #if 0 00443 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, PERIOD_FRAMES); 00444 if (err < 0) 00445 ast_log(LOG_ERROR, "Unable to set xfer alignment: %s\n", snd_strerror(err)); 00446 #endif 00447 00448 #if 0 00449 err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold); 00450 if (err < 0) 00451 ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err)); 00452 #endif 00453 err = snd_pcm_sw_params(handle, swparams); 00454 if (err < 0) 00455 ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err)); 00456 00457 err = snd_pcm_poll_descriptors_count(handle); 00458 if (err <= 0) 00459 ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err)); 00460 if (err != 1) 00461 ast_log(LOG_DEBUG, "Can't handle more than one device\n"); 00462 00463 snd_pcm_poll_descriptors(handle, &pfd, err); 00464 ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd); 00465 00466 if (stream == SND_PCM_STREAM_CAPTURE) 00467 readdev = pfd.fd; 00468 else 00469 writedev = pfd.fd; 00470 00471 return handle; 00472 }
static int alsa_digit | ( | struct ast_channel * | c, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 487 of file chan_alsa.c.
References alsalock, ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().
00488 { 00489 ast_mutex_lock(&alsalock); 00490 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00491 digit, duration); 00492 ast_mutex_unlock(&alsalock); 00493 return 0; 00494 }
static int alsa_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 735 of file chan_alsa.c.
References alsalock, ast_mutex_lock(), ast_mutex_unlock(), chan_alsa_pvt::owner, and ast_channel::tech_pvt.
00736 { 00737 struct chan_alsa_pvt *p = newchan->tech_pvt; 00738 ast_mutex_lock(&alsalock); 00739 p->owner = newchan; 00740 ast_mutex_unlock(&alsalock); 00741 return 0; 00742 }
static int alsa_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 567 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.
00568 { 00569 int res; 00570 ast_mutex_lock(&alsalock); 00571 cursound = -1; 00572 c->tech_pvt = NULL; 00573 alsa.owner = NULL; 00574 ast_verbose(" << Hangup on console >> \n"); 00575 ast_module_unref(ast_module_info->self); 00576 if (hookstate) { 00577 hookstate = 0; 00578 if (!autoanswer) { 00579 /* Congestion noise */ 00580 res = 2; 00581 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00582 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00583 } 00584 } 00585 } 00586 snd_pcm_drop(alsa.icard); 00587 ast_mutex_unlock(&alsalock); 00588 return 0; 00589 }
static int alsa_indicate | ( | struct ast_channel * | chan, | |
int | cond, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 744 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.
00745 { 00746 int res = 0; 00747 00748 ast_mutex_lock(&alsalock); 00749 00750 switch (cond) { 00751 case AST_CONTROL_BUSY: 00752 res = 1; 00753 break; 00754 case AST_CONTROL_CONGESTION: 00755 res = 2; 00756 break; 00757 case AST_CONTROL_RINGING: 00758 case AST_CONTROL_PROGRESS: 00759 break; 00760 case -1: 00761 res = -1; 00762 break; 00763 case AST_CONTROL_VIDUPDATE: 00764 res = -1; 00765 break; 00766 case AST_CONTROL_HOLD: 00767 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00768 ast_moh_start(chan, data, mohinterpret); 00769 break; 00770 case AST_CONTROL_UNHOLD: 00771 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00772 ast_moh_stop(chan); 00773 break; 00774 case AST_CONTROL_SRCUPDATE: 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 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00783 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00784 } 00785 } 00786 00787 ast_mutex_unlock(&alsalock); 00788 00789 return res; 00790 }
static struct ast_channel* alsa_new | ( | struct chan_alsa_pvt * | p, | |
int | state | |||
) | [static] |
Definition at line 792 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().
00793 { 00794 struct ast_channel *tmp = NULL; 00795 00796 if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "ALSA/%s", indevname))) 00797 return NULL; 00798 00799 tmp->tech = &alsa_tech; 00800 tmp->fds[0] = readdev; 00801 tmp->nativeformats = AST_FORMAT_SLINEAR; 00802 tmp->readformat = AST_FORMAT_SLINEAR; 00803 tmp->writeformat = AST_FORMAT_SLINEAR; 00804 tmp->tech_pvt = p; 00805 if (!ast_strlen_zero(p->context)) 00806 ast_copy_string(tmp->context, p->context, sizeof(tmp->context)); 00807 if (!ast_strlen_zero(p->exten)) 00808 ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten)); 00809 if (!ast_strlen_zero(language)) 00810 ast_string_field_set(tmp, language, language); 00811 p->owner = tmp; 00812 ast_module_ref(ast_module_info->self); 00813 ast_jb_configure(tmp, &global_jbconf); 00814 if (state != AST_STATE_DOWN) { 00815 if (ast_pbx_start(tmp)) { 00816 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00817 ast_hangup(tmp); 00818 tmp = NULL; 00819 } 00820 } 00821 00822 return tmp; 00823 }
static struct ast_frame * alsa_read | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 660 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.
00661 { 00662 static struct ast_frame f; 00663 static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2]; 00664 short *buf; 00665 static int readpos = 0; 00666 static int left = FRAME_SIZE; 00667 snd_pcm_state_t state; 00668 int r = 0; 00669 int off = 0; 00670 00671 ast_mutex_lock(&alsalock); 00672 /* Acknowledge any pending cmd */ 00673 f.frametype = AST_FRAME_NULL; 00674 f.subclass = 0; 00675 f.samples = 0; 00676 f.datalen = 0; 00677 f.data = NULL; 00678 f.offset = 0; 00679 f.src = "Console"; 00680 f.mallocd = 0; 00681 f.delivery.tv_sec = 0; 00682 f.delivery.tv_usec = 0; 00683 00684 state = snd_pcm_state(alsa.icard); 00685 if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) { 00686 snd_pcm_prepare(alsa.icard); 00687 } 00688 00689 buf = __buf + AST_FRIENDLY_OFFSET / 2; 00690 00691 r = snd_pcm_readi(alsa.icard, buf + readpos, left); 00692 if (r == -EPIPE) { 00693 #if DEBUG 00694 ast_log(LOG_ERROR, "XRUN read\n"); 00695 #endif 00696 snd_pcm_prepare(alsa.icard); 00697 } else if (r == -ESTRPIPE) { 00698 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00699 snd_pcm_prepare(alsa.icard); 00700 } else if (r < 0) { 00701 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00702 } else if (r >= 0) { 00703 off -= r; 00704 } 00705 /* Update positions */ 00706 readpos += r; 00707 left -= r; 00708 00709 if (readpos >= FRAME_SIZE) { 00710 /* A real frame */ 00711 readpos = 0; 00712 left = FRAME_SIZE; 00713 if (chan->_state != AST_STATE_UP) { 00714 /* Don't transmit unless it's up */ 00715 ast_mutex_unlock(&alsalock); 00716 return &f; 00717 } 00718 f.frametype = AST_FRAME_VOICE; 00719 f.subclass = AST_FORMAT_SLINEAR; 00720 f.samples = FRAME_SIZE; 00721 f.datalen = FRAME_SIZE * 2; 00722 f.data = buf; 00723 f.offset = AST_FRIENDLY_OFFSET; 00724 f.src = "Console"; 00725 f.mallocd = 0; 00726 #ifdef ALSA_MONITOR 00727 alsa_monitor_read((char *) buf, FRAME_SIZE * 2); 00728 #endif 00729 00730 } 00731 ast_mutex_unlock(&alsalock); 00732 return &f; 00733 }
static struct ast_channel * alsa_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 825 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.
00826 { 00827 int oldformat = format; 00828 struct ast_channel *tmp = NULL; 00829 00830 format &= AST_FORMAT_SLINEAR; 00831 if (!format) { 00832 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat); 00833 return NULL; 00834 } 00835 00836 ast_mutex_lock(&alsalock); 00837 00838 if (alsa.owner) { 00839 ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n"); 00840 *cause = AST_CAUSE_BUSY; 00841 } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN))) 00842 ast_log(LOG_WARNING, "Unable to create new ALSA channel\n"); 00843 00844 ast_mutex_unlock(&alsalock); 00845 00846 return tmp; 00847 }
static int alsa_text | ( | struct ast_channel * | c, | |
const char * | text | |||
) | [static] |
Definition at line 496 of file chan_alsa.c.
References alsalock, ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().
00497 { 00498 ast_mutex_lock(&alsalock); 00499 ast_verbose(" << Console Received text %s >> \n", text); 00500 ast_mutex_unlock(&alsalock); 00501 return 0; 00502 }
static int alsa_write | ( | struct ast_channel * | chan, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 591 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.
00592 { 00593 static char sizbuf[8000]; 00594 static int sizpos = 0; 00595 int len = sizpos; 00596 int pos; 00597 int res = 0; 00598 /* size_t frames = 0; */ 00599 snd_pcm_state_t state; 00600 00601 /* Immediately return if no sound is enabled */ 00602 if (nosound) 00603 return 0; 00604 00605 ast_mutex_lock(&alsalock); 00606 /* Stop any currently playing sound */ 00607 if (cursound != -1) { 00608 snd_pcm_drop(alsa.ocard); 00609 snd_pcm_prepare(alsa.ocard); 00610 cursound = -1; 00611 } 00612 00613 00614 /* We have to digest the frame in 160-byte portions */ 00615 if (f->datalen > sizeof(sizbuf) - sizpos) { 00616 ast_log(LOG_WARNING, "Frame too large\n"); 00617 res = -1; 00618 } else { 00619 memcpy(sizbuf + sizpos, f->data, f->datalen); 00620 len += f->datalen; 00621 pos = 0; 00622 #ifdef ALSA_MONITOR 00623 alsa_monitor_write(sizbuf, len); 00624 #endif 00625 state = snd_pcm_state(alsa.ocard); 00626 if (state == SND_PCM_STATE_XRUN) 00627 snd_pcm_prepare(alsa.ocard); 00628 while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) { 00629 usleep(1); 00630 } 00631 if (res == -EPIPE) { 00632 #if DEBUG 00633 ast_log(LOG_DEBUG, "XRUN write\n"); 00634 #endif 00635 snd_pcm_prepare(alsa.ocard); 00636 while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) { 00637 usleep(1); 00638 } 00639 if (res != len / 2) { 00640 ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res)); 00641 res = -1; 00642 } else if (res < 0) { 00643 ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res)); 00644 res = -1; 00645 } 00646 } else { 00647 if (res == -ESTRPIPE) 00648 ast_log(LOG_ERROR, "You've got some big problems\n"); 00649 else if (res < 0) 00650 ast_log(LOG_NOTICE, "Error %d on write\n", res); 00651 } 00652 } 00653 ast_mutex_unlock(&alsalock); 00654 if (res > 0) 00655 res = 0; 00656 return res; 00657 }
static void answer_sound | ( | void | ) | [static] |
Definition at line 543 of file chan_alsa.c.
References ast_log(), errno, and LOG_WARNING.
Referenced by alsa_answer(), console_answer(), and console_answer_deprecated().
00544 { 00545 int res; 00546 00547 nosound = 1; 00548 res = 4; 00549 if (write(sndcmd[1], &res, sizeof(res)) < 0) { 00550 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno)); 00551 } 00552 }
static char* autoanswer_complete | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 894 of file chan_alsa.c.
References ast_strdup, ast_strlen_zero(), and MIN.
00895 { 00896 #ifndef MIN 00897 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00898 #endif 00899 switch (state) { 00900 case 0: 00901 if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2))) 00902 return ast_strdup("on"); 00903 case 1: 00904 if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3))) 00905 return ast_strdup("off"); 00906 default: 00907 return NULL; 00908 } 00909 return NULL; 00910 }
static int console_answer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 950 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.
00951 { 00952 int res = RESULT_SUCCESS; 00953 00954 if (argc != 2) 00955 return RESULT_SHOWUSAGE; 00956 00957 ast_mutex_lock(&alsalock); 00958 00959 if (!alsa.owner) { 00960 ast_cli(fd, "No one is calling us\n"); 00961 res = RESULT_FAILURE; 00962 } else { 00963 hookstate = 1; 00964 cursound = -1; 00965 grab_owner(); 00966 if (alsa.owner) { 00967 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00968 ast_queue_frame(alsa.owner, &f); 00969 ast_mutex_unlock(&alsa.owner->lock); 00970 } 00971 answer_sound(); 00972 } 00973 00974 snd_pcm_prepare(alsa.icard); 00975 snd_pcm_start(alsa.icard); 00976 00977 ast_mutex_unlock(&alsalock); 00978 00979 return RESULT_SUCCESS; 00980 }
static int console_answer_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 918 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.
00919 { 00920 int res = RESULT_SUCCESS; 00921 00922 if (argc != 1) 00923 return RESULT_SHOWUSAGE; 00924 00925 ast_mutex_lock(&alsalock); 00926 00927 if (!alsa.owner) { 00928 ast_cli(fd, "No one is calling us\n"); 00929 res = RESULT_FAILURE; 00930 } else { 00931 hookstate = 1; 00932 cursound = -1; 00933 grab_owner(); 00934 if (alsa.owner) { 00935 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00936 ast_queue_frame(alsa.owner, &f); 00937 ast_mutex_unlock(&alsa.owner->lock); 00938 } 00939 answer_sound(); 00940 } 00941 00942 snd_pcm_prepare(alsa.icard); 00943 snd_pcm_start(alsa.icard); 00944 00945 ast_mutex_unlock(&alsalock); 00946 00947 return RESULT_SUCCESS; 00948 }
static int console_autoanswer | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 874 of file chan_alsa.c.
References alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00875 { 00876 int res = RESULT_SUCCESS;; 00877 if ((argc != 2) && (argc != 3)) 00878 return RESULT_SHOWUSAGE; 00879 ast_mutex_lock(&alsalock); 00880 if (argc == 2) { 00881 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off"); 00882 } else { 00883 if (!strcasecmp(argv[2], "on")) 00884 autoanswer = -1; 00885 else if (!strcasecmp(argv[2], "off")) 00886 autoanswer = 0; 00887 else 00888 res = RESULT_SHOWUSAGE; 00889 } 00890 ast_mutex_unlock(&alsalock); 00891 return res; 00892 }
static int console_autoanswer_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 849 of file chan_alsa.c.
References alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
00850 { 00851 int res = RESULT_SUCCESS; 00852 00853 if ((argc != 1) && (argc != 2)) 00854 return RESULT_SHOWUSAGE; 00855 00856 ast_mutex_lock(&alsalock); 00857 00858 if (argc == 1) { 00859 ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off"); 00860 } else { 00861 if (!strcasecmp(argv[1], "on")) 00862 autoanswer = -1; 00863 else if (!strcasecmp(argv[1], "off")) 00864 autoanswer = 0; 00865 else 00866 res = RESULT_SHOWUSAGE; 00867 } 00868 00869 ast_mutex_unlock(&alsalock); 00870 00871 return res; 00872 }
static int console_dial | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1189 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.
01190 { 01191 char tmp[256], *tmp2; 01192 char *mye, *myc; 01193 char *d; 01194 int res = RESULT_SUCCESS; 01195 01196 if ((argc != 2) && (argc != 3)) 01197 return RESULT_SHOWUSAGE; 01198 01199 ast_mutex_lock(&alsalock); 01200 01201 if (alsa.owner) { 01202 if (argc == 3) { 01203 d = argv[2]; 01204 grab_owner(); 01205 if (alsa.owner) { 01206 struct ast_frame f = { AST_FRAME_DTMF }; 01207 while (*d) { 01208 f.subclass = *d; 01209 ast_queue_frame(alsa.owner, &f); 01210 d++; 01211 } 01212 ast_mutex_unlock(&alsa.owner->lock); 01213 } 01214 } else { 01215 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n"); 01216 res = RESULT_FAILURE; 01217 } 01218 } else { 01219 mye = exten; 01220 myc = context; 01221 if (argc == 3) { 01222 char *stringp = NULL; 01223 ast_copy_string(tmp, argv[2], sizeof(tmp)); 01224 stringp = tmp; 01225 strsep(&stringp, "@"); 01226 tmp2 = strsep(&stringp, "@"); 01227 if (!ast_strlen_zero(tmp)) 01228 mye = tmp; 01229 if (!ast_strlen_zero(tmp2)) 01230 myc = tmp2; 01231 } 01232 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01233 ast_copy_string(alsa.exten, mye, sizeof(alsa.exten)); 01234 ast_copy_string(alsa.context, myc, sizeof(alsa.context)); 01235 hookstate = 1; 01236 alsa_new(&alsa, AST_STATE_RINGING); 01237 } else 01238 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc); 01239 } 01240 01241 ast_mutex_unlock(&alsalock); 01242 01243 return res; 01244 }
static int console_dial_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1132 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.
01133 { 01134 char tmp[256], *tmp2; 01135 char *mye, *myc; 01136 char *d; 01137 int res = RESULT_SUCCESS; 01138 01139 if ((argc != 1) && (argc != 2)) 01140 return RESULT_SHOWUSAGE; 01141 01142 ast_mutex_lock(&alsalock); 01143 01144 if (alsa.owner) { 01145 if (argc == 2) { 01146 d = argv[1]; 01147 grab_owner(); 01148 if (alsa.owner) { 01149 struct ast_frame f = { AST_FRAME_DTMF }; 01150 while (*d) { 01151 f.subclass = *d; 01152 ast_queue_frame(alsa.owner, &f); 01153 d++; 01154 } 01155 ast_mutex_unlock(&alsa.owner->lock); 01156 } 01157 } else { 01158 ast_cli(fd, "You're already in a call. You can use this only to dial digits until you hangup\n"); 01159 res = RESULT_FAILURE; 01160 } 01161 } else { 01162 mye = exten; 01163 myc = context; 01164 if (argc == 2) { 01165 char *stringp = NULL; 01166 ast_copy_string(tmp, argv[1], sizeof(tmp)); 01167 stringp = tmp; 01168 strsep(&stringp, "@"); 01169 tmp2 = strsep(&stringp, "@"); 01170 if (!ast_strlen_zero(tmp)) 01171 mye = tmp; 01172 if (!ast_strlen_zero(tmp2)) 01173 myc = tmp2; 01174 } 01175 if (ast_exists_extension(NULL, myc, mye, 1, NULL)) { 01176 ast_copy_string(alsa.exten, mye, sizeof(alsa.exten)); 01177 ast_copy_string(alsa.context, myc, sizeof(alsa.context)); 01178 hookstate = 1; 01179 alsa_new(&alsa, AST_STATE_RINGING); 01180 } else 01181 ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc); 01182 } 01183 01184 ast_mutex_unlock(&alsalock); 01185 01186 return res; 01187 }
static int console_hangup | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1100 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.
01101 { 01102 int res = RESULT_SUCCESS; 01103 01104 if (argc != 2) 01105 return RESULT_SHOWUSAGE; 01106 01107 cursound = -1; 01108 01109 ast_mutex_lock(&alsalock); 01110 01111 if (!alsa.owner && !hookstate) { 01112 ast_cli(fd, "No call to hangup up\n"); 01113 res = RESULT_FAILURE; 01114 } else { 01115 hookstate = 0; 01116 grab_owner(); 01117 if (alsa.owner) { 01118 ast_queue_hangup(alsa.owner); 01119 ast_mutex_unlock(&alsa.owner->lock); 01120 } 01121 } 01122 01123 ast_mutex_unlock(&alsalock); 01124 01125 return res; 01126 }
static int console_hangup_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1072 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.
01073 { 01074 int res = RESULT_SUCCESS; 01075 01076 if (argc != 1) 01077 return RESULT_SHOWUSAGE; 01078 01079 cursound = -1; 01080 01081 ast_mutex_lock(&alsalock); 01082 01083 if (!alsa.owner && !hookstate) { 01084 ast_cli(fd, "No call to hangup up\n"); 01085 res = RESULT_FAILURE; 01086 } else { 01087 hookstate = 0; 01088 grab_owner(); 01089 if (alsa.owner) { 01090 ast_queue_hangup(alsa.owner); 01091 ast_mutex_unlock(&alsa.owner->lock); 01092 } 01093 } 01094 01095 ast_mutex_unlock(&alsalock); 01096 01097 return res; 01098 }
static int console_sendtext | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 1027 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.
01028 { 01029 int tmparg = 3; 01030 int res = RESULT_SUCCESS; 01031 01032 if (argc < 3) 01033 return RESULT_SHOWUSAGE; 01034 01035 ast_mutex_lock(&alsalock); 01036 01037 if (!alsa.owner) { 01038 ast_cli(fd, "No one is calling us\n"); 01039 res = RESULT_FAILURE; 01040 } else { 01041 struct ast_frame f = { AST_FRAME_TEXT, 0 }; 01042 char text2send[256] = ""; 01043 text2send[0] = '\0'; 01044 while (tmparg < argc) { 01045 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1); 01046 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1); 01047 } 01048 text2send[strlen(text2send) - 1] = '\n'; 01049 f.data = text2send; 01050 f.datalen = strlen(text2send) + 1; 01051 grab_owner(); 01052 if (alsa.owner) { 01053 ast_queue_frame(alsa.owner, &f); 01054 f.frametype = AST_FRAME_CONTROL; 01055 f.subclass = AST_CONTROL_ANSWER; 01056 f.data = NULL; 01057 f.datalen = 0; 01058 ast_queue_frame(alsa.owner, &f); 01059 ast_mutex_unlock(&alsa.owner->lock); 01060 } 01061 } 01062 01063 ast_mutex_unlock(&alsalock); 01064 01065 return res; 01066 }
static int console_sendtext_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 986 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.
00987 { 00988 int tmparg = 2; 00989 int res = RESULT_SUCCESS; 00990 00991 if (argc < 2) 00992 return RESULT_SHOWUSAGE; 00993 00994 ast_mutex_lock(&alsalock); 00995 00996 if (!alsa.owner) { 00997 ast_cli(fd, "No one is calling us\n"); 00998 res = RESULT_FAILURE; 00999 } else { 01000 struct ast_frame f = { AST_FRAME_TEXT, 0 }; 01001 char text2send[256] = ""; 01002 text2send[0] = '\0'; 01003 while (tmparg < argc) { 01004 strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1); 01005 strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1); 01006 } 01007 text2send[strlen(text2send) - 1] = '\n'; 01008 f.data = text2send; 01009 f.datalen = strlen(text2send) + 1; 01010 grab_owner(); 01011 if (alsa.owner) { 01012 ast_queue_frame(alsa.owner, &f); 01013 f.frametype = AST_FRAME_CONTROL; 01014 f.subclass = AST_CONTROL_ANSWER; 01015 f.data = NULL; 01016 f.datalen = 0; 01017 ast_queue_frame(alsa.owner, &f); 01018 ast_mutex_unlock(&alsa.owner->lock); 01019 } 01020 } 01021 01022 ast_mutex_unlock(&alsalock); 01023 01024 return res; 01025 }
static void grab_owner | ( | void | ) | [static] |
Definition at line 504 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().
00505 { 00506 while (alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) { 00507 DEADLOCK_AVOIDANCE(&alsalock); 00508 } 00509 }
static int load_module | ( | void | ) | [static] |
Definition at line 1297 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.
01298 { 01299 int res; 01300 struct ast_config *cfg; 01301 struct ast_variable *v; 01302 01303 /* Copy the default jb config over global_jbconf */ 01304 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf)); 01305 01306 strcpy(mohinterpret, "default"); 01307 01308 if ((cfg = ast_config_load(config))) { 01309 v = ast_variable_browse(cfg, "general"); 01310 for (; v; v = v->next) { 01311 /* handle jb conf */ 01312 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) 01313 continue; 01314 01315 if (!strcasecmp(v->name, "autoanswer")) 01316 autoanswer = ast_true(v->value); 01317 else if (!strcasecmp(v->name, "silencesuppression")) 01318 silencesuppression = ast_true(v->value); 01319 else if (!strcasecmp(v->name, "silencethreshold")) 01320 silencethreshold = atoi(v->value); 01321 else if (!strcasecmp(v->name, "context")) 01322 ast_copy_string(context, v->value, sizeof(context)); 01323 else if (!strcasecmp(v->name, "language")) 01324 ast_copy_string(language, v->value, sizeof(language)); 01325 else if (!strcasecmp(v->name, "extension")) 01326 ast_copy_string(exten, v->value, sizeof(exten)); 01327 else if (!strcasecmp(v->name, "input_device")) 01328 ast_copy_string(indevname, v->value, sizeof(indevname)); 01329 else if (!strcasecmp(v->name, "output_device")) 01330 ast_copy_string(outdevname, v->value, sizeof(outdevname)); 01331 else if (!strcasecmp(v->name, "mohinterpret")) 01332 ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret)); 01333 } 01334 ast_config_destroy(cfg); 01335 } 01336 res = pipe(sndcmd); 01337 if (res) { 01338 ast_log(LOG_ERROR, "Unable to create pipe\n"); 01339 return -1; 01340 } 01341 res = soundcard_init(); 01342 if (res < 0) { 01343 if (option_verbose > 1) { 01344 ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n"); 01345 ast_verbose(VERBOSE_PREFIX_2 "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n"); 01346 } 01347 return 0; 01348 } 01349 01350 res = ast_channel_register(&alsa_tech); 01351 if (res < 0) { 01352 ast_log(LOG_ERROR, "Unable to register channel class 'Console'\n"); 01353 return -1; 01354 } 01355 ast_cli_register_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry)); 01356 01357 ast_pthread_create_background(&sthread, NULL, sound_thread, NULL); 01358 #ifdef ALSA_MONITOR 01359 if (alsa_monitor_start()) 01360 ast_log(LOG_ERROR, "Problem starting Monitoring\n"); 01361 #endif 01362 return 0; 01363 }
static int send_sound | ( | void | ) | [static] |
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 while ((res = snd_pcm_writei(alsa.ocard, frame, res)) == -EAGAIN) { 00271 usleep(1); 00272 } 00273 if (res > 0) 00274 return 0; 00275 return 0; 00276 }
static void* sound_thread | ( | void * | unused | ) | [static] |
Definition at line 278 of file chan_alsa.c.
References alsa, ast_log(), ast_poll, errno, FRAME_SIZE, chan_alsa_pvt::icard, LOG_ERROR, LOG_WARNING, chan_alsa_pvt::ocard, chan_alsa_pvt::owner, and send_sound().
Referenced by load_module().
00279 { 00280 struct pollfd pfd[3] = { { .fd = sndcmd[0], .events = POLLIN }, { .fd = writedev }, { .fd = readdev } }; 00281 int res, x; 00282 00283 for (;;) { 00284 for (x = 0; x < 3; x++) { 00285 pfd[x].revents = 0; 00286 } 00287 00288 pfd[1].events = cursound > -1 ? POLLOUT : 0; 00289 #ifdef ALSA_MONITOR 00290 pfd[2].events = !alsa.owner ? POLLIN : 0; 00291 #endif 00292 res = ast_poll(pfd, 3, -1); 00293 if (res < 1) { 00294 ast_log(LOG_WARNING, "poll() failed: %s\n", strerror(errno)); 00295 continue; 00296 } 00297 #ifdef ALSA_MONITOR 00298 if (pfd[2].revents & POLLIN) { 00299 /* Keep the pipe going with read audio */ 00300 snd_pcm_state_t state; 00301 short buf[FRAME_SIZE]; 00302 int r; 00303 00304 state = snd_pcm_state(alsa.ocard); 00305 if (state == SND_PCM_STATE_XRUN) { 00306 snd_pcm_prepare(alsa.ocard); 00307 } 00308 r = snd_pcm_readi(alsa.icard, buf, FRAME_SIZE); 00309 if (r == -EPIPE) { 00310 #if DEBUG 00311 ast_log(LOG_ERROR, "XRUN read\n"); 00312 #endif 00313 snd_pcm_prepare(alsa.icard); 00314 } else if (r == -ESTRPIPE) { 00315 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00316 snd_pcm_prepare(alsa.icard); 00317 } else if (r < 0) { 00318 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00319 } else 00320 alsa_monitor_read((char *) buf, r * 2); 00321 } 00322 #endif 00323 if (pfd[0].revents & POLLIN) { 00324 if (read(sndcmd[0], &cursound, sizeof(cursound)) < 0) { 00325 ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno)); 00326 } 00327 silencelen = 0; 00328 offset = 0; 00329 sampsent = 0; 00330 } 00331 if (pfd[1].revents & POLLOUT) { 00332 if (send_sound()) { 00333 ast_log(LOG_WARNING, "Failed to write sound\n"); 00334 } 00335 } 00336 } 00337 /* Never reached */ 00338 return NULL; 00339 }
static int soundcard_init | ( | void | ) | [static] |
Definition at line 474 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().
00475 { 00476 alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE); 00477 alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK); 00478 00479 if (!alsa.icard || !alsa.ocard) { 00480 ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n"); 00481 return -1; 00482 } 00483 00484 return readdev; 00485 }
static int unload_module | ( | void | ) | [static] |
Definition at line 1365 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.
01366 { 01367 ast_channel_unregister(&alsa_tech); 01368 ast_cli_unregister_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry)); 01369 01370 if (alsa.icard) 01371 snd_pcm_close(alsa.icard); 01372 if (alsa.ocard) 01373 snd_pcm_close(alsa.ocard); 01374 if (sndcmd[0] > 0) { 01375 close(sndcmd[0]); 01376 close(sndcmd[1]); 01377 } 01378 if (alsa.owner) 01379 ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD); 01380 if (alsa.owner) 01381 return -1; 01382 return 0; 01383 }
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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 1385 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 198 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 119 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 1068 of file chan_alsa.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 1385 of file chan_alsa.c.
int autoanswer = 1 [static] |
Definition at line 178 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 912 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 1250 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 1270 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 1260 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 1255 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 1265 of file chan_alsa.c.
const char config[] = "alsa.conf" [static] |
Definition at line 122 of file chan_alsa.c.
char context[AST_MAX_CONTEXT] = "default" [static] |
Definition at line 124 of file chan_alsa.c.
Referenced by __login_exec(), acf_vmcount_exec(), action_agent_callback_login(), 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(), 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 180 of file chan_alsa.c.
struct ast_jb_conf default_jbconf [static] |
Global jitterbuffer configuration - by default, jb is disabled
Definition at line 77 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 1246 of file chan_alsa.c.
char exten[AST_MAX_EXTENSION] = "s" [static] |
Definition at line 126 of file chan_alsa.c.
Referenced by action_agent_callback_login(), action_extensionstate(), action_originate(), action_redirect(), add_extensions(), ast_compile_ael2(), ast_context_remove_extension_callerid2(), ast_get_extension_context(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_ivr_menu_run_internal(), 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(), feature_interpret_helper(), 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(), hint_cmp(), 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 104 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(), check_header_fmt(), echo_exec(), handle_saydatetime(), handle_showfeatures(), handle_showmancmds(), handle_showmanconn(), process_sdp_a_audio(), 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 83 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 1128 of file chan_alsa.c.
int hookstate = 0 [static] |
Definition at line 129 of file chan_alsa.c.
char indevname[50] = ALSA_INDEV [static] |
Definition at line 109 of file chan_alsa.c.
char language[MAX_LANGUAGE] = "" [static] |
Definition at line 125 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_real(), 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 127 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 184 of file chan_alsa.c.
int offset = 0 [static] |
Definition at line 183 of file chan_alsa.c.
Referenced by _macro_exec(), ast_backtrace(), 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_zh(), 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 110 of file chan_alsa.c.
int readdev = -1 [static] |
Definition at line 175 of file chan_alsa.c.
int sampsent = 0 [static] |
Definition at line 181 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 982 of file chan_alsa.c.
short silence[FRAME_SIZE] = { 0, } [static] |
Definition at line 131 of file chan_alsa.c.
Referenced by ast_dsp_process(), handle_recordfile(), record_exec(), and send_sound().
int silencelen = 0 [static] |
Definition at line 182 of file chan_alsa.c.
int silencesuppression = 0 [static] |
Definition at line 116 of file chan_alsa.c.
int silencethreshold = 1000 [static] |
int sndcmd[2] [static] |
Definition at line 151 of file chan_alsa.c.
pthread_t sthread |
Definition at line 170 of file chan_alsa.c.
const char tdesc[] = "ALSA Console Channel Driver" [static] |
Definition at line 121 of file chan_alsa.c.
int writedev = -1 [static] |
Definition at line 176 of file chan_alsa.c.