Thu May 14 15:13:16 2009

Asterisk developer's documentation


chan_alsa.c File Reference

ALSA sound card channel driver. More...

#include "asterisk.h"
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <alsa/asoundlib.h>
#include "asterisk/frame.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/endian.h"
#include "asterisk/stringfields.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/musiconhold.h"
#include "busy_tone.h"
#include "ring_tone.h"
#include "ring10.h"
#include "answer.h"

Go to the source code of this file.

Data Structures

struct  chan_alsa_pvt
struct  sound

Defines

#define ALSA_INDEV   "default"
#define ALSA_OUTDEV   "default"
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#define BUFFER_FMT   ((buffersize * 10) << 16) | (0x0006);
#define DEBUG   0
#define DESIRED_RATE   8000
#define FRAME_SIZE   160
#define MAX_BUFFER_SIZE   100
#define MIN(a, b)   ((a) < (b) ? (a) : (b))
#define MIN_SWITCH_TIME   600
#define PERIOD_FRAMES   80

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int alsa_answer (struct ast_channel *c)
static int alsa_call (struct ast_channel *c, char *dest, int timeout)
static snd_pcm_t * alsa_card_init (char *dev, snd_pcm_stream_t stream)
static int alsa_digit (struct ast_channel *c, char digit, unsigned int duration)
static int alsa_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int alsa_hangup (struct ast_channel *c)
static int alsa_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen)
static struct ast_channelalsa_new (struct chan_alsa_pvt *p, int state)
static struct ast_framealsa_read (struct ast_channel *chan)
static struct ast_channelalsa_request (const char *type, int format, void *data, int *cause)
static int alsa_text (struct ast_channel *c, const char *text)
static int alsa_write (struct ast_channel *chan, struct ast_frame *f)
static void answer_sound (void)
static char * autoanswer_complete (const char *line, const char *word, int pos, int state)
static int console_answer (int fd, int argc, char *argv[])
static int console_answer_deprecated (int fd, int argc, char *argv[])
static int console_autoanswer (int fd, int argc, char *argv[])
static int console_autoanswer_deprecated (int fd, int argc, char *argv[])
static int console_dial (int fd, int argc, char *argv[])
static int console_dial_deprecated (int fd, int argc, char *argv[])
static int console_hangup (int fd, int argc, char *argv[])
static int console_hangup_deprecated (int fd, int argc, char *argv[])
static int console_sendtext (int fd, int argc, char *argv[])
static int console_sendtext_deprecated (int fd, int argc, char *argv[])
static void grab_owner (void)
static int load_module (void)
static int send_sound (void)
static void * sound_thread (void *unused)
static int soundcard_init (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ALSA Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, }
static struct chan_alsa_pvt alsa
static struct ast_channel_tech alsa_tech
static ast_mutex_t alsalock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char answer_usage []
static const struct ast_module_infoast_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


Detailed Description

ALSA sound card channel driver.

Author:
Matthew Fredrickson <creslin@digium.com>
See also

Definition in file chan_alsa.c.


Define Documentation

#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

Definition at line 88 of file chan_alsa.c.

Referenced by alsa_card_init().

#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,
 )     ((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

Definition at line 92 of file chan_alsa.c.

Referenced by alsa_card_init().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1391 of file chan_alsa.c.

static void __unreg_module ( void   )  [static]

Definition at line 1391 of file chan_alsa.c.

static int alsa_answer ( struct ast_channel c  )  [static]

Definition at line 560 of file chan_alsa.c.

References alsa, alsalock, answer_sound(), ast_mutex_lock(), ast_mutex_unlock(), ast_setstate(), AST_STATE_UP, ast_verbose(), and chan_alsa_pvt::icard.

00561 {
00562    ast_mutex_lock(&alsalock);
00563    ast_verbose(" << Console call has been answered >> \n");
00564    answer_sound();
00565    ast_setstate(c, AST_STATE_UP);
00566    cursound = -1;
00567    snd_pcm_prepare(alsa.icard);
00568    snd_pcm_start(alsa.icard);
00569    ast_mutex_unlock(&alsalock);
00570    return 0;
00571 }

static int alsa_call ( struct ast_channel c,
char *  dest,
int  timeout 
) [static]

Definition at line 517 of file chan_alsa.c.

References alsa, alsalock, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_verbose(), errno, f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, LOG_WARNING, and chan_alsa_pvt::owner.

00518 {
00519    int res = 3;
00520    struct ast_frame f = { AST_FRAME_CONTROL };
00521    ast_mutex_lock(&alsalock);
00522    ast_verbose(" << Call placed to '%s' on console >> \n", dest);
00523    if (autoanswer) {
00524       ast_verbose(" << Auto-answered >> \n");
00525       grab_owner();
00526       if (alsa.owner) {
00527          f.subclass = AST_CONTROL_ANSWER;
00528          ast_queue_frame(alsa.owner, &f);
00529          ast_mutex_unlock(&alsa.owner->lock);
00530       }
00531    } else {
00532       ast_verbose(" << Type 'answer' to answer, or use 'autoanswer' for future calls >> \n");
00533       grab_owner();
00534       if (alsa.owner) {
00535          f.subclass = AST_CONTROL_RINGING;
00536          ast_queue_frame(alsa.owner, &f);
00537          ast_mutex_unlock(&alsa.owner->lock);
00538       }
00539       if (write(sndcmd[1], &res, sizeof(res)) < 0) {
00540          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00541       }
00542    }
00543    snd_pcm_prepare(alsa.icard);
00544    snd_pcm_start(alsa.icard);
00545    ast_mutex_unlock(&alsalock);
00546    return 0;
00547 }

static snd_pcm_t* alsa_card_init ( char *  dev,
snd_pcm_stream_t  stream 
) [static]

Definition at line 347 of file chan_alsa.c.

References ast_log(), DESIRED_RATE, pollfd::fd, LOG_DEBUG, LOG_ERROR, LOG_WARNING, and PERIOD_FRAMES.

Referenced by soundcard_init().

00348 {
00349    int err;
00350    int direction;
00351    snd_pcm_t *handle = NULL;
00352    snd_pcm_hw_params_t *hwparams = NULL;
00353    snd_pcm_sw_params_t *swparams = NULL;
00354    struct pollfd pfd;
00355    snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4;
00356    /* int period_bytes = 0; */
00357    snd_pcm_uframes_t buffer_size = 0;
00358 
00359    unsigned int rate = DESIRED_RATE;
00360 #if 0
00361    unsigned int per_min = 1;
00362 #endif
00363    /* unsigned int per_max = 8; */
00364    snd_pcm_uframes_t start_threshold, stop_threshold;
00365 
00366    err = snd_pcm_open(&handle, dev, stream, SND_PCM_NONBLOCK);
00367    if (err < 0) {
00368       ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err));
00369       return NULL;
00370    } else
00371       ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write");
00372 
00373    hwparams = alloca(snd_pcm_hw_params_sizeof());
00374    memset(hwparams, 0, snd_pcm_hw_params_sizeof());
00375    snd_pcm_hw_params_any(handle, hwparams);
00376 
00377    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
00378    if (err < 0)
00379       ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err));
00380 
00381    err = snd_pcm_hw_params_set_format(handle, hwparams, format);
00382    if (err < 0)
00383       ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err));
00384 
00385    err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
00386    if (err < 0)
00387       ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err));
00388 
00389    direction = 0;
00390    err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction);
00391    if (rate != DESIRED_RATE)
00392       ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate);
00393 
00394    direction = 0;
00395    err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction);
00396    if (err < 0)
00397       ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err));
00398    else
00399       ast_log(LOG_DEBUG, "Period size is %d\n", err);
00400 
00401    buffer_size = 4096 * 2;    /* period_size * 16; */
00402    err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
00403    if (err < 0)
00404       ast_log(LOG_WARNING, "Problem setting buffer size of %ld: %s\n", buffer_size, snd_strerror(err));
00405    else
00406       ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err);
00407 
00408 #if 0
00409    direction = 0;
00410    err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction);
00411    if (err < 0)
00412       ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err));
00413 
00414    err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0);
00415    if (err < 0)
00416       ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err));
00417 #endif
00418 
00419    err = snd_pcm_hw_params(handle, hwparams);
00420    if (err < 0)
00421       ast_log(LOG_ERROR, "Couldn't set the new hw params: %s\n", snd_strerror(err));
00422 
00423    swparams = alloca(snd_pcm_sw_params_sizeof());
00424    memset(swparams, 0, snd_pcm_sw_params_sizeof());
00425    snd_pcm_sw_params_current(handle, swparams);
00426 
00427 #if 1
00428    if (stream == SND_PCM_STREAM_PLAYBACK)
00429       start_threshold = period_size;
00430    else
00431       start_threshold = 1;
00432 
00433    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
00434    if (err < 0)
00435       ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err));
00436 #endif
00437 
00438 #if 1
00439    if (stream == SND_PCM_STREAM_PLAYBACK)
00440       stop_threshold = buffer_size;
00441    else
00442       stop_threshold = buffer_size;
00443 
00444    err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
00445    if (err < 0)
00446       ast_log(LOG_ERROR, "stop threshold: %s\n", snd_strerror(err));
00447 #endif
00448 #if 0
00449    err = snd_pcm_sw_params_set_xfer_align(handle, swparams, PERIOD_FRAMES);
00450    if (err < 0)
00451       ast_log(LOG_ERROR, "Unable to set xfer alignment: %s\n", snd_strerror(err));
00452 #endif
00453 
00454 #if 0
00455    err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold);
00456    if (err < 0)
00457       ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err));
00458 #endif
00459    err = snd_pcm_sw_params(handle, swparams);
00460    if (err < 0)
00461       ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err));
00462 
00463    err = snd_pcm_poll_descriptors_count(handle);
00464    if (err <= 0)
00465       ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
00466    if (err != 1)
00467       ast_log(LOG_DEBUG, "Can't handle more than one device\n");
00468 
00469    snd_pcm_poll_descriptors(handle, &pfd, err);
00470    ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd);
00471 
00472    if (stream == SND_PCM_STREAM_CAPTURE)
00473       readdev = pfd.fd;
00474    else
00475       writedev = pfd.fd;
00476 
00477    return handle;
00478 }

