Sat Nov 1 06:28:51 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 *text)
static int alsa_write (struct ast_channel *chan, struct ast_frame *f)
static void answer_sound (void)
 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"ALSA Console Channel Driver")
 AST_MUTEX_DEFINE_STATIC (alsalock)
static char * autoanswer_complete (const char *line, const char *word, int pos, int state)
static int console_answer (int fd, int argc, char *argv[])
static int console_answer_deprecated (int fd, int argc, char *argv[])
static int console_autoanswer (int fd, int argc, char *argv[])
static int console_autoanswer_deprecated (int fd, int argc, char *argv[])
static int console_dial (int fd, int argc, char *argv[])
static int console_dial_deprecated (int fd, int argc, char *argv[])
static int console_hangup (int fd, int argc, char *argv[])
static int console_hangup_deprecated (int fd, int argc, char *argv[])
static int console_sendtext (int fd, int argc, char *argv[])
static int console_sendtext_deprecated (int fd, int argc, char *argv[])
static void grab_owner (void)
static int load_module (void)
static int send_sound (void)
static void * sound_thread (void *unused)
static int soundcard_init (void)
static int unload_module (void)

Variables

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


Detailed Description

ALSA sound card channel driver.

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

Definition in file chan_alsa.c.


Define Documentation

#define ALSA_INDEV   "default"

Definition at line 86 of file chan_alsa.c.

#define ALSA_OUTDEV   "default"

Definition at line 87 of file chan_alsa.c.

#define ALSA_PCM_NEW_HW_PARAMS_API

Definition at line 47 of file chan_alsa.c.

#define ALSA_PCM_NEW_SW_PARAMS_API

Definition at line 48 of file chan_alsa.c.

#define BUFFER_FMT   ((buffersize * 10) << 16) | (0x0006);

Definition at line 97 of file chan_alsa.c.

#define DEBUG   0

Definition at line 84 of file chan_alsa.c.

#define DESIRED_RATE   8000

Definition at line 88 of file chan_alsa.c.

Referenced by alsa_card_init().

#define FRAME_SIZE   160

Definition at line 91 of file chan_alsa.c.

Referenced by alsa_read(), oss_read(), send_sound(), sound_thread(), and soundcard_writeframe().

#define MAX_BUFFER_SIZE   100

Definition at line 171 of file chan_alsa.c.

#define MIN ( a,
 )     ((a) < (b) ? (a) : (b))

Referenced by autoanswer_complete().

#define MIN_SWITCH_TIME   600

Definition at line 100 of file chan_alsa.c.

#define PERIOD_FRAMES   80

Definition at line 92 of file chan_alsa.c.

Referenced by alsa_card_init().


Function Documentation

static int alsa_answer ( struct ast_channel c  )  [static]

Definition at line 552 of file chan_alsa.c.

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

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

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

Definition at line 513 of file chan_alsa.c.

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

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

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

Definition at line 343 of file chan_alsa.c.

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

Referenced by soundcard_init().

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

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

Definition at line 489 of file chan_alsa.c.

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

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

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

Definition at line 727 of file chan_alsa.c.

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

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

static int alsa_hangup ( struct ast_channel c  )  [static]

Definition at line 565 of file chan_alsa.c.

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

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

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

Definition at line 736 of file chan_alsa.c.

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

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

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

Definition at line 781 of file chan_alsa.c.

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

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

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

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

Definition at line 652 of file chan_alsa.c.

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

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

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

Definition at line 814 of file chan_alsa.c.

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

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

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

Definition at line 498 of file chan_alsa.c.

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

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

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

Definition at line 587 of file chan_alsa.c.

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

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

static void answer_sound ( void   )  [static]

Definition at line 543 of file chan_alsa.c.

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

00544 {
00545    int res;
00546    nosound = 1;
00547    res = 4;
00548    write(sndcmd[1], &res, sizeof(res));
00549 
00550 }

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"ALSA Console Channel Driver"   
)

AST_MUTEX_DEFINE_STATIC ( alsalock   ) 

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

Definition at line 883 of file chan_alsa.c.

References ast_strdup, ast_strlen_zero(), and MIN.

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

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

Definition at line 939 of file chan_alsa.c.

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

00940 {
00941    int res = RESULT_SUCCESS;
00942 
00943    if (argc != 2)
00944       return RESULT_SHOWUSAGE;
00945 
00946    ast_mutex_lock(&alsalock);
00947 
00948    if (!alsa.owner) {
00949       ast_cli(fd, "No one is calling us\n");
00950       res = RESULT_FAILURE;
00951    } else {
00952       hookstate = 1;
00953       cursound = -1;
00954       grab_owner();
00955       if (alsa.owner) {
00956          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
00957          ast_queue_frame(