Sat Apr 12 07:12:35 2008

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.h"
#include "ringtone.h"
#include "ring10.h"
#include "answer.h"

Include dependency graph for chan_alsa.c:

Go to the source code of this file.

Data Structures

struct  chan_alsa_pvt
struct  sound

Defines

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

Functions

static int alsa_answer (struct ast_channel *c)
static int alsa_call (struct ast_channel *c, char *dest, int timeout)
static snd_pcm_t * alsa_card_init (char *dev, snd_pcm_stream_t stream)
static int alsa_digit (struct ast_channel *c, char digit, unsigned int duration)
static int alsa_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int alsa_hangup (struct ast_channel *c)
static int alsa_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen)
static struct ast_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 *dest, const char *text, int ispdu)
static int alsa_write (struct ast_channel *chan, struct ast_frame *f)
static void answer_sound (void)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"ALSA Console Channel Driver")
 AST_MUTEX_DEFINE_STATIC (alsalock)
static char * autoanswer_complete (const char *line, const char *word, int pos, int state)
static int console_answer (int fd, int argc, char *argv[])
static int console_answer_deprecated (int fd, int argc, char *argv[])
static int console_autoanswer (int fd, int argc, char *argv[])
static int console_autoanswer_deprecated (int fd, int argc, char *argv[])
static int console_dial (int fd, int argc, char *argv[])
static int console_dial_deprecated (int fd, int argc, char *argv[])
static int console_hangup (int fd, int argc, char *argv[])
static int console_hangup_deprecated (int fd, int argc, char *argv[])
static int console_sendtext (int fd, int argc, char *argv[])
static int console_sendtext_deprecated (int fd, int argc, char *argv[])
static void grab_owner (void)
static int load_module (void)
static int send_sound (void)
static void * sound_thread (void *unused)
static int soundcard_init (void)
static int unload_module (void)

Variables

static struct chan_alsa_pvt alsa
static struct ast_channel_tech alsa_tech
static char answer_usage []
static int autoanswer = 1
static const char autoanswer_usage []
static struct ast_cli_entry cli_alsa []
static struct ast_cli_entry cli_alsa_answer_deprecated
static struct ast_cli_entry cli_alsa_autoanswer_deprecated
static struct ast_cli_entry cli_alsa_dial_deprecated
static struct ast_cli_entry cli_alsa_hangup_deprecated
static struct ast_cli_entry cli_alsa_send_text_deprecated
static const char config [] = "alsa.conf"
static char context [AST_MAX_CONTEXT] = "default"
static int cursound = -1
static struct ast_jb_conf default_jbconf
static char dial_usage []
static char exten [AST_MAX_EXTENSION] = "s"
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE
static struct ast_jb_conf global_jbconf
static char hangup_usage []
static int hookstate = 0
static char indevname [50] = ALSA_INDEV
static char language [MAX_LANGUAGE] = ""
static char mohinterpret [MAX_MUSICCLASS]
static int nosound = 0
static int offset = 0
static char outdevname [50] = ALSA_OUTDEV
static int readdev = -1
static int sampsent = 0
static char sendtext_usage []
static short silence [FRAME_SIZE] = { 0, }
static int silencelen = 0
static int silencesuppression = 0
static int silencethreshold = 1000
static int sndcmd [2]
static struct sound sounds []
pthread_t sthread
static const char tdesc [] = "ALSA Console Channel Driver"
static int writedev = -1


Detailed Description

ALSA sound card channel driver.

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

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 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 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 int alsa_answer ( struct ast_channel c  )  [static]

Definition at line 555 of file chan_alsa.c.

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

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

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

Definition at line 516 of file chan_alsa.c.

References alsa, AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_verbose(), grab_owner(), chan_alsa_pvt::icard, ast_channel::lock, chan_alsa_pvt::owner, and ast_frame::subclass.

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

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

Definition at line 344 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().

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

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

Definition at line 490 of file chan_alsa.c.

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

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

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

Definition at line 730 of file chan_alsa.c.

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

00731 {
00732    struct chan_alsa_pvt *p = newchan->tech_pvt;
00733    ast_mutex_lock(&alsalock);
00734    p->owner = newchan;
00735    ast_mutex_unlock(&alsalock);
00736    return 0;
00737 }

static int alsa_hangup ( struct ast_channel c  )  [static]

Definition at line 568 of file chan_alsa.c.

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

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

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

Definition at line 739 of file chan_alsa.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), and LOG_WARNING.

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

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

Definition at line 782 of file chan_alsa.c.

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

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

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

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

Definition at line 655 of file chan_alsa.c.

References ast_channel::_state, alsa, AST_FORMAT_SLINEAR, AST_FRAME_NULL, AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), AST_STATE_UP, ast_frame::data, ast_frame::datalen, ast_frame::delivery, FRAME_SIZE, ast_frame::frametype, chan_alsa_pvt::icard, LOG_ERROR, ast_frame::mallocd, ast_frame::offset, ast_frame::samples, ast_frame::src, and ast_frame::subclass.

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

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

Definition at line 815 of file chan_alsa.c.

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