static int alsa_digit ( struct ast_channel c,
char  digit,
unsigned int  duration 
) [static]

Definition at line 493 of file chan_alsa.c.

References alsalock, ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().

00494 {
00495    ast_mutex_lock(&alsalock);
00496    ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
00497       digit, duration);
00498    ast_mutex_unlock(&alsalock);
00499    return 0;
00500 }

static int alsa_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 741 of file chan_alsa.c.

References alsalock, ast_mutex_lock(), ast_mutex_unlock(), chan_alsa_pvt::owner, and ast_channel::tech_pvt.

00742 {
00743    struct chan_alsa_pvt *p = newchan->tech_pvt;
00744    ast_mutex_lock(&alsalock);
00745    p->owner = newchan;
00746    ast_mutex_unlock(&alsalock);
00747    return 0;
00748 }

static int alsa_hangup ( struct ast_channel c  )  [static]

Definition at line 573 of file chan_alsa.c.

References alsa, alsalock, ast_log(), ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, chan_alsa_pvt::icard, LOG_WARNING, chan_alsa_pvt::owner, and ast_channel::tech_pvt.

00574 {
00575    int res;
00576    ast_mutex_lock(&alsalock);
00577    cursound = -1;
00578    c->tech_pvt = NULL;
00579    alsa.owner = NULL;
00580    ast_verbose(" << Hangup on console >> \n");
00581    ast_module_unref(ast_module_info->self);
00582    if (hookstate) {
00583       hookstate = 0;
00584       if (!autoanswer) {
00585          /* Congestion noise */
00586          res = 2;
00587          if (write(sndcmd[1], &res, sizeof(res)) < 0) {
00588             ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00589          }
00590       }
00591    }
00592    snd_pcm_drop(alsa.icard);
00593    ast_mutex_unlock(&alsalock);
00594    return 0;
00595 }

static int alsa_indicate ( struct ast_channel chan,
int  cond,
const void *  data,
size_t  datalen 
) [static]

Definition at line 750 of file chan_alsa.c.

References alsalock, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), errno, LOG_WARNING, and ast_channel::name.

00751 {
00752    int res = 0;
00753 
00754    ast_mutex_lock(&alsalock);
00755 
00756    switch (cond) {
00757    case AST_CONTROL_BUSY:
00758       res = 1;
00759       break;
00760    case AST_CONTROL_CONGESTION:
00761       res = 2;
00762       break;
00763    case AST_CONTROL_RINGING:
00764    case AST_CONTROL_PROGRESS:
00765       break;
00766    case -1:
00767       res = -1;
00768       break;
00769    case AST_CONTROL_VIDUPDATE:
00770       res = -1;
00771       break;
00772    case AST_CONTROL_HOLD:
00773       ast_verbose(" << Console Has Been Placed on Hold >> \n");
00774       ast_moh_start(chan, data, mohinterpret);
00775       break;
00776    case AST_CONTROL_UNHOLD:
00777       ast_verbose(" << Console Has Been Retrieved from Hold >> \n");
00778       ast_moh_stop(chan);
00779       break;
00780    case AST_CONTROL_SRCUPDATE:
00781       break;
00782    default:
00783       ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", cond, chan->name);
00784       res = -1;
00785    }
00786 
00787    if (res > -1) {
00788       if (write(sndcmd[1], &res, sizeof(res)) < 0) {
00789          ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00790       }
00791    }
00792 
00793    ast_mutex_unlock(&alsalock);
00794 
00795    return res;
00796 }

static struct ast_channel* alsa_new ( struct chan_alsa_pvt p,
int  state 
) [static]

Definition at line 798 of file chan_alsa.c.

