Sat Aug 6 00:39:40 2011

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 "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_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 = "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_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 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

Definition at line 89 of file chan_alsa.c.

Referenced by alsa_card_init().

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

Definition at line 93 of file chan_alsa.c.

Referenced by alsa_card_init().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1385 of file chan_alsa.c.

static void __unreg_module ( void   )  [static]

Definition at line 1385 of file chan_alsa.c.

static int alsa_answer ( struct ast_channel c  )  [static]

Definition at line 554 of file chan_alsa.c.

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

00555 {
00556    ast_mutex_lock(&alsalock);
00557    ast_verbose(" << Console call has been answered >> \n");
00558    answer_sound();
00559    ast_setstate(c, AST_STATE_UP);
00560    cursound = -1;
00561    snd_pcm_prepare(alsa.icard);
00562    snd_pcm_start(alsa.icard);
00563    ast_mutex_unlock(&alsalock);
00564    return 0;
00565 }

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

Definition at line 511 of file chan_alsa.c.

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

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

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

Definition at line 341 of file chan_alsa.c.

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

Referenced by soundcard_init().

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

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

Definition at line 487 of file chan_alsa.c.

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

00488 {
00489    ast_mutex_lock(&alsalock);
00490    ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
00491       digit, duration);
00492    ast_mutex_unlock(&alsalock);
00493    return 0;
00494 }

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

Definition at line 735 of file chan_alsa.c.

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

00736 {
00737    struct chan_alsa_pvt *p = newchan->tech_pvt;
00738    ast_mutex_lock(&alsalock);
00739    p->owner = newchan;
00740    ast_mutex_unlock(&alsalock);
00741    return 0;
00742 }

static int alsa_hangup ( struct ast_channel c  )  [static]

Definition at line 567 of file chan_alsa.c.

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

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

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

Definition at line 744 of file chan_alsa.c.

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

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

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

Definition at line 792 of file chan_alsa.c.

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

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

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

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

Definition at line 660 of file chan_alsa.c.

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

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

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

Definition at line 825 of file chan_alsa.c.

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

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

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

Definition at line 496 of file chan_alsa.c.

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

00497 {
00498    ast_mutex_lock(&alsalock);
00499    ast_verbose(" << Console Received text %s >> \n", text);
00500    ast_mutex_unlock(&alsalock);
00501    return 0;
00502 }

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

Definition at line 591 of file chan_alsa.c.

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

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

static void answer_sound ( void   )  [static]

Definition at line 543 of file chan_alsa.c.

References ast_log(), errno, and LOG_WARNING.

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

00544 {
00545    int res;
00546 
00547    nosound = 1;
00548    res = 4;
00549    if (write(sndcmd[1], &res, sizeof(res)) < 0) {
00550       ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
00551    }
00552 }

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

Definition at line 894 of file chan_alsa.c.

References ast_strdup, ast_strlen_zero(), and MIN.

00895 {
00896 #ifndef MIN
00897 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00898 #endif
00899    switch (state) {
00900       case 0:
00901          if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
00902             return ast_strdup("on");
00903       case 1:
00904          if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
00905             return ast_strdup("off");
00906       default:
00907          return NULL;
00908    }
00909    return NULL;
00910 }

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

Definition at line 950 of file chan_alsa.c.

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

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

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

Definition at line 918 of file chan_alsa.c.

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

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

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

Definition at line 874 of file chan_alsa.c.

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

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

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

Definition at line 849 of file chan_alsa.c.

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

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

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

Definition at line 1189 of file chan_alsa.c.

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

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

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

Definition at line 1132 of file chan_alsa.c.

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

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

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

Definition at line 1100 of file chan_alsa.c.

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

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

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

Definition at line 1072 of file chan_alsa.c.

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

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

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

Definition at line 1027 of file chan_alsa.c.

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

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

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

Definition at line 986 of file chan_alsa.c.

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

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

static void grab_owner ( void   )  [static]

Definition at line 504 of file chan_alsa.c.

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

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

00505 {
00506    while (alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) {
00507       DEADLOCK_AVOIDANCE(&alsalock);
00508    }
00509 }

static int load_module ( void   )  [static]

Definition at line 1297 of file chan_alsa.c.

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

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

static int send_sound ( void   )  [static]

Definition at line 214 of file chan_alsa.c.

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

Referenced by sound_thread().

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

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

Definition at line 278 of file chan_alsa.c.

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

Referenced by load_module().

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