00816 {
00817    int oldformat = format;
00818    struct ast_channel *tmp = NULL;
00819 
00820    format &= AST_FORMAT_SLINEAR;
00821    if (!format) {
00822       ast_log(LOG_NOTICE, "Asked to get a channel of format '%d'\n", oldformat);
00823       return NULL;
00824    }
00825 
00826    ast_mutex_lock(&alsalock);
00827 
00828    if (alsa.owner) {
00829       ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");
00830       *cause = AST_CAUSE_BUSY;
00831    } else if (!(tmp = alsa_new(&alsa, AST_STATE_DOWN)))
00832       ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");
00833 
00834    ast_mutex_unlock(&alsalock);
00835 
00836    return tmp;
00837 }

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

Definition at line 499 of file chan_alsa.c.

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

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

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

Definition at line 590 of file chan_alsa.c.

References alsa, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_frame::data, ast_frame::datalen, len, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, and chan_alsa_pvt::ocard.

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

static void answer_sound ( void   )  [static]

Definition at line 546 of file chan_alsa.c.

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

00547 {
00548    int res;
00549    nosound = 1;
00550    res = 4;
00551    write(sndcmd[1], &res, sizeof(res));
00552 
00553 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"ALSA Console Channel Driver"   
)

AST_MUTEX_DEFINE_STATIC ( alsalock   ) 

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

Definition at line 884 of file chan_alsa.c.

References ast_strdup, ast_strlen_zero(), and MIN.

00885 {
00886 #ifndef MIN
00887 #define MIN(a,b) ((a) < (b) ? (a) : (b))
00888 #endif
00889    switch (state) {
00890       case 0:
00891          if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
00892             return ast_strdup("on");
00893       case 1:
00894          if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
00895             return ast_strdup("off");
00896       default:
00897          return NULL;
00898    }
00899    return NULL;
00900 }

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

Definition at line 940 of file chan_alsa.c.

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

00941 {
00942    int res = RESULT_SUCCESS;
00943 
00944    if (argc != 2)
00945       return RESULT_SHOWUSAGE;
00946 
00947    ast_mutex_lock(&alsalock);
00948 
00949    if (!alsa.owner) {
00950       ast_cli(fd, "No one is calling us\n");
00951       res = RESULT_FAILURE;
00952    } else {
00953       hookstate = 1;
00954       cursound = -1;
00955       grab_owner();
00956       if (alsa.owner) {
00957          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00958          ast_queue_frame(alsa.owner, &f);
00959          ast_mutex_unlock(&alsa.owner->lock);
00960       }
00961       answer_sound();
00962    }
00963 
00964    snd_pcm_prepare(alsa.icard);
00965    snd_pcm_start(alsa.icard);
00966 
00967    ast_mutex_unlock(&alsalock);
00968 
00969    return RESULT_SUCCESS;
00970 }

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

Definition at line 908 of file chan_alsa.c.

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

00909 {
00910    int res = RESULT_SUCCESS;
00911 
00912    if (argc != 1)
00913       return RESULT_SHOWUSAGE;
00914 
00915    ast_mutex_lock(&alsalock);
00916 
00917    if (!alsa.owner) {
00918       ast_cli(fd, "No one is calling us\n");
00919       res = RESULT_FAILURE;
00920    } else {
00921       hookstate = 1;
00922       cursound = -1;
00923       grab_owner();
00924       if (alsa.owner) {
00925          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00926          ast_queue_frame(alsa.owner, &f);
00927          ast_mutex_unlock(&alsa.owner->lock);
00928       }
00929       answer_sound();
00930    }
00931 
00932    snd_pcm_prepare(alsa.icard);
00933    snd_pcm_start(alsa.icard);
00934 
00935    ast_mutex_unlock(&alsalock);
00936 
00937    return RESULT_SUCCESS;
00938 }

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

Definition at line 864 of file chan_alsa.c.

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

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

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

Definition at line 839 of file chan_alsa.c.

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

00840 {
00841    int res = RESULT_SUCCESS;
00842 
00843    if ((argc != 1) && (argc != 2))
00844       return RESULT_SHOWUSAGE;
00845 
00846    ast_mutex_lock(&alsalock);
00847 
00848    if (argc == 1) {
00849       ast_cli(fd, "Auto answer is %s.\n", autoanswer ? "on" : "off");
00850    } else {
00851       if (!strcasecmp(argv[1], "on"))
00852          autoanswer = -1;
00853       else if (!strcasecmp(argv[1], "off"))
00854          autoanswer = 0;
00855       else
00856          res = RESULT_SHOWUSAGE;
00857    }
00858 
00859    ast_mutex_unlock(&alsalock);
00860 
00861    return res;
00862 }

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

Definition at line 1179 of file chan_alsa.c.

References alsa, alsa_new(), ast_cli(), 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, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, strsep(), and ast_frame::subclass.

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

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

Definition at line 1122 of file chan_alsa.c.

References alsa, alsa_new(), ast_cli(), 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, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, strsep(), and ast_frame::subclass.

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

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