References alsa_tech, ast_channel_alloc(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_pbx_start(), AST_STATE_DOWN, ast_string_field_set, ast_strlen_zero(), ast_channel::context, chan_alsa_pvt::context, ast_channel::exten, chan_alsa_pvt::exten, ast_channel::fds, global_jbconf, LOG_WARNING, ast_channel::nativeformats, chan_alsa_pvt::owner, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by alsa_request(), console_dial(), and console_dial_deprecated().

00799 {
00800    struct ast_channel *tmp = NULL;
00801    
00802    if (!(tmp = ast_channel_alloc(1, state, 0, 0, "", p->exten, p->context, 0, "ALSA/%s", indevname)))
00803       return NULL;
00804 
00805    tmp->tech = &alsa_tech;
00806    tmp->fds[0] = readdev;
00807    tmp->nativeformats = AST_FORMAT_SLINEAR;
00808    tmp->readformat = AST_FORMAT_SLINEAR;
00809    tmp->writeformat = AST_FORMAT_SLINEAR;
00810    tmp->tech_pvt = p;
00811    if (!ast_strlen_zero(p->context))
00812       ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
00813    if (!ast_strlen_zero(p->exten))
00814       ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten));
00815    if (!ast_strlen_zero(language))
00816       ast_string_field_set(tmp, language, language);
00817    p->owner = tmp;
00818    ast_module_ref(ast_module_info->self);
00819    ast_jb_configure(tmp, &global_jbconf);
00820    if (state != AST_STATE_DOWN) {
00821       if (ast_pbx_start(tmp)) {
00822          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
00823          ast_hangup(tmp);
00824          tmp = NULL;
00825       }
00826    }
00827 
00828    return tmp;
00829 }

static struct ast_frame * alsa_read ( struct ast_channel chan  )  [static]

Definition at line 666 of file chan_alsa.c.

References ast_channel::_state, alsa, alsalock, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, f, FRAME_SIZE, chan_alsa_pvt::icard, and LOG_ERROR.

00667 {
00668    static struct ast_frame f;
00669    static short __buf[FRAME_SIZE + AST_FRIENDLY_OFFSET / 2];
00670    short *buf;
00671    static int readpos = 0;
00672    static int left = FRAME_SIZE;
00673    snd_pcm_state_t state;
00674    int r = 0;
00675    int off = 0;
00676 
00677    ast_mutex_lock(&alsalock);
00678    /* Acknowledge any pending cmd */
00679    f.frametype = AST_FRAME_NULL;
00680    f.subclass = 0;
00681    f.samples = 0;
00682    f.datalen = 0;
00683    f.data = NULL;
00684    f.offset = 0;
00685    f.src = "Console";
00686    f.mallocd = 0;
00687    f.delivery.tv_sec = 0;
00688    f.delivery.tv_usec = 0;
00689 
00690    state = snd_pcm_state(alsa.icard);
00691    if ((state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING)) {
00692       snd_pcm_prepare(alsa.icard);
00693    }
00694 
00695    buf = __buf + AST_FRIENDLY_OFFSET / 2;
00696 
00697    r = snd_pcm_readi(alsa.icard, buf + readpos, left);
00698    if (r == -EPIPE) {
00699 #if DEBUG
00700       ast_log(LOG_ERROR, "XRUN read\n");
00701 #endif
00702       snd_pcm_prepare(alsa.icard);
00703    } else if (r == -ESTRPIPE) {
00704       ast_log(LOG_ERROR, "-ESTRPIPE\n");
00705       snd_pcm_prepare(alsa.icard);
00706    } else if (r < 0) {
00707       ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
00708    } else if (r >= 0) {
00709       off -= r;
00710    }
00711    /* Update positions */
00712    readpos += r;
00713    left -= r;
00714 
00715    if (readpos >= FRAME_SIZE) {
00716       /* A real frame */
00717       readpos = 0;
00718       left = FRAME_SIZE;
00719       if (chan->_state != AST_STATE_UP) {
00720          /* Don't transmit unless it's up */
00721          ast_mutex_unlock(&alsalock);
00722          return &f;
00723       }
00724       f.frametype = AST_FRAME_VOICE;
00725       f.subclass = AST_FORMAT_SLINEAR;
00726       f.samples = FRAME_SIZE;
00727       f.datalen = FRAME_SIZE * 2;
00728       f.data = buf;
00729       f.offset = AST_FRIENDLY_OFFSET;
00730       f.src = "Console";
00731       f.mallocd = 0;
00732 #ifdef ALSA_MONITOR
00733       alsa_monitor_read((char *) buf, FRAME_SIZE * 2);
00734 #endif
00735 
00736    }
00737    ast_mutex_unlock(&alsalock);
00738    return &f;
00739 }

static struct ast_channel * alsa_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static]

Definition at line 831 of file chan_alsa.c.

References alsa, alsa_new(), alsalock, AST_CAUSE_BUSY, AST_FORMAT_SLINEAR, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_DOWN, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::owner.

00832 {
00833    int oldformat = format;
00834    struct ast_channel *tmp = NULL;
00835 
00836    format &= AST_FORMAT_SLINEAR;
00837    if (!format) {
00838       ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
00839       return NULL;
00840    }
00841 
00842    ast_mutex_lock(&alsalock);
00843 
00844    if (alsa.owner) {
00845       ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");
00846       *cause = AST_CAUSE_BUSY;
00847    } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN)))
00848       ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");
00849 
00850    ast_mutex_unlock(&alsalock);
00851 
00852    return tmp;
00853 }

static int alsa_text ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 502 of file chan_alsa.c.

References alsalock, ast_mutex_lock(), ast_mutex_unlock(), and ast_verbose().

00503 {
00504    ast_mutex_lock(&alsalock);
00505    ast_verbose(" << Console Received text %s >> \n", text);
00506    ast_mutex_unlock(&alsalock);
00507    return 0;
00508 }

static int alsa_write ( struct ast_channel chan,
struct ast_frame f 
) [static]

Definition at line 597 of file chan_alsa.c.

References alsa, alsalock, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), f, len(), LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::ocard.

00598 {
00599    static char sizbuf[8000];
00600    static int sizpos = 0;
00601    int len = sizpos;
00602    int pos;
00603    int res = 0;
00604    /* size_t frames = 0; */
00605    snd_pcm_state_t state;
00606 
00607    /* Immediately return if no sound is enabled */
00608    if (nosound)
00609       return 0;
00610 
00611    ast_mutex_lock(&alsalock);
00612    /* Stop any currently playing sound */
00613    if (cursound != -1) {
00614       snd_pcm_drop(alsa.ocard);
00615       snd_pcm_prepare(alsa.ocard);
00616       cursound = -1;
00617    }
00618 
00619 
00620    /* We have to digest the frame in 160-byte portions */
00621    if (f->datalen > sizeof(sizbuf) - sizpos) {
00622       ast_log(LOG_WARNING, "Frame too large\n");
00623       res = -1;
00624    } else {
00625       memcpy(sizbuf + sizpos, f->data, f->datalen);
00626       len += f->datalen;
00627       pos = 0;
00628 #ifdef ALSA_MONITOR
00629       alsa_monitor_write(sizbuf, len);
00630 #endif
00631       state = snd_pcm_state(alsa.ocard);
00632       if (state == SND_PCM_STATE_XRUN)
00633          snd_pcm_prepare(alsa.ocard);
00634       while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
00635          usleep(1);
00636       }
00637       if (res == -EPIPE) {
00638 #if DEBUG
00639          ast_log(LOG_DEBUG, "XRUN write\n");
00640 #endif
00641          snd_pcm_prepare(alsa.ocard);
00642          while ((res = snd_pcm_writei(alsa.ocard, sizbuf, len / 2)) == -EAGAIN) {
00643             usleep(1);
00644          }
00645          if (res != len / 2) {
00646             ast_log(LOG_ERROR, "Write error: %s\n", snd_strerror(res));
00647             res = -1;
00648          } else if (res < 0) {
00649             ast_log(LOG_ERROR, "Write error %s\n", snd_strerror(res));
00650             res = -1;
00651          }
00652       } else {
00653          if (res == -ESTRPIPE)
00654             ast_log(LOG_ERROR, "You've got some big problems\n");
00655          else if (res < 0)
00656             ast_log(LOG_NOTICE, "Error %d on write\n", res);
00657       }
00658    }
00659    ast_mutex_unlock(&alsalock);
00660    if (res > 0)
00661       res = 0;
00662    return res;
00663 }

