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