#include "asterisk.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/endian.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/musiconhold.h"
#include "busy.h"
#include "ringtone.h"
#include "ring10.h"
#include "answer.h"
Include dependency graph for chan_alsa.c:

Go to the source code of this file.
Data Structures | |
| struct | chan_alsa_pvt |
| struct | sound |
Defines | |
| #define | ALSA_INDEV "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 int | alsa_answer (struct ast_channel *c) |
| static int | alsa_call (struct ast_channel *c, char *dest, int timeout) |
| static snd_pcm_t * | alsa_card_init (char *dev, snd_pcm_stream_t stream) |
| static int | alsa_digit (struct ast_channel *c, char digit, unsigned int duration) |
| static int | alsa_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
| static int | alsa_hangup (struct ast_channel *c) |
| static int | alsa_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen) |
| static struct ast_channel * | alsa_new (struct chan_alsa_pvt *p, int state) |
| static struct ast_frame * | alsa_read (struct ast_channel *chan) |
| static struct ast_channel * | alsa_request (const char *type, int format, void *data, int *cause) |
| static int | alsa_text (struct ast_channel *c, const char *text) |
| static int | alsa_write (struct ast_channel *chan, struct ast_frame *f) |
| static void | answer_sound (void) |
| AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"ALSA Console Channel Driver") | |
| AST_MUTEX_DEFINE_STATIC (alsalock) | |
| static char * | autoanswer_complete (const char *line, const char *word, int pos, int state) |
| static int | console_answer (int fd, int argc, char *argv[]) |
| static int | console_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 chan_alsa_pvt | alsa |
| static struct ast_channel_tech | alsa_tech |
| static char | answer_usage [] |
| static int | autoanswer = 1 |
| static const char | autoanswer_usage [] |
| static struct ast_cli_entry | cli_alsa [] |
| static struct ast_cli_entry | cli_alsa_answer_deprecated |
| static struct ast_cli_entry | cli_alsa_autoanswer_deprecated |
| static struct ast_cli_entry | cli_alsa_dial_deprecated |
| static struct ast_cli_entry | cli_alsa_hangup_deprecated |
| static struct ast_cli_entry | cli_alsa_send_text_deprecated |
| static const char | config [] = "alsa.conf" |
| static char | context [AST_MAX_CONTEXT] = "default" |
| static int | cursound = -1 |
| static struct ast_jb_conf | default_jbconf |
| static char | dial_usage [] |
| static char | exten [AST_MAX_EXTENSION] = "s" |
| static snd_pcm_format_t | format = SND_PCM_FORMAT_S16_LE |
| static struct ast_jb_conf | global_jbconf |
| static char | hangup_usage [] |
| static int | hookstate = 0 |
| static char | indevname [50] = ALSA_INDEV |
| static char | language [MAX_LANGUAGE] = "" |
| static char | mohinterpret [MAX_MUSICCLASS] |
| static int | nosound = 0 |
| static int | offset = 0 |
| static char | outdevname [50] = ALSA_OUTDEV |
| static int | readdev = -1 |
| static int | sampsent = 0 |
| static char | sendtext_usage [] |
| static short | silence [FRAME_SIZE] = { 0, } |
| static int | silencelen = 0 |
| static int | silencesuppression = 0 |
| static int | silencethreshold = 1000 |
| static int | sndcmd [2] |
| static struct sound | sounds [] |
| pthread_t | sthread |
| static const char | tdesc [] = "ALSA Console Channel Driver" |
| static int | writedev = -1 |
Definition in file chan_alsa.c.
| #define ALSA_INDEV "default" |
Definition at line 86 of file chan_alsa.c.
| #define ALSA_OUTDEV "default" |
Definition at line 87 of file chan_alsa.c.
| #define ALSA_PCM_NEW_HW_PARAMS_API |
Definition at line 47 of file chan_alsa.c.
| #define ALSA_PCM_NEW_SW_PARAMS_API |
Definition at line 48 of file chan_alsa.c.
| #define BUFFER_FMT ((buffersize * 10) << 16) | (0x0006); |
Definition at line 97 of file chan_alsa.c.
| #define DEBUG 0 |
Definition at line 84 of file chan_alsa.c.
| #define DESIRED_RATE 8000 |
| #define FRAME_SIZE 160 |
Definition at line 91 of file chan_alsa.c.
Referenced by alsa_read(), oss_read(), send_sound(), sound_thread(), and soundcard_writeframe().
| #define MAX_BUFFER_SIZE 100 |
Definition at line 171 of file chan_alsa.c.
| #define MIN | ( | a, | |||
| b | ) | ((a) < (b) ? (a) : (b)) |
Referenced by autoanswer_complete().
| #define MIN_SWITCH_TIME 600 |
Definition at line 100 of file chan_alsa.c.
| #define PERIOD_FRAMES 80 |
| static int alsa_answer | ( | struct ast_channel * | c | ) | [static] |
Definition at line 552 of file chan_alsa.c.
References alsa, answer_sound(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verbose(), and chan_alsa_pvt::icard.
00553 { 00554 ast_mutex_lock(&alsalock); 00555 ast_verbose(" << Console call has been answered >> \n"); 00556 answer_sound(); 00557 ast_setstate(c, AST_STATE_UP); 00558 cursound = -1; 00559 snd_pcm_prepare(alsa.icard); 00560 snd_pcm_start(alsa.icard); 00561 ast_mutex_unlock(&alsalock); 00562 return 0; 00563 }
| static int alsa_call | ( | struct ast_channel * | c, | |
| char * | dest, | |||
| int | timeout | |||
| ) | [static] |
Definition at line 513 of file chan_alsa.c.
References alsa, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_verbose(), f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, and chan_alsa_pvt::owner.
00514 { 00515 int res = 3; 00516 struct ast_frame f = { AST_FRAME_CONTROL }; 00517 ast_mutex_lock(&alsalock); 00518 ast_verbose(" << Call placed to '%s' on console >> \n", dest); 00519 if (autoanswer) { 00520 ast_verbose(" << Auto-answered >> \n"); 00521 grab_owner(); 00522 if (alsa.owner) { 00523 f.subclass = AST_CONTROL_ANSWER; 00524 ast_queue_frame(alsa.owner, &f); 00525 ast_mutex_unlock(&alsa.owner->lock); 00526 } 00527 } else { 00528 ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n"); 00529 grab_owner(); 00530 if (alsa.owner) { 00531 f.subclass = AST_CONTROL_RINGING; 00532 ast_queue_frame(alsa.owner, &f); 00533 ast_mutex_unlock(&alsa.owner->lock); 00534 } 00535 write(sndcmd[1], &res, sizeof(res)); 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 343 of file chan_alsa.c.
References ast_log(), DESIRED_RATE, pollfd::fd, LOG_DEBUG, LOG_ERROR, LOG_WARNING, and PERIOD_FRAMES.
Referenced by soundcard_init().
00344 { 00345 int err; 00346 int direction; 00347 snd_pcm_t *handle = NULL; 00348 snd_pcm_hw_params_t *hwparams = NULL; 00349 snd_pcm_sw_params_t *swparams = NULL; 00350 struct pollfd pfd; 00351 snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4; 00352 /* int period_bytes = 0; */ 00353 snd_pcm_uframes_t buffer_size = 0; 00354 00355 unsigned int rate = DESIRED_RATE; 00356 #if 0 00357 unsigned int per_min = 1; 00358 #endif 00359 /* unsigned int per_max = 8; */ 00360 snd_pcm_uframes_t start_threshold, stop_threshold; 00361 00362 err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK); 00363 if (err < 0) { 00364 ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err)); 00365 return NULL; 00366 } else 00367 ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write"); 00368 00369 hwparams = alloca(snd_pcm_hw_params_sizeof()); 00370 memset(hwparams, 0, snd_pcm_hw_params_sizeof()); 00371 snd_pcm_hw_params_any(handle, hwparams); 00372 00373 err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED); 00374 if (err < 0) 00375 ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err)); 00376 00377 err = snd_pcm_hw_params_set_format(handle, hwparams, format); 00378 if (err < 0) 00379 ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err)); 00380 00381 err = snd_pcm_hw_params_set_channels(handle, hwparams, 1); 00382 if (err < 0) 00383 ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err)); 00384 00385 direction = 0; 00386 err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction); 00387 if (rate != DESIRED_RATE) 00388 ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate); 00389 00390 direction = 0; 00391 err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction); 00392 if (err < 0) 00393 ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err)); 00394 else 00395 ast_log(LOG_DEBUG, "Period size is %d\n", err); 00396 00397 buffer_size = 4096 * 2; /* period_size * 16; */ 00398 err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size); 00399 if (err < 0) 00400 ast_log(LOG_WARNING, "Problem setting buffer size of %ld: %s\n", buffer_size, snd_strerror(err)); 00401 else 00402 ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err); 00403 00404 #if 0 00405 direction = 0; 00406 err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction); 00407 if (err < 0) 00408 ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err)); 00409 00410 err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0); 00411 if (err < 0) 00412 ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err)); 00413 #endif 00414 00415 err = snd_pcm_hw_params(handle, hwparams); 00416 if (err < 0) 00417 ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err)); 00418 00419 swparams = alloca(snd_pcm_sw_params_sizeof()); 00420 memset(swparams, 0, snd_pcm_sw_params_sizeof()); 00421 snd_pcm_sw_params_current(handle, swparams); 00422 00423 #if 1 00424 if (stream == SND_PCM_STREAM_PLAYBACK) 00425 start_threshold = period_size; 00426 else 00427 start_threshold = 1; 00428 00429 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold); 00430 if (err < 0) 00431 ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err)); 00432 #endif 00433 00434 #if 1 00435 if (stream == SND_PCM_STREAM_PLAYBACK) 00436 stop_threshold = buffer_size; 00437 else 00438 stop_threshold = buffer_size; 00439 00440 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold); 00441 if (err < 0) 00442 ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err)); 00443 #endif 00444 #if 0 00445 err = snd_pcm_sw_params_set_xfer_align(handle, swparams, PERIOD_FRAMES); 00446 if (err < 0) 00447 ast_log(LOG_ERROR, "Unable to set xfer alignment: %s\n", snd_strerror(err)); 00448 #endif 00449 00450 #if 0 00451 err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold); 00452 if (err < 0) 00453 ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err)); 00454 #endif 00455 err = snd_pcm_sw_params(handle, swparams); 00456 if (err < 0) 00457 ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err)); 00458 00459 err = snd_pcm_poll_descriptors_count(handle); 00460 if (err <= 0) 00461 ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err)); 00462 if (err != 1) 00463 ast_log(LOG_DEBUG, "Can't handle more than one device\n"); 00464 00465 snd_pcm_poll_descriptors(handle, &pfd, err); 00466 ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd); 00467 00468 if (stream == SND_PCM_STREAM_CAPTURE) 00469 readdev = pfd.fd; 00470 else 00471 writedev = pfd.fd; 00472 00473 return handle; 00474 }
| static int alsa_digit | ( | struct ast_channel * | c, | |
| char | digit, | |||
| unsigned int | duration | |||
| ) | [static] |
Definition at line 489 of file chan_alsa.c.
References ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().
00490 { 00491 ast_mutex_lock(&alsalock); 00492 ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 00493 digit, duration); 00494 ast_mutex_unlock(&alsalock); 00495 return 0; 00496 }
| static int alsa_fixup | ( | struct ast_channel * | oldchan, | |
| struct ast_channel * | newchan | |||
| ) | [static] |
Definition at line 727 of file chan_alsa.c.
References ast_mutex_lock(), ast_mutex_unlock(), chan_alsa_pvt::owner, and ast_channel::tech_pvt.
00728 { 00729 struct chan_alsa_pvt *p = newchan->tech_pvt; 00730 ast_mutex_lock(&alsalock); 00731 p->owner = newchan; 00732 ast_mutex_unlock(&alsalock); 00733 return 0; 00734 }
| static int alsa_hangup | ( | struct ast_channel * | c | ) | [static] |
Definition at line 565 of file chan_alsa.c.
References alsa, ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), chan_alsa_pvt::icard, chan_alsa_pvt::owner, and ast_channel::tech_pvt.
00566 { 00567 int res; 00568 ast_mutex_lock(&alsalock); 00569 cursound = -1; 00570 c->tech_pvt = NULL; 00571 alsa.owner = NULL; 00572 ast_verbose(" << Hangup on console >> \n"); 00573 ast_module_unref(ast_module_info->self); 00574 if (hookstate) { 00575 hookstate = 0; 00576 if (!autoanswer) { 00577 /* Congestion noise */ 00578 res = 2; 00579 write(sndcmd[1], &res, sizeof(res)); 00580 } 00581 } 00582 snd_pcm_drop(alsa.icard); 00583 ast_mutex_unlock(&alsalock); 00584 return 0; 00585 }
| static int alsa_indicate | ( | struct ast_channel * | chan, | |
| int | cond, | |||
| const void * | data, | |||
| size_t | datalen | |||
| ) | [static] |
Definition at line 736 of file chan_alsa.c.
References 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(), and LOG_WARNING.
00737 { 00738 int res = 0; 00739 00740 ast_mutex_lock(&alsalock); 00741 00742 switch (cond) { 00743 case AST_CONTROL_BUSY: 00744 res = 1; 00745 break; 00746 case AST_CONTROL_CONGESTION: 00747 res = 2; 00748 break; 00749 case AST_CONTROL_RINGING: 00750 case AST_CONTROL_PROGRESS: 00751 break; 00752 case -1: 00753 res = -1; 00754 break; 00755 case AST_CONTROL_VIDUPDATE: 00756 res = -1; 00757 break; 00758 case AST_CONTROL_HOLD: 00759 ast_verbose(" << Console Has Been Placed on Hold >> \n"); 00760 ast_moh_start(chan, data, mohinterpret); 00761 break; 00762 case AST_CONTROL_UNHOLD: 00763 ast_verbose(" << Console Has Been Retrieved from Hold >> \n"); 00764 ast_moh_stop(chan); 00765 break; 00766 case AST_CONTROL_SRCUPDATE: 00767 break; 00768 default: 00769 ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name); 00770 res = -1; 00771 } 00772 00773 if (res > -1) 00774 write(sndcmd[1], &res, sizeof(res)); 00775 00776 ast_mutex_unlock(&alsalock); 00777 00778 return res; 00779 }
| static struct ast_channel* alsa_new | ( | struct chan_alsa_pvt * | p, | |
| int | state | |||
| ) | [static] |
Definition at line 781 of file chan_alsa.c.
References alsa_tech, ast_channel_alloc(), 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().
00782 { 00783 struct ast_channel *tmp = NULL; 00784 00785 if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "ALSA/%s", indevname))) 00786 return NULL; 00787 00788 tmp->tech = &alsa_tech; 00789 tmp->fds[0] = readdev; 00790 tmp->nativeformats = AST_FORMAT_SLINEAR; 00791 tmp->readformat = AST_FORMAT_SLINEAR; 00792 tmp->writeformat = AST_FORMAT_SLINEAR; 00793 tmp->tech_pvt = p; 00794 if (!ast_strlen_zero(p->context)) 00795 ast_copy_string(tmp->context, p->context, sizeof(tmp->context)); 00796 if (!ast_strlen_zero(p->exten)) 00797 ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten)); 00798 if (!ast_strlen_zero(language)) 00799 ast_string_field_set(tmp, language, language); 00800 p->owner = tmp; 00801 ast_module_ref(ast_module_info->self); 00802 ast_jb_configure(tmp, &global_jbconf); 00803 if (state != AST_STATE_DOWN) { 00804 if (ast_pbx_start(tmp)) { 00805 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name); 00806 ast_hangup(tmp); 00807 tmp = NULL; 00808 } 00809 } 00810 00811 return tmp; 00812 }
| static struct ast_frame * alsa_read | ( | struct ast_channel * | chan | ) | [static] |
Definition at line 652 of file chan_alsa.c.
References ast_channel::_state, alsa, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, f, FRAME_SIZE, chan_alsa_pvt::icard, and LOG_ERROR.
00653 { 00654 static struct ast_frame f; 00655 static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2]; 00656 short *buf; 00657 static int readpos = 0; 00658 static int left = FRAME_SIZE; 00659 snd_pcm_state_t state; 00660 int r = 0; 00661 int off = 0; 00662 00663 ast_mutex_lock(&alsalock); 00664 /* Acknowledge any pending cmd */ 00665 f.frametype = AST_FRAME_NULL; 00666 f.subclass = 0; 00667 f.samples = 0; 00668 f.datalen = 0; 00669 f.data = NULL; 00670 f.offset = 0; 00671 f.src = "Console"; 00672 f.mallocd = 0; 00673 f.delivery.tv_sec = 0; 00674 f.delivery.tv_usec = 0; 00675 00676 state = snd_pcm_state(alsa.icard); 00677 if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) { 00678 snd_pcm_prepare(alsa.icard); 00679 } 00680 00681 buf = __buf + AST_FRIENDLY_OFFSET / 2; 00682 00683 r = snd_pcm_readi(alsa.icard, buf + readpos, left); 00684 if (r == -EPIPE) { 00685 #if DEBUG 00686 ast_log(LOG_ERROR, "XRUN read\n"); 00687 #endif 00688 snd_pcm_prepare(alsa.icard); 00689 } else if (r == -ESTRPIPE) { 00690 ast_log(LOG_ERROR, "-ESTRPIPE\n"); 00691 snd_pcm_prepare(alsa.icard); 00692 } else if (r < 0) { 00693 ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r)); 00694 } else if (r >= 0) { 00695 off -= r; 00696 } 00697 /* Update positions */ 00698 readpos += r; 00699 left -= r; 00700 00701 if (readpos >= FRAME_SIZE) { 00702 /* A real frame */ 00703 readpos = 0; 00704 left = FRAME_SIZE; 00705 if (chan->_state != AST_STATE_UP) { 00706 /* Don't transmit unless it's up */ 00707 ast_mutex_unlock(&alsalock); 00708 return &f; 00709 } 00710 f.frametype = AST_FRAME_VOICE; 00711 f.subclass = AST_FORMAT_SLINEAR; 00712 f.samples = FRAME_SIZE; 00713 f.datalen = FRAME_SIZE * 2; 00714 f.data = buf; 00715 f.offset = AST_FRIENDLY_OFFSET; 00716 f.src = "Console"; 00717 f.mallocd = 0; 00718 #ifdef ALSA_MONITOR 00719 alsa_monitor_read((char *) buf, FRAME_SIZE * 2); 00720 #endif 00721 00722 } 00723 ast_mutex_unlock(&alsalock); 00724 return &f; 00725 }
| static struct ast_channel * alsa_request | ( | const char * | type, | |
| int | format, | |||
| void * | data, | |||
| int * | cause | |||
| ) | [static] |
Definition at line 814 of file chan_alsa.c.
References alsa, alsa_new(), AST_CAUSE_BUSY, AST_FORMAT_SLINEAR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::owner.
00815 { 00816 int oldformat = format; 00817 struct ast_channel *tmp = NULL; 00818 00819 format &= AST_FORMAT_SLINEAR; 00820 if (!format) { 00821 ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat); 00822 return NULL; 00823 } 00824 00825 ast_mutex_lock(&alsalock); 00826 00827 if (alsa.owner) { 00828 ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n"); 00829 *cause = AST_CAUSE_BUSY; 00830 } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN))) 00831 ast_log(LOG_WARNING, "Unable to create new ALSA channel\n"); 00832 00833 ast_mutex_unlock(&alsalock); 00834 00835 return tmp; 00836 }
| static int alsa_text | ( | struct ast_channel * | c, | |
| const char * | text | |||
| ) | [static] |
Definition at line 498 of file chan_alsa.c.
References ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().
00499 { 00500 ast_mutex_lock(&alsalock); 00501 ast_verbose(" << Console Received text %s >> \n", text); 00502 ast_mutex_unlock(&alsalock); 00503 return 0; 00504 }
| static int alsa_write | ( | struct ast_channel * | chan, | |
| struct ast_frame * | f | |||
| ) | [static] |
Definition at line 587 of file chan_alsa.c.
References alsa, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::ocard.
00588 { 00589 static char sizbuf[8000]; 00590 static int sizpos = 0; 00591 int len = sizpos; 00592 int pos; 00593 int res = 0; 00594 /* size_t frames = 0; */ 00595 snd_pcm_state_t state; 00596 00597 /* Immediately return if no sound is enabled */ 00598 if (nosound) 00599 return 0; 00600 00601 ast_mutex_lock(&alsalock); 00602 /* Stop any currently playing sound */ 00603 if (cursound != -1) { 00604 snd_pcm_drop(alsa.ocard); 00605 snd_pcm_prepare(alsa.ocard); 00606 cursound = -1; 00607 } 00608 00609 00610 /* We have to digest the frame in 160-byte portions */ 00611 if (f->datalen > sizeof(sizbuf) - sizpos) { 00612 ast_log(LOG_WARNING, "Frame too large\n"); 00613 res = -1; 00614 } else { 00615 memcpy(sizbuf + sizpos, f->data, f->datalen); 00616 len += f->datalen; 00617 pos = 0; 00618 #ifdef ALSA_MONITOR 00619 alsa_monitor_write(sizbuf, len); 00620 #endif 00621 state = snd_pcm_state(alsa.ocard); 00622 if (state == SND_PCM_STATE_XRUN) 00623 snd_pcm_prepare(alsa.ocard); 00624 res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2); 00625 if (res == -EPIPE) { 00626 #if DEBUG 00627 ast_log(LOG_DEBUG, "XRUN write\n"); 00628 #endif 00629 snd_pcm_prepare(alsa.ocard); 00630 res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2); 00631 if (res != len / 2) { 00632 ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res)); 00633 res = -1; 00634 } else if (res < 0) { 00635 ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res)); 00636 res = -1; 00637 } 00638 } else { 00639 if (res == -ESTRPIPE) 00640 ast_log(LOG_ERROR, "You've got some big problems\n"); 00641 else if (res < 0) 00642 ast_log(LOG_NOTICE, "Error %d on write\n", res); 00643 } 00644 } 00645 ast_mutex_unlock(&alsalock); 00646 if (res > 0) 00647 res = 0; 00648 return res; 00649 }
| static void answer_sound | ( | void | ) | [static] |
Definition at line 543 of file chan_alsa.c.
Referenced by alsa_answer(), console_answer(), and console_answer_deprecated().
00544 { 00545 int res; 00546 nosound = 1; 00547 res = 4; 00548 write(sndcmd[1], &res, sizeof(res)); 00549 00550 }
| AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
| "ALSA Console Channel Driver" | ||||
| ) |
| AST_MUTEX_DEFINE_STATIC | ( | alsalock | ) |
| static char* autoanswer_complete | ( | const char * | line, | |
| const char * | word, | |||
| int | pos, | |||
| int | state | |||
| ) | [static] |
Definition at line 883 of file chan_alsa.c.
References ast_strdup, ast_strlen_zero(), and MIN.
00884 { 00885 #ifndef MIN 00886 #define MIN(a,b) ((a) < (b) ? (a) : (b)) 00887 #endif 00888 switch (state) { 00889 case 0: 00890 if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2))) 00891 return ast_strdup("on"); 00892 case 1: 00893 if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3))) 00894 return ast_strdup("off"); 00895 default: 00896 return NULL; 00897 } 00898 return NULL; 00899 }
| static int console_answer | ( | int | fd, | |
| int | argc, | |||
| char * | argv[] | |||
| ) | [static] |
Definition at line 939 of file chan_alsa.c.
References alsa, 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.
00940 { 00941 int res = RESULT_SUCCESS; 00942 00943 if (argc != 2) 00944 return RESULT_SHOWUSAGE; 00945 00946 ast_mutex_lock(&alsalock); 00947 00948 if (!alsa.owner) { 00949 ast_cli(fd, "No one is calling us\n"); 00950 res = RESULT_FAILURE; 00951 } else { 00952 hookstate = 1; 00953 cursound = -1; 00954 grab_owner(); 00955 if (alsa.owner) { 00956 struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00957 ast_queue_frame(