static void answer_sound ( void   )  [static]

Definition at line 549 of file chan_alsa.c.

References ast_log(), errno, and LOG_WARNING.

Referenced by alsa_answer(), console_answer(), and console_answer_deprecated().

00550 {
00551    int res;
00552 
00553    nosound = 1;
00554    res = 4;
00555    if (write(sndcmd[1], &res, sizeof(res)) < 0) {
00556       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00557    }
00558 }

static char* autoanswer_complete ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 900 of file chan_alsa.c.

References ast_strdup, ast_strlen_zero(), and MIN.

00901 {
00902 #ifndef MIN
00903 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00904 #endif
00905    switch (state) {
00906       case 0:
00907          if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
00908             return ast_strdup("on");
00909       case 1:
00910          if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
00911             return ast_strdup("off");
00912       default:
00913          return NULL;
00914    }
00915    return NULL;
00916 }

static int console_answer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 956 of file chan_alsa.c.

References alsa, alsalock, answer_sound(), ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00957 {
00958    int res = RESULT_SUCCESS;
00959 
00960    if (argc != 2)
00961       return RESULT_SHOWUSAGE;
00962 
00963    ast_mutex_lock(&alsalock);
00964 
00965    if (!alsa.owner) {
00966       ast_cli(fd, "No one is calling us\n");
00967       res = RESULT_FAILURE;
00968    } else {
00969       hookstate = 1;
00970       cursound = -1;
00971       grab_owner();
00972       if (alsa.owner) {
00973          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00974          ast_queue_frame(alsa.owner, &f);
00975          ast_mutex_unlock(&alsa.owner->lock);
00976       }
00977       answer_sound();
00978    }
00979 
00980    snd_pcm_prepare(alsa.icard);
00981    snd_pcm_start(alsa.icard);
00982 
00983    ast_mutex_unlock(&alsalock);
00984 
00985    return RESULT_SUCCESS;
00986 }

static int console_answer_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 924 of file chan_alsa.c.

References alsa, alsalock, answer_sound(), ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00925 {
00926    int res = RESULT_SUCCESS;
00927 
00928    if (argc != 1)
00929       return RESULT_SHOWUSAGE;
00930 
00931    ast_mutex_lock(&alsalock);
00932 
00933    if (!alsa.owner) {
00934       ast_cli(fd, "No one is calling us\n");
00935       res = RESULT_FAILURE;
00936    } else {
00937       hookstate = 1;
00938       cursound = -1;
00939       grab_owner();
00940       if (alsa.owner) {
00941          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00942          ast_queue_frame(alsa.owner, &f);
00943          ast_mutex_unlock(&alsa.owner->lock);
00944       }
00945       answer_sound();
00946    }
00947 
00948    snd_pcm_prepare(alsa.icard);
00949    snd_pcm_start(alsa.icard);
00950 
00951    ast_mutex_unlock(&alsalock);
00952 
00953    return RESULT_SUCCESS;
00954 }

static int console_autoanswer ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 880 of file chan_alsa.c.

References alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00881 {
00882    int res = RESULT_SUCCESS;;
00883    if ((argc != 2) && (argc != 3))
00884       return RESULT_SHOWUSAGE;
00885    ast_mutex_lock(&alsalock);
00886    if (argc == 2) {
00887       ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
00888    } else {
00889       if (!strcasecmp(argv[2], "on"))
00890          autoanswer = -1;
00891       else if (!strcasecmp(argv[2], "off"))
00892          autoanswer = 0;
00893       else
00894          res = RESULT_SHOWUSAGE;
00895    }
00896    ast_mutex_unlock(&alsalock);
00897    return res;
00898 }

static int console_autoanswer_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 855 of file chan_alsa.c.

References alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00856 {
00857    int res = RESULT_SUCCESS;
00858 
00859    if ((argc != 1) && (argc != 2))
00860       return RESULT_SHOWUSAGE;
00861 
00862    ast_mutex_lock(&alsalock);
00863 
00864    if (argc == 1) {
00865       ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
00866    } else {
00867       if (!strcasecmp(argv[1], "on"))
00868          autoanswer = -1;
00869       else if (!strcasecmp(argv[1], "off"))
00870          autoanswer = 0;
00871       else
00872          res = RESULT_SHOWUSAGE;
00873    }
00874 
00875    ast_mutex_unlock(&alsalock);
00876 
00877    return res;
00878 }

static int console_dial ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1195 of file chan_alsa.c.

References alsa, alsa_new(), alsalock, ast_cli(), ast_copy_string(), ast_exists_extension(), AST_FRAME_DTMF, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), AST_STATE_RINGING, ast_strlen_zero(), chan_alsa_pvt::context, chan_alsa_pvt::exten, f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01196 {
01197    char tmp[256], *tmp2;
01198    char *mye, *myc;
01199    char *d;
01200    int res = RESULT_SUCCESS;
01201 
01202    if ((argc != 2) && (argc != 3))
01203       return RESULT_SHOWUSAGE;
01204 
01205    ast_mutex_lock(&alsalock);
01206 
01207    if (alsa.owner) {
01208       if (argc == 3) {
01209          d = argv[2];
01210          grab_owner();
01211          if (alsa.owner) {
01212             struct ast_frame f = { AST_FRAME_DTMF };
01213             while (*d) {
01214                f.subclass = *d;
01215                ast_queue_frame(alsa.owner, &f);
01216                d++;
01217             }
01218             ast_mutex_unlock(&alsa.owner->lock);
01219          }
01220       } else {
01221          ast_cli(fd, "You're already in a call.  You can use this only to dial digits until you hangup\n");
01222          res = RESULT_FAILURE;
01223       }
01224    } else {
01225       mye = exten;
01226       myc = context;
01227       if (argc == 3) {
01228          char *stringp = NULL;
01229          ast_copy_string(tmp, argv[2], sizeof(tmp));
01230          stringp = tmp;
01231          strsep(&stringp, "@");
01232          tmp2 = strsep(&stringp, "@");
01233          if (!ast_strlen_zero(tmp))
01234             mye = tmp;
01235          if (!ast_strlen_zero(tmp2))
01236             myc = tmp2;
01237       }
01238       if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
01239          ast_copy_string(alsa.exten, mye, sizeof(alsa.exten));
01240          ast_copy_string(alsa.context, myc, sizeof(alsa.context));
01241          hookstate = 1;
01242          alsa_new(&alsa, AST_STATE_RINGING);
01243       } else
01244          ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
01245    }
01246 
01247    ast_mutex_unlock(&alsalock);
01248 
01249    return res;
01250 }