static int soundcard_init ( void   )  [static]

Definition at line 474 of file chan_alsa.c.

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

Referenced by load_module().

00475 {
00476    alsa.icard = alsa_card_init(indevname, SND_PCM_STREAM_CAPTURE);
00477    alsa.ocard = alsa_card_init(outdevname, SND_PCM_STREAM_PLAYBACK);
00478 
00479    if (!alsa.icard || !alsa.ocard) {
00480       ast_log(LOG_ERROR, "Problem opening alsa I/O devices\n");
00481       return -1;
00482    }
00483 
00484    return readdev;
00485 }

static int unload_module ( void   )  [static]

Definition at line 1365 of file chan_alsa.c.

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

01366 {
01367    ast_channel_unregister(&alsa_tech);
01368    ast_cli_unregister_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry));
01369 
01370    if (alsa.icard)
01371       snd_pcm_close(alsa.icard);
01372    if (alsa.ocard)
01373       snd_pcm_close(alsa.ocard);
01374    if (sndcmd[0] > 0) {
01375       close(sndcmd[0]);
01376       close(sndcmd[1]);
01377    }
01378    if (alsa.owner)
01379       ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD);
01380    if (alsa.owner)
01381       return -1;
01382    return 0;
01383 }


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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 1385 of file chan_alsa.c.

struct chan_alsa_pvt alsa [static]

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

struct ast_channel_tech alsa_tech [static]

Definition at line 198 of file chan_alsa.c.

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

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

Definition at line 119 of file chan_alsa.c.

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

char answer_usage[] [static]

Initial value:

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

Definition at line 1068 of file chan_alsa.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1385 of file chan_alsa.c.

int autoanswer = 1 [static]

Definition at line 178 of file chan_alsa.c.

const char autoanswer_usage[] [static]

Initial value:

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

Definition at line 912 of file chan_alsa.c.

struct ast_cli_entry cli_alsa[] [static]

Definition at line 1275 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 1250 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_autoanswer_deprecated [static]

Initial value:

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

Definition at line 1270 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_dial_deprecated [static]

Initial value:

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

Definition at line 1260 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_hangup_deprecated [static]

Initial value:

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

Definition at line 1255 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_send_text_deprecated [static]

Initial value:

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

Definition at line 1265 of file chan_alsa.c.

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

Definition at line 122 of file chan_alsa.c.

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

Definition at line 124 of file chan_alsa.c.

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

int cursound = -1 [static]

Definition at line 180 of file chan_alsa.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 77 of file chan_alsa.c.

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

char dial_usage[] [static]

Initial value:

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

Definition at line 1246 of file chan_alsa.c.

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

Definition at line 126 of file chan_alsa.c.

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

snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE [static]

Definition at line 104 of file chan_alsa.c.

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

struct ast_jb_conf global_jbconf [static]

Definition at line 83 of file chan_alsa.c.

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

char hangup_usage[] [static]

Initial value:

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

Definition at line 1128 of file chan_alsa.c.

int hookstate = 0 [static]

Definition at line 129 of file chan_alsa.c.

char indevname[50] = ALSA_INDEV [static]

Definition at line 109 of file chan_alsa.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 125 of file chan_alsa.c.

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

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 127 of file chan_alsa.c.

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

int nosound = 0 [static]

Definition at line 184 of file chan_alsa.c.

int offset = 0 [static]

Definition at line 183 of file chan_alsa.c.

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

char outdevname[50] = ALSA_OUTDEV [static]

Definition at line 110 of file chan_alsa.c.

int readdev = -1 [static]

Definition at line 175 of file chan_alsa.c.

int sampsent = 0 [static]

Definition at line 181 of file chan_alsa.c.

char sendtext_usage[] [static]

Initial value:

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

Definition at line 982 of file chan_alsa.c.

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

Definition at line 131 of file chan_alsa.c.

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

int silencelen = 0 [static]

Definition at line 182 of file chan_alsa.c.

int silencesuppression = 0 [static]

Definition at line 116 of file chan_alsa.c.

int silencethreshold = 1000 [static]

Definition at line 117 of file chan_alsa.c.

Referenced by ast_record_review(), and do_waiting().

int sndcmd[2] [static]

Definition at line 151 of file chan_alsa.c.

struct sound sounds[] [static]

Definition at line 142 of file chan_alsa.c.

Referenced by send_sound(), and sound_thread().

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.


Generated on Sat Aug 6 00:39:41 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7