Definition at line 1090 of file chan_alsa.c.

References alsa, 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.

01091 {
01092    int res = RESULT_SUCCESS;
01093 
01094    if (argc != 2)
01095       return RESULT_SHOWUSAGE;
01096 
01097    cursound = -1;
01098 
01099    ast_mutex_lock(&alsalock);
01100 
01101    if (!alsa.owner && !hookstate) {
01102       ast_cli(fd, "No call to hangup up\n");
01103       res = RESULT_FAILURE;
01104    } else {
01105       hookstate = 0;
01106       grab_owner();
01107       if (alsa.owner) {
01108          ast_queue_hangup(alsa.owner);
01109          ast_mutex_unlock(&alsa.owner->lock);
01110       }
01111    }
01112 
01113    ast_mutex_unlock(&alsalock);
01114 
01115    return res;
01116 }

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

Definition at line 1062 of file chan_alsa.c.

References alsa, 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.

01063 {
01064    int res = RESULT_SUCCESS;
01065 
01066    if (argc != 1)
01067       return RESULT_SHOWUSAGE;
01068 
01069    cursound = -1;
01070 
01071    ast_mutex_lock(&alsalock);
01072 
01073    if (!alsa.owner && !hookstate) {
01074       ast_cli(fd, "No call to hangup up\n");
01075       res = RESULT_FAILURE;
01076    } else {
01077       hookstate = 0;
01078       grab_owner();
01079       if (alsa.owner) {
01080          ast_queue_hangup(alsa.owner);
01081          ast_mutex_unlock(&alsa.owner->lock);
01082       }
01083    }
01084 
01085    ast_mutex_unlock(&alsalock);
01086 
01087    return res;
01088 }

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

Definition at line 1017 of file chan_alsa.c.

References alsa, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_frame::subclass.

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

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

Definition at line 976 of file chan_alsa.c.

References alsa, ast_cli(), AST_CONTROL_ANSWER, AST_FRAME_CONTROL, AST_FRAME_TEXT, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_frame(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, grab_owner(), ast_channel::lock, chan_alsa_pvt::owner, RESULT_FAILURE, RESULT_SHOWUSAGE, RESULT_SUCCESS, and ast_frame::subclass.

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

static void grab_owner ( void   )  [static]

static int load_module ( void   )  [static]

Definition at line 1287 of file chan_alsa.c.

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

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

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, 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    res = snd_pcm_writei(alsa.ocard, frame, res);
00271    if (res > 0)
00272       return 0;
00273    return 0;
00274 }

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

Definition at line 276 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(), and store_config().

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

static int soundcard_init ( void   )  [static]

Definition at line 477 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().

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

static int unload_module ( void   )  [static]

Definition at line 1355 of file chan_alsa.c.

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

01356 {
01357    ast_channel_unregister(&alsa_tech);
01358    ast_cli_unregister_multiple(cli_alsa, sizeof(cli_alsa) / sizeof(struct ast_cli_entry));
01359 
01360    if (alsa.icard)
01361       snd_pcm_close(alsa.icard);
01362    if (alsa.ocard)
01363       snd_pcm_close(alsa.ocard);
01364    if (sndcmd[0] > 0) {
01365       close(sndcmd[0]);
01366       close(sndcmd[1]);
01367    }
01368    if (alsa.owner)
01369       ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD);
01370    if (alsa.owner)
01371       return -1;
01372    return 0;
01373 }


Variable Documentation

struct chan_alsa_pvt alsa [static]

struct ast_channel_tech alsa_tech [static]

Definition at line 198 of file chan_alsa.c.

char answer_usage[] [static]

Initial value:

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

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

struct ast_cli_entry cli_alsa[] [static]

Definition at line 1265 of file chan_alsa.c.

Initial value:

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

Definition at line 1240 of file chan_alsa.c.

Initial value:

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

Definition at line 1260 of file chan_alsa.c.

Initial value:

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

Definition at line 1250 of file chan_alsa.c.

Initial value:

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

Definition at line 1245 of file chan_alsa.c.

Initial value:

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

Definition at line 1255 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]

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 76 of file chan_alsa.c.

char dial_usage[] [static]

Initial value:

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

Definition at line 1236 of file chan_alsa.c.

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]

Initial value:

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

Definition at line 1118 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]

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 127 of file chan_alsa.c.

Referenced by 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]

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 972 of file chan_alsa.c.

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

Definition at line 131 of file chan_alsa.c.

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

int silencelen = 0 [static]

Definition at line 182 of file chan_alsa.c.

int silencesuppression = 0 [static]

Definition at line 116 of file chan_alsa.c.

int silencethreshold = 1000 [static]

int sndcmd[2] [static]

Definition at line 151 of file chan_alsa.c.

struct sound sounds[] [static]

Definition at line 142 of file chan_alsa.c.

pthread_t sthread

Definition at line 170 of file chan_alsa.c.

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

Definition at line 121 of file chan_alsa.c.

int writedev = -1 [static]

Definition at line 176 of file chan_alsa.c.


Generated on Sat Apr 12 07:12:35 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.5