static int console_dial_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1138 of file chan_alsa.c.

References alsa, alsa_new(), alsalock, ast_cli(), ast_copy_string(), ast_exists_extension(), AST_FRAME_DTMF, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), AST_STATE_RINGING, ast_strlen_zero(), chan_alsa_pvt::context, chan_alsa_pvt::exten, f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01139 {
01140    char tmp[256], *tmp2;
01141    char *mye, *myc;
01142    char *d;
01143    int res = RESULT_SUCCESS;
01144 
01145    if ((argc != 1) && (argc != 2))
01146       return RESULT_SHOWUSAGE;
01147 
01148    ast_mutex_lock(&alsalock);
01149 
01150    if (alsa.owner) {
01151       if (argc == 2) {
01152          d = argv[1];
01153          grab_owner();
01154          if (alsa.owner) {
01155             struct ast_frame f = { AST_FRAME_DTMF };
01156             while (*d) {
01157                f.subclass = *d;
01158                ast_queue_frame(alsa.owner, &f);
01159                d++;
01160             }
01161             ast_mutex_unlock(&alsa.owner->lock);
01162          }
01163       } else {
01164          ast_cli(fd, "You're already in a call.  You can use this only to dial digits until you hangup\n");
01165          res = RESULT_FAILURE;
01166       }
01167    } else {
01168       mye = exten;
01169       myc = context;
01170       if (argc == 2) {
01171          char *stringp = NULL;
01172          ast_copy_string(tmp, argv[1], sizeof(tmp));
01173          stringp = tmp;
01174          strsep(&stringp, "@");
01175          tmp2 = strsep(&stringp, "@");
01176          if (!ast_strlen_zero(tmp))
01177             mye = tmp;
01178          if (!ast_strlen_zero(tmp2))
01179             myc = tmp2;
01180       }
01181       if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
01182          ast_copy_string(alsa.exten, mye, sizeof(alsa.exten));
01183          ast_copy_string(alsa.context, myc, sizeof(alsa.context));
01184          hookstate = 1;
01185          alsa_new(&alsa, AST_STATE_RINGING);
01186       } else
01187          ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
01188    }
01189 
01190    ast_mutex_unlock(&alsalock);
01191 
01192    return res;
01193 }

static int console_hangup ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1106 of file chan_alsa.c.

References alsa, alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01107 {
01108    int res = RESULT_SUCCESS;
01109 
01110    if (argc != 2)
01111       return RESULT_SHOWUSAGE;
01112 
01113    cursound = -1;
01114 
01115    ast_mutex_lock(&alsalock);
01116 
01117    if (!alsa.owner && !hookstate) {
01118       ast_cli(fd, "No call to hangup up\n");
01119       res = RESULT_FAILURE;
01120    } else {
01121       hookstate = 0;
01122       grab_owner();
01123       if (alsa.owner) {
01124          ast_queue_hangup(alsa.owner);
01125          ast_mutex_unlock(&alsa.owner->lock);
01126       }
01127    }
01128 
01129    ast_mutex_unlock(&alsalock);
01130 
01131    return res;
01132 }

static int console_hangup_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1078 of file chan_alsa.c.

References alsa, alsalock, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_hangup(), grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01079 {
01080    int res = RESULT_SUCCESS;
01081 
01082    if (argc != 1)
01083       return RESULT_SHOWUSAGE;
01084 
01085    cursound = -1;
01086 
01087    ast_mutex_lock(&alsalock);
01088 
01089    if (!alsa.owner && !hookstate) {
01090       ast_cli(fd, "No call to hangup up\n");
01091       res = RESULT_FAILURE;
01092    } else {
01093       hookstate = 0;
01094       grab_owner();
01095       if (alsa.owner) {
01096          ast_queue_hangup(alsa.owner);
01097          ast_mutex_unlock(&alsa.owner->lock);
01098       }
01099    }
01100 
01101    ast_mutex_unlock(&alsalock);
01102 
01103    return res;
01104 }

static int console_sendtext ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1033 of file chan_alsa.c.

References alsa, alsalock, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

01034 {
01035    int tmparg = 3;
01036    int res = RESULT_SUCCESS;
01037 
01038    if (argc < 3)
01039       return RESULT_SHOWUSAGE;
01040 
01041    ast_mutex_lock(&alsalock);
01042 
01043    if (!alsa.owner) {
01044       ast_cli(fd, "No one is calling us\n");
01045       res = RESULT_FAILURE;
01046    } else {
01047       struct ast_frame f = { AST_FRAME_TEXT, 0 };
01048       char text2send[256] = "";
01049       text2send[0] = '\0';
01050       while (tmparg < argc) {
01051          strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
01052          strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
01053       }
01054       text2send[strlen(text2send) - 1] = '\n';
01055       f.data = text2send;
01056       f.datalen = strlen(text2send) + 1;
01057       grab_owner();
01058       if (alsa.owner) {
01059          ast_queue_frame(alsa.owner, &f);
01060          f.frametype = AST_FRAME_CONTROL;
01061          f.subclass = AST_CONTROL_ANSWER;
01062          f.data = NULL;
01063          f.datalen = 0;
01064          ast_queue_frame(alsa.owner, &f);
01065          ast_mutex_unlock(&alsa.owner->lock);
01066       }
01067    }
01068 
01069    ast_mutex_unlock(&alsalock);
01070 
01071    return res;
01072 }

static int console_sendtext_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 992 of file chan_alsa.c.

References alsa, alsalock, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), f, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00993 {
00994    int tmparg = 2;
00995    int res = RESULT_SUCCESS;
00996 
00997    if (argc < 2)
00998       return RESULT_SHOWUSAGE;
00999 
01000    ast_mutex_lock(&alsalock);
01001 
01002    if (!alsa.owner) {
01003       ast_cli(fd, "No one is calling us\n");
01004       res = RESULT_FAILURE;
01005    } else {
01006       struct ast_frame f = { AST_FRAME_TEXT, 0 };
01007       char text2send[256] = "";
01008       text2send[0] = '\0';
01009       while (tmparg < argc) {
01010          strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
01011          strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
01012       }
01013       text2send[strlen(text2send) - 1] = '\n';
01014       f.data = text2send;
01015       f.datalen = strlen(text2send) + 1;
01016       grab_owner();
01017       if (alsa.owner) {
01018          ast_queue_frame(alsa.owner, &f);
01019          f.frametype = AST_FRAME_CONTROL;
01020          f.subclass = AST_CONTROL_ANSWER;
01021          f.data = NULL;
01022          f.datalen = 0;
01023          ast_queue_frame(alsa.owner, &f);
01024          ast_mutex_unlock(&alsa.owner->lock);
01025       }
01026    }
01027 
01028    ast_mutex_unlock(&alsalock);
01029 
01030    return res;
01031 }

static void grab_owner ( void   )  [static]

Definition at line 510 of file chan_alsa.c.

References alsa, alsalock, ast_mutex_trylock(), DEADLOCK_AVOIDANCE, ast_channel::lock, and chan_alsa_pvt::owner.

Referenced by alsa_call(), console_answer(), console_answer_deprecated(), console_dial(), console_dial_deprecated(), console_hangup(), console_hangup_deprecated(), console_sendtext(), and console_sendtext_deprecated().

00511 {
00512    while (alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) {
00513       DEADLOCK_AVOIDANCE(&alsalock);
00514    }
00515 }

static int load_module ( void   )  [static]

Definition at line 1303 of file chan_alsa.c.

References alsa_tech, ast_channel_register(), ast_cli_register_multiple(), ast_config_destroy(), ast_config_load(), ast_copy_string(), ast_jb_read_conf(), ast_log(), ast_pthread_create_background, ast_true(), ast_variable_browse(), ast_verbose(), cli_alsa, default_jbconf, global_jbconf, LOG_ERROR, ast_variable::name, ast_variable::next, option_verbose, sound_thread(), soundcard_init(), ast_variable::value, and VERBOSE_PREFIX_2.

01304 {
01305    int res;
01306    struct ast_config *cfg;
01307    struct ast_variable *v;
01308 
01309    /* Copy the default jb config over global_jbconf */
01310    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
01311 
01312    strcpy(mohinterpret, "default");
01313 
01314    if ((cfg = ast_config_load(config))) {
01315       v = ast_variable_browse(cfg, "general");
01316       for (; v; v = v->next) {
01317          /* handle jb conf */
01318          if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
01319             continue;
01320 
01321          if (!strcasecmp(v->name, "autoanswer"))
01322             autoanswer = ast_true(v->value);
01323          else if (!strcasecmp(v->name, "silencesuppression"))
01324             silencesuppression = ast_true(v->value);
01325          else if (!strcasecmp(v->name, "silencethreshold"))
01326             silencethreshold = atoi(v->value);
01327          else if (!strcasecmp(v->name, "context"))
01328             ast_copy_string(context, v->value, sizeof(context));
01329          else if (!strcasecmp(v->name, "language"))
01330             ast_copy_string(language, v->value, sizeof(language));
01331          else if (!strcasecmp(v->name, "extension"))
01332             ast_copy_string(exten, v->value, sizeof(exten));
01333          else if (!strcasecmp(v->name, "input_device"))
01334             ast_copy_string(indevname, v->value, sizeof(indevname));
01335          else if (!strcasecmp(v->name, "output_device"))
01336             ast_copy_string(outdevname, v->value, sizeof(outdevname));
01337          else if (!strcasecmp(v->name, "mohinterpret"))
01338             ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
01339       }
01340       ast_config_destroy(cfg);
01341    }
01342    res = pipe(sndcmd);
01343    if (res) {
01344       ast_log(LOG_ERROR, "Unable to create pipe\n");
01345       return -1;
01346    }
01347    res = soundcard_init();
01348    if (res < 0) {
01349       if (option_verbose > 1) {
01350          ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n");
01351          ast_verbose(VERBOSE_PREFIX_2 "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
01352       }
01353       return 0;
01354    }
01355 
01356    res = ast_channel_register(&alsa_tech);
01357    if (res < 0) {
01358       ast_log(LOG_ERROR, "Unable to register channel class 'Console'\n");
01359       return -1;
01360    }
01361    ast_cli_register_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry));
01362 
01363    ast_pthread_create_background(&sthread, NULL, sound_thread, NULL);
01364 #ifdef ALSA_MONITOR
01365    if (alsa_monitor_start())
01366       ast_log(LOG_ERROR, "Problem starting Monitoring\n");
01367 #endif
01368    return 0;
01369 }

static int send_sound ( void   )  [static]

Definition at line 213 of file chan_alsa.c.

References alsa, sound::datalen, FRAME_SIZE, chan_alsa_pvt::ocard, sound::silencelen, sounds, and total.

Referenced by sound_thread().

00214 {
00215    short myframe[FRAME_SIZE];
00216    int total = FRAME_SIZE;
00217    short *frame = NULL;
00218    int amt = 0, res, myoff;
00219    snd_pcm_state_t state;
00220 
00221    if (cursound == -1)
00222       return 0;
00223    
00224    res = total;
00225    if (sampsent < sounds[cursound].samplen) {
00226       myoff = 0;
00227       while (total) {
00228          amt = total;
00229          if (amt > (sounds[cursound].datalen - offset))
00230             amt = sounds[cursound].datalen - offset;
00231          memcpy(myframe + myoff, sounds[cursound].data + offset, amt * 2);
00232          total -= amt;
00233          offset += amt;
00234          sampsent += amt;
00235          myoff += amt;
00236          if (offset >= sounds[cursound].datalen)
00237             offset = 0;
00238       }
00239       /* Set it up for silence */
00240       if (sampsent >= sounds[cursound].samplen)
00241          silencelen = sounds[cursound].silencelen;
00242       frame = myframe;
00243    } else {
00244       if (silencelen > 0) {
00245          frame = silence;
00246          silencelen -= res;
00247       } else {
00248          if (sounds[cursound].repeat) {
00249             /* Start over */
00250             sampsent = 0;
00251             offset = 0;
00252          } else {
00253             cursound = -1;
00254             nosound = 0;
00255          }
00256          return 0;
00257       }
00258    }
00259    
00260    if (res == 0 || !frame)
00261       return 0;
00262 
00263 #ifdef ALSA_MONITOR
00264    alsa_monitor_write((char *) frame, res * 2);
00265 #endif
00266    state = snd_pcm_state(alsa.ocard);
00267    if (state == SND_PCM_STATE_XRUN)
00268       snd_pcm_prepare(alsa.ocard);
00269    while ((res = snd_pcm_writei(alsa.ocard, frame, res)) == -EAGAIN) {
00270       usleep(1);
00271    }
00272    if (res > 0)
00273       return 0;
00274    return 0;
00275 }

static void* sound_thread ( void *  unused  )  [static]

Definition at line 277 of file chan_alsa.c.

References alsa, ast_log(), ast_select(), errno, FRAME_SIZE, chan_alsa_pvt::icard, LOG_ERROR, LOG_WARNING, chan_alsa_pvt::ocard, chan_alsa_pvt::owner, ast_channel_tech::read, and send_sound().

Referenced by load_module().

00278 {
00279    fd_set rfds;
00280    fd_set wfds;
00281    int max, res;
00282 
00283    for (;;) {
00284       FD_ZERO(&rfds);
00285       FD_ZERO(&wfds);
00286       max = sndcmd[0];
00287       FD_SET(sndcmd[0], &rfds);
00288       if (cursound > -1) {
00289          FD_SET(writedev, &wfds);
00290          if (writedev > max)
00291             max = writedev;
00292       }
00293 #ifdef ALSA_MONITOR
00294       if (!alsa.owner) {
00295          FD_SET(readdev, &rfds);
00296          if (readdev > max)
00297             max = readdev;
00298       }
00299 #endif
00300       res = ast_select(max + 1, &rfds, &wfds, NULL, NULL);
00301       if (res < 1) {
00302          ast_log(LOG_WARNING, "select failed: %s\n", strerror(errno));
00303          continue;
00304       }
00305 #ifdef ALSA_MONITOR
00306       if (FD_ISSET(readdev, &rfds)) {
00307          /* Keep the pipe going with read audio */
00308          snd_pcm_state_t state;
00309          short buf[FRAME_SIZE];
00310          int r;
00311 
00312          state = snd_pcm_state(alsa.ocard);
00313          if (state == SND_PCM_STATE_XRUN) {
00314             snd_pcm_prepare(alsa.ocard);
00315          }
00316          r = snd_pcm_readi(alsa.icard, buf, FRAME_SIZE);
00317          if (r == -EPIPE) {
00318 #if DEBUG
00319             ast_log(LOG_ERROR, "XRUN read\n");
00320 #endif
00321             snd_pcm_prepare(alsa.icard);
00322          } else if (r == -ESTRPIPE) {
00323             ast_log(LOG_ERROR, "-ESTRPIPE\n");
00324             snd_pcm_prepare(alsa.icard);
00325          } else if (r < 0) {
00326             ast_log(LOG_ERROR, "Read error: %s\n", snd_strerror(r));
00327          } else
00328             alsa_monitor_read((char *) buf, r * 2);
00329       }
00330 #endif
00331       if (FD_ISSET(sndcmd[0], &rfds)) {
00332          if (read(sndcmd[0], &cursound, sizeof(cursound)) < 0) {
00333             ast_log(LOG_WARNING, "read() failed: %s\n", strerror(errno));
00334          }
00335          silencelen = 0;
00336          offset = 0;
00337          sampsent = 0;
00338       }
00339       if (FD_ISSET(writedev, &wfds))
00340          if (send_sound())
00341             ast_log(LOG_WARNING, "Failed to write sound\n");
00342    }
00343    /* Never reached */
00344    return NULL;
00345 }

static int soundcard_init ( void   )  [static]

Definition at line 480 of file chan_alsa.c.

References alsa, alsa_card_init(), ast_log(), chan_alsa_pvt::icard, LOG_ERROR, and chan_alsa_pvt::ocard.

Referenced by load_module().

00481 {
00482    alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
00483    alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);
00484 
00485    if (!alsa.icard || !alsa.ocard) {
00486       ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n");
00487       return -1;
00488    }
00489 
00490    return readdev;
00491 }

static int unload_module ( void   )  [static]

Definition at line 1371 of file chan_alsa.c.

References alsa, alsa_tech, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_alsa, chan_alsa_pvt::icard, chan_alsa_pvt::ocard, and chan_alsa_pvt::owner.

01372 {
01373    ast_channel_unregister(&alsa_tech);
01374    ast_cli_unregister_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry));
01375 
01376    if (alsa.icard)
01377       snd_pcm_close(alsa.icard);
01378    if (alsa.ocard)
01379       snd_pcm_close(alsa.ocard);
01380    if (sndcmd[0] > 0) {
01381       close(sndcmd[0]);
01382       close(sndcmd[1]);
01383    }
01384    if (alsa.owner)
01385       ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD);
01386    if (alsa.owner)
01387       return -1;
01388    return 0;
01389 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ALSA Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static]

Definition at line 1391 of file chan_alsa.c.

struct chan_alsa_pvt alsa [static]

Referenced by alsa_answer(), alsa_call(), alsa_hangup(), alsa_read(), alsa_request(), alsa_write(), console_answer(), console_answer_deprecated(), console_dial(), console_dial_deprecated(), console_hangup(), console_hangup_deprecated(), console_sendtext(), console_sendtext_deprecated(), grab_owner(), send_sound(), sound_thread(), soundcard_init(), and unload_module().

struct ast_channel_tech alsa_tech [static]

Definition at line 197 of file chan_alsa.c.

Referenced by alsa_new(), load_module(), and unload_module().

ast_mutex_t alsalock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 118 of file chan_alsa.c.

Referenced by alsa_answer(), alsa_call(), alsa_digit(), alsa_fixup(), alsa_hangup(), alsa_indicate(), alsa_read(), alsa_request(), alsa_text(), alsa_write(), console_answer(), console_answer_deprecated(), console_autoanswer(), console_autoanswer_deprecated(), console_dial(), console_dial_deprecated(), console_hangup(), console_hangup_deprecated(), console_sendtext(), console_sendtext_deprecated(), and grab_owner().

char answer_usage[] [static]

Initial value:

   "Usage: console answer\n"
   "       Answers an incoming call on the console (ALSA) channel.\n"

Definition at line 1074 of file chan_alsa.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1391 of file chan_alsa.c.

int autoanswer = 1 [static]

Definition at line 177 of file chan_alsa.c.

const char autoanswer_usage[] [static]

Initial value:

   "Usage: console autoanswer [on|off]\n"
   "       Enables or disables autoanswer feature.  If used without\n"
   "       argument, displays the current on/off status of autoanswer.\n"
   "       The default value of autoanswer is in 'alsa.conf'.\n"

Definition at line 918 of file chan_alsa.c.

struct ast_cli_entry cli_alsa[] [static]

Definition at line 1281 of file chan_alsa.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_alsa_answer_deprecated [static]

Initial value:

 {
   { "answer", NULL },
   console_answer_deprecated, NULL,
   NULL }

Definition at line 1256 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_autoanswer_deprecated [static]

Initial value:

 {
   { "autoanswer", NULL },
   console_autoanswer_deprecated, NULL,
   NULL, autoanswer_complete }

Definition at line 1276 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_dial_deprecated [static]

Initial value:

 {
   { "dial", NULL },
   console_dial_deprecated, NULL,
   NULL }

Definition at line 1266 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_hangup_deprecated [static]

Initial value:

 {
   { "hangup", NULL },
   console_hangup_deprecated, NULL,
   NULL }

Definition at line 1261 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_send_text_deprecated [static]

Initial value:

 {
   { "send", "text", NULL },
   console_sendtext_deprecated, NULL,
   NULL }

Definition at line 1271 of file chan_alsa.c.

const char config[] = "alsa.conf" [static]

Definition at line 121 of file chan_alsa.c.

char context[AST_MAX_CONTEXT] = "default" [static]

Definition at line 123 of file chan_alsa.c.

Referenced by __login_exec(), acf_vmcount_exec(), action_agent_callback_login(), action_atxfer(), action_extensionstate(), action_originate(), action_redirect(), append_mailbox_mapping(), ast_compile_ael2(), ast_get_enum(), ast_get_srv(), ast_get_txt(), asyncgoto_exec(), build_device(), build_gateway(), check_user_full(), cmd_atxfer(), complete_context_add_include(), complete_context_add_include_deprecated(), complete_context_dont_include_deprecated(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_context_remove_include(), create_addr_from_peer(), disa_exec(), extenspy_exec(), get_also_info(), get_cid_name(), get_destination(), gtalk_load_config(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), handle_request_bye(), handle_request_invite(), handle_request_options(), handle_request_refer(), handle_show_dialplan(), hasvoicemail_exec(), log_exec(), metermaidstate(), orig_exten(), parkandannounce_exec(), pickup_exec(), process_ast_dsp(), process_weights(), register_peer_exten(), reload_config(), retrydial_exec(), SHA1Input(), SHA1PadMessage(), SHA1ProcessMessageBlock(), SHA1Reset(), SHA1Result(), sip_alloc(), and wait_for_answer().

int cursound = -1 [static]

Definition at line 179 of file chan_alsa.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 76 of file chan_alsa.c.

Referenced by gtalk_load_config(), load_module(), misdn_cfg_init(), reload_config(), and setup_dahdi().

char dial_usage[] [static]

Initial value:

   "Usage: console dial [extension[@context]]\n"
   "       Dials a given extension (and context if specified)\n"

Definition at line 1252 of file chan_alsa.c.

char exten[AST_MAX_EXTENSION] = "s" [static]

Definition at line 125 of file chan_alsa.c.

Referenced by action_agent_callback_login(), action_atxfer(), action_extensionstate(), action_originate(), action_redirect(), add_extensions(), ast_compile_ael2(), ast_context_remove_extension_callerid2(), ast_feature_interpret(), ast_get_extension_context(), ast_get_extension_label(), ast_get_extension_name(), ast_get_extension_priority(), ast_ivr_menu_run_internal(), ast_parseable_goto(), ast_walk_context_extensions(), ast_walk_extension_priorities(), asyncgoto_exec(), build_device(), check_access(), check_user_full(), complete_context_remove_extension(), complete_context_remove_extension_deprecated(), complete_dpreply(), destroy_extensions(), destroy_station(), disa_exec(), extenspy_exec(), fix_gotos_in_extensions(), gen_prios(), get_cid_name(), get_destination(), gtalk_alloc(), handle_context_add_extension(), handle_context_add_extension_deprecated(), handle_context_remove_extension(), handle_context_remove_extension_deprecated(), handle_request_invite(), handle_show_dialplan(), handle_showfeatures(), initreqprep(), leave_voicemail(), linkexten(), linkprio(), metermaidstate(), mgcp_ss(), new_iax(), orig_exten(), osplookup_exec(), park_add_hints(), parkandannounce_exec(), pickup_exec(), register_verify(), remap_feature(), set_priorities(), skinny_answer(), skinny_indicate(), socket_process(), ss_thread(), transmit_register(), unmap_features(), and waitstream_core().

snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE [static]

Definition at line 103 of file chan_alsa.c.

Referenced by acf_sprintf(), acf_strftime(), acf_strptime(), action_originate(), add_codec_to_answer(), ast_codec_pref_getsize(), ast_getformatbyname(), ast_monitor_stop(), ast_openvstream(), ast_parse_allow_disallow(), ast_rtp_lookup_mime_multiple(), build_user(), check_header(), echo_exec(), handle_saydatetime(), handle_showfeatures(), handle_showmancmds(), handle_showmanconn(), process_sdp(), reload_config(), sayunixtime_exec(), set_config(), socket_process(), start_monitor_action(), and start_monitor_exec().

struct ast_jb_conf global_jbconf [static]

Definition at line 82 of file chan_alsa.c.

Referenced by __oh323_rtp_create(), __oh323_update_info(), _build_general_config(), alsa_new(), dahdi_new(), gtalk_load_config(), gtalk_new(), load_module(), mgcp_new(), misdn_cfg_init(), misdn_get_global_jbconf(), oss_new(), process_dahdi(), reload_config(), setup_dahdi(), sip_get_rtp_peer(), sip_new(), skinny_new(), and store_config().

char hangup_usage[] [static]

Initial value:

   "Usage: console hangup\n"
   "       Hangs up any call currently placed on the console.\n"

Definition at line 1134 of file chan_alsa.c.

int hookstate = 0 [static]

Definition at line 128 of file chan_alsa.c.

char indevname[50] = ALSA_INDEV [static]

Definition at line 108 of file chan_alsa.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 124 of file chan_alsa.c.

Referenced by agent_new(), ast_do_masquerade(), begin_dial(), build_device(), build_gateway(), check_user_full(), create_addr_from_peer(), dahdi_new(), features_call(), func_channel_write(), gtalk_new(), language_write(), local_call(), mgcp_new(), nbs_new(), oss_new(), read_config(), sip_new(), skinny_new(), and vm_execmain().

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 126 of file chan_alsa.c.

Referenced by build_device(), check_user_full(), create_addr_from_peer(), and sip_alloc().

int nosound = 0 [static]

Definition at line 183 of file chan_alsa.c.

int offset = 0 [static]

Definition at line 182 of file chan_alsa.c.

Referenced by _macro_exec(), ast_dynamic_str_thread_build_va(), ast_say_date_with_format_da(), ast_say_date_with_format_de(), ast_say_date_with_format_en(), ast_say_date_with_format_es(), ast_say_date_with_format_fr(), ast_say_date_with_format_gr(), ast_say_date_with_format_he(), ast_say_date_with_format_it(), ast_say_date_with_format_nl(), ast_say_date_with_format_pl(), ast_say_date_with_format_pt(), ast_say_date_with_format_tw(), ast_slinfactory_read(), au_seek(), au_tell(), cliinput(), copy_request(), fileexists_test(), function_remote(), g729_seek(), g729_tell(), gsm_seek(), gsm_tell(), h263_tell(), h264_tell(), ilbc_seek(), ilbc_tell(), mkintf(), mp3_exec(), NBScat_exec(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), pcm_seek(), resynch_jb(), send_waveform_to_channel(), setkenwood(), slinear_seek(), vox_seek(), vox_tell(), wav_seek(), and wav_tell().

char outdevname[50] = ALSA_OUTDEV [static]

Definition at line 109 of file chan_alsa.c.

int readdev = -1 [static]

Definition at line 174 of file chan_alsa.c.

int sampsent = 0 [static]

Definition at line 180 of file chan_alsa.c.

char sendtext_usage[] [static]

Initial value:

   "Usage: console send text <message>\n"
   "       Sends a text message for display on the remote terminal.\n"

Definition at line 988 of file chan_alsa.c.

short silence[FRAME_SIZE] = { 0, } [static]

Definition at line 130 of file chan_alsa.c.

Referenced by ast_dsp_process(), handle_recordfile(), record_exec(), and send_sound().

int silencelen = 0 [static]

Definition at line 181 of file chan_alsa.c.

int silencesuppression = 0 [static]

Definition at line 115 of file chan_alsa.c.

int silencethreshold = 1000 [static]

Definition at line 116 of file chan_alsa.c.

Referenced by ast_record_review(), and do_waiting().

int sndcmd[2] [static]

Definition at line 150 of file chan_alsa.c.

struct sound sounds[] [static]

Definition at line 141 of file chan_alsa.c.

Referenced by send_sound(), and sound_thread().

pthread_t sthread

Definition at line 169 of file chan_alsa.c.

const char tdesc[] = "ALSA Console Channel Driver" [static]

Definition at line 120 of file chan_alsa.c.

int writedev = -1 [static]

Definition at line 175 of file chan_alsa.c.


Generated on Thu May 14 15:13:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7