Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:27 2009

## Asterisk developer's documentation

# chan_alsa.c File Reference

ALSA sound card channel driver. More...

`#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.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 "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)
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)
static struct ast_channel * | alsa_new (struct chan_alsa_pvt *p, int state)
static struct ast_frame * | alsa_read (struct ast_channel *chan)
static struct ast_channel * | alsa_request (const char *type, int format, void *data, int *cause)
static int | alsa_text (struct ast_channel *c, const char *text)
static int | alsa_write (struct ast_channel *chan, struct ast_frame *f)
static void | answer_sound (void)
| AST_MUTEX_DEFINE_STATIC (alsalock)
| AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static char * | autoanswer_complete (char *line, char *word, int pos, int state)
static int | console_answer (int fd, int argc, char *argv[])
static int | console_autoanswer (int fd, int argc, char *argv[])
static int | console_dial (int fd, int argc, char *argv[])
static int | console_hangup (int fd, int argc, char *argv[])
static int | console_sendtext (int fd, int argc, char *argv[])
char * | description ()
| Provides a description of the module.
static void | grab_owner (void)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module ()
| Initialize the module.
static int | send_sound (void)
static void * | sound_thread (void *unused)
static int | soundcard_init (void)
int | unload_module ()
| Cleanup all module structures, sockets, etc.
int | usecount ()
| Provides a usecount.

## Variables

static struct chan_alsa_pvt | alsa
static struct ast_channel_tech | alsa_tech
static char | answer_usage []
static int | autoanswer = 1
static char | autoanswer_usage []
static const char | config [] = "alsa.conf"
static char | context [AST_MAX_CONTEXT] = "default"
static int | cursound = -1
static const char | desc [] = "ALSA Console Channel Driver"
static char | dial_usage []
static char | exten [AST_MAX_EXTENSION] = "s"
static snd_pcm_format_t | format = SND_PCM_FORMAT_S16_LE
static char | hangup_usage []
static int | hookstate = 0
static char | indevname [50] = ALSA_INDEV
static char | language [MAX_LANGUAGE] = ""
static struct ast_cli_entry | myclis []
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 const char | type [] = "Console"
static int | usecnt
static int | writedev = -1

## Detailed Description

ALSA sound card channel driver.

See also
  - Config_alsa

Definition in file chan_alsa.c.

## Define Documentation

#define ALSA_INDEV "default"

Definition at line 69 of file chan_alsa.c.

#define ALSA_OUTDEV "default"

Definition at line 70 of file chan_alsa.c.

#define ALSA_PCM_NEW_HW_PARAMS_API

Definition at line 38 of file chan_alsa.c.

#define ALSA_PCM_NEW_SW_PARAMS_API

Definition at line 39 of file chan_alsa.c.

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

Definition at line 80 of file chan_alsa.c.

Referenced by setformat().

#define DEBUG 0

Definition at line 67 of file chan_alsa.c.

#define DESIRED_RATE 8000

Definition at line 71 of file chan_alsa.c.

Referenced by alsa_card_init().

#define FRAME_SIZE 160

Definition at line 74 of file chan_alsa.c.

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

#define MAX_BUFFER_SIZE 100

Definition at line 158 of file chan_alsa.c.

Referenced by soundcard_writeframe().

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

Referenced by autoanswer_complete().

#define MIN_SWITCH_TIME 600

Definition at line 83 of file chan_alsa.c.

Referenced by time_has_passed().

#define PERIOD_FRAMES 80

Definition at line 75 of file chan_alsa.c.

Referenced by alsa_card_init().

## Function Documentation

static int alsa_answer | ( | struct ast_channel * | c | ) | `[static]`

Definition at line 560 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.

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

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

Definition at line 521 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.

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

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

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

    00334 {
    00335    int err;
    00336    int direction;
    00337    snd_pcm_t *handle = NULL;
    00338    snd_pcm_hw_params_t *hwparams = NULL;
    00339    snd_pcm_sw_params_t *swparams = NULL;
    00340    struct pollfd pfd;
    00341    snd_pcm_uframes_t period_size = PERIOD_FRAMES * 4;
    00342    /* int period_bytes = 0; */
    00343    snd_pcm_uframes_t buffer_size = 0;
    00344
    00345    unsigned int rate = DESIRED_RATE;
    00346 #if 0
    00347    unsigned int per_min = 1;
    00348 #endif
    00349    /* unsigned int per_max = 8; */
    00350    snd_pcm_uframes_t start_threshold, stop_threshold;
    00351
    00352    err = snd_pcm_open(&handle, dev, stream, O_NONBLOCK);
    00353    if (err < 0) {
    00354       ast_log(LOG_ERROR, "snd_pcm_open failed: %s\n", snd_strerror(err));
    00355       return NULL;
    00356    } else {
    00357       ast_log(LOG_DEBUG, "Opening device %s in %s mode\n", dev, (stream == SND_PCM_STREAM_CAPTURE) ? "read" : "write");
    00358    }
    00359
    00360    snd_pcm_hw_params_alloca(&hwparams);
    00361    snd_pcm_hw_params_any(handle, hwparams);
    00362
    00363    err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
    00364    if (err < 0) {
    00365       ast_log(LOG_ERROR, "set_access failed: %s\n", snd_strerror(err));
    00366    }
    00367
    00368    err = snd_pcm_hw_params_set_format(handle, hwparams, format);
    00369    if (err < 0) {
    00370       ast_log(LOG_ERROR, "set_format failed: %s\n", snd_strerror(err));
    00371    }
    00372
    00373    err = snd_pcm_hw_params_set_channels(handle, hwparams, 1);
    00374    if (err < 0) {
    00375       ast_log(LOG_ERROR, "set_channels failed: %s\n", snd_strerror(err));
    00376    }
    00377
    00378    direction = 0;
    00379    err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, &direction);
    00380    if (rate != DESIRED_RATE) {
    00381       ast_log(LOG_WARNING, "Rate not correct, requested %d, got %d\n", DESIRED_RATE, rate);
    00382    }
    00383
    00384    direction = 0;
    00385    err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &direction);
    00386    if (err < 0) {
    00387       ast_log(LOG_ERROR, "period_size(%ld frames) is bad: %s\n", period_size, snd_strerror(err));
    00388    } else {
    00389       ast_log(LOG_DEBUG, "Period size is %d\n", err);
    00390    }
    00391
    00392    buffer_size = 4096 * 2; /* period_size * 16; */
    00393    err = snd_pcm_hw_params_set_buffer_size_near(handle, hwparams, &buffer_size);
    00394    if (err < 0) {
    00395       ast_log(LOG_WARNING, "Problem setting buffer size of %ld: %s\n", buffer_size, snd_strerror(err));
    00396    } else {
    00397       ast_log(LOG_DEBUG, "Buffer size is set to %d frames\n", err);
    00398    }
    00399
    00400 #if 0
    00401    direction = 0;
    00402    err = snd_pcm_hw_params_set_periods_min(handle, hwparams, &per_min, &direction);
    00403    if (err < 0) {
    00404       ast_log(LOG_ERROR, "periods_min: %s\n", snd_strerror(err));
    00405    }
    00406
    00407    err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &per_max, 0);
    00408    if (err < 0) {
    00409       ast_log(LOG_ERROR, "periods_max: %s\n", snd_strerror(err));
    00410    }
    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
    00418    snd_pcm_sw_params_alloca(&swparams);
    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
    00428    err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
    00429    if (err < 0) {
    00430       ast_log(LOG_ERROR, "start threshold: %s\n", snd_strerror(err));
    00431    }
    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    }
    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    }
    00450 #endif
    00451
    00452 #if 0
    00453    err = snd_pcm_sw_params_set_silence_threshold(handle, swparams, silencethreshold);
    00454    if (err < 0) {
    00455       ast_log(LOG_ERROR, "Unable to set silence threshold: %s\n", snd_strerror(err));
    00456    }
    00457 #endif
    00458    err = snd_pcm_sw_params(handle, swparams);
    00459    if (err < 0) {
    00460       ast_log(LOG_ERROR, "sw_params: %s\n", snd_strerror(err));
    00461    }
    00462
    00463    err = snd_pcm_poll_descriptors_count(handle);
    00464    if (err <= 0) {
    00465       ast_log(LOG_ERROR, "Unable to get a poll descriptors count, error is %s\n", snd_strerror(err));
    00466    }
    00467
    00468    if (err != 1) {
    00469       ast_log(LOG_DEBUG, "Can't handle more than one device\n");
    00470    }
    00471
    00472    snd_pcm_poll_descriptors(handle, &pfd, err);
    00473    ast_log(LOG_DEBUG, "Acquired fd %d from the poll descriptor\n", pfd.fd);
    00474
    00475    if (stream == SND_PCM_STREAM_CAPTURE)
    00476       readdev = pfd.fd;
    00477    else
    00478       writedev = pfd.fd;
    00479
    00480    return handle;
    00481 }

static int alsa_digit | ( | struct ast_channel * | c,
|  | char | digit |
| ) |  |  | `[static]`

Definition at line 496 of file chan_alsa.c.

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

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

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

Definition at line 739 of file chan_alsa.c.

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

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

static int alsa_hangup | ( | struct ast_channel * | c | ) | `[static]`

Definition at line 573 of file chan_alsa.c.

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

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

static int alsa_indicate | ( | struct ast_channel * | chan,
|  | int | cond |
| ) |  |  | `[static]`

Definition at line 748 of file chan_alsa.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_RINGING, AST_CONTROL_VIDUPDATE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), LOG_WARNING, and ast_channel::name.

    00749 {
    00750    int res = 0;
    00751    ast_mutex_lock(&alsalock);
    00752    switch(cond) {
    00753    case AST_CONTROL_BUSY:
    00754       res = 1;
    00755       break;
    00756    case AST_CONTROL_CONGESTION:
    00757       res = 2;
    00758       break;
    00759    case AST_CONTROL_RINGING:
    00760       res = 0;
    00761       break;
    00762    case -1:
    00763       res = -1;
    00764       break;
    00765    case AST_CONTROL_VIDUPDATE:
    00766       res = -1;
    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    if (res > -1) {
    00773       write(sndcmd[1], &res, sizeof(res));
    00774    }
    00775    ast_mutex_unlock(&alsalock);
    00776    return res;
    00777 }

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

Definition at line 779 of file chan_alsa.c.

References ast_channel_alloc(), AST_FORMAT_SLINEAR, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_setstate(), AST_STATE_DOWN, ast_strlen_zero(), ast_update_use_count(), ast_channel::context, chan_alsa_pvt::context, ast_channel::exten, chan_alsa_pvt::exten, ast_channel::fds, ast_channel::language, LOG_WARNING, ast_channel::name, ast_channel::nativeformats, chan_alsa_pvt::owner, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, usecnt_lock, and ast_channel::writeformat.

Referenced by alsa_request(), and console_dial().

    00780 {
    00781    struct ast_channel *tmp;
    00782    tmp = ast_channel_alloc(1);
    00783    if (tmp) {
    00784       tmp->tech = &alsa_tech;
    00785       snprintf(tmp->name, sizeof(tmp->name), "ALSA/%s", indevname);
    00786       tmp->type = type;
    00787       tmp->fds[0] = readdev;
    00788       tmp->nativeformats = AST_FORMAT_SLINEAR;
    00789       tmp->readformat = AST_FORMAT_SLINEAR;
    00790       tmp->writeformat = AST_FORMAT_SLINEAR;
    00791       tmp->tech_pvt = p;
    00792       if (!ast_strlen_zero(p->context))
    00793          ast_copy_string(tmp->context, p->context, sizeof(tmp->context));
    00794       if (!ast_strlen_zero(p->exten))
    00795          ast_copy_string(tmp->exten, p->exten, sizeof(tmp->exten));
    00796       if (!ast_strlen_zero(language))
    00797          ast_copy_string(tmp->language, language, sizeof(tmp->language));
    00798       p->owner = tmp;
    00799       ast_setstate(tmp, state);
    00800       ast_mutex_lock(&usecnt_lock);
    00801       usecnt++;
    00802       ast_mutex_unlock(&usecnt_lock);
    00803       ast_update_use_count();
    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 663 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.

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

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    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    ast_mutex_lock(&alsalock);
    00825    if (alsa.owner) {
    00826       ast_log(LOG_NOTICE, "Already have a call on the ALSA channel\n");
    00827       *cause = AST_CAUSE_BUSY;
    00828    } else {
    00829       tmp= alsa_new(&alsa, AST_STATE_DOWN);
    00830       if (!tmp) {
    00831          ast_log(LOG_WARNING, "Unable to create new ALSA channel\n");
    00832       }
    00833    }
    00834    ast_mutex_unlock(&alsalock);
    00835    return tmp;
    00836 }

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

Definition at line 504 of file chan_alsa.c.

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

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

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

Definition at line 599 of file chan_alsa.c.

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

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

static void answer_sound | ( | void |  | ) | `[static]`

Definition at line 551 of file chan_alsa.c.

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

    00552 {
    00553    int res;
    00554    nosound = 1;
    00555    res = 4;
    00556    write(sndcmd[1], &res, sizeof(res));
    00557
    00558 }

AST_MUTEX_DEFINE_STATIC | ( | alsalock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | usecnt_lock |  | ) |

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

Definition at line 858 of file chan_alsa.c.

References ast_strlen_zero(), MIN, and strdup.

    00859 {
    00860 #ifndef MIN
    00861 #define MIN(a,b) ((a) < (b) ? (a) : (b))
    00862 #endif
    00863    switch(state) {
    00864    case 0:
    00865       if (!ast_strlen_zero(word) && !strncasecmp(word, "on", MIN(strlen(word), 2)))
    00866          return strdup("on");
    00867    case 1:
    00868       if (!ast_strlen_zero(word) && !strncasecmp(word, "off", MIN(strlen(word), 3)))
    00869          return strdup("off");
    00870    default:
    00871       return NULL;
    00872    }
    00873    return NULL;
    00874 }

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

Definition at line 882 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.

    00883 {
    00884    int res = RESULT_SUCCESS;
    00885    if (argc != 1)
    00886       return RESULT_SHOWUSAGE;
    00887    ast_mutex_lock(&alsalock);
    00888    if (!alsa.owner) {
    00889       ast_cli(fd, "No one is calling us\n");
    00890       res = RESULT_FAILURE;
    00891    } else {
    00892       hookstate = 1;
    00893       cursound = -1;
    00894       grab_owner();
    00895       if (alsa.owner) {
    00896          struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
    00897          ast_queue_frame(alsa.owner, &f);
    00898          ast_mutex_unlock(&alsa.owner->lock);
    00899       }
    00900       answer_sound();
    00901    }
    00902    snd_pcm_prepare(alsa.icard);
    00903    snd_pcm_start(alsa.icard);
    00904    ast_mutex_unlock(&alsalock);
    00905    return RESULT_SUCCESS;
    00906 }

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

Definition at line 838 of file chan_alsa.c.

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

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

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

Definition at line 979 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.

    00980 {
    00981    char tmp[256], *tmp2;
    00982    char *mye, *myc;
    00983    char *d;
    00984    int res = RESULT_SUCCESS;
    00985    if ((argc != 1) && (argc != 2))
    00986       return RESULT_SHOWUSAGE;
    00987    ast_mutex_lock(&alsalock);
    00988    if (alsa.owner) {
    00989       if (argc == 2) {
    00990          d = argv[1];
    00991          grab_owner();
    00992          if (alsa.owner) {
    00993             struct ast_frame f = { AST_FRAME_DTMF };
    00994             while(*d) {
    00995                f.subclass = *d;
    00996                ast_queue_frame(alsa.owner, &f);
    00997                d++;
    00998             }
    00999             ast_mutex_unlock(&alsa.owner->lock);
    01000          }
    01001       } else {
    01002          ast_cli(fd, "You're already in a call.  You can use this only to dial digits until you hangup\n");
    01003          res = RESULT_FAILURE;
    01004       }
    01005    } else {
    01006       mye = exten;
    01007       myc = context;
    01008       if (argc == 2) {
    01009          char *stringp=NULL;
    01010          strncpy(tmp, argv[1], sizeof(tmp)-1);
    01011          stringp=tmp;
    01012          strsep(&stringp, "@");
    01013          tmp2 = strsep(&stringp, "@");
    01014          if (!ast_strlen_zero(tmp))
    01015             mye = tmp;
    01016          if (!ast_strlen_zero(tmp2))
    01017             myc = tmp2;
    01018       }
    01019       if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
    01020          strncpy(alsa.exten, mye, sizeof(alsa.exten)-1);
    01021          strncpy(alsa.context, myc, sizeof(alsa.context)-1);
    01022          hookstate = 1;
    01023          alsa_new(&alsa, AST_STATE_RINGING);
    01024       } else
    01025          ast_cli(fd, "No such extension '%s' in context '%s'\n", mye, myc);
    01026    }
    01027    ast_mutex_unlock(&alsalock);
    01028    return res;
    01029 }

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

Definition at line 952 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.

    00953 {
    00954    int res = RESULT_SUCCESS;
    00955    if (argc != 1)
    00956       return RESULT_SHOWUSAGE;
    00957    cursound = -1;
    00958    ast_mutex_lock(&alsalock);
    00959    if (!alsa.owner && !hookstate) {
    00960       ast_cli(fd, "No call to hangup up\n");
    00961       res = RESULT_FAILURE;
    00962    } else {
    00963       hookstate = 0;
    00964       grab_owner();
    00965       if (alsa.owner) {
    00966          ast_queue_hangup(alsa.owner);
    00967          ast_mutex_unlock(&alsa.owner->lock);
    00968       }
    00969    }
    00970    ast_mutex_unlock(&alsalock);
    00971    return res;
    00972 }

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

Definition at line 912 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.

    00913 {
    00914    int tmparg = 2;
    00915    int res = RESULT_SUCCESS;
    00916    if (argc < 2)
    00917       return RESULT_SHOWUSAGE;
    00918    ast_mutex_lock(&alsalock);
    00919    if (!alsa.owner) {
    00920       ast_cli(fd, "No one is calling us\n");
    00921       res = RESULT_FAILURE;
    00922    } else {
    00923       struct ast_frame f = { AST_FRAME_TEXT, 0 };
    00924       char text2send[256] = "";
    00925       text2send[0] = '\0';
    00926       while(tmparg < argc) {
    00927          strncat(text2send, argv[tmparg++], sizeof(text2send) - strlen(text2send) - 1);
    00928          strncat(text2send, " ", sizeof(text2send) - strlen(text2send) - 1);
    00929       }
    00930       text2send[strlen(text2send) - 1] = '\n';
    00931       f.data = text2send;
    00932       f.datalen = strlen(text2send) + 1;
    00933       grab_owner();
    00934       if (alsa.owner) {
    00935          ast_queue_frame(alsa.owner, &f);
    00936          f.frametype = AST_FRAME_CONTROL;
    00937          f.subclass = AST_CONTROL_ANSWER;
    00938          f.data = NULL;
    00939          f.datalen = 0;
    00940          ast_queue_frame(alsa.owner, &f);
    00941          ast_mutex_unlock(&alsa.owner->lock);
    00942       }
    00943    }
    00944    ast_mutex_unlock(&alsalock);
    00945    return res;
    00946 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 1127 of file chan_alsa.c.

    01128 {
    01129    return (char *) desc;
    01130 }

static void grab_owner | ( | void |  | ) | `[static]`

Definition at line 512 of file chan_alsa.c.

References alsa, ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_channel::lock, and chan_alsa_pvt::owner.

Referenced by alsa_call(), console_answer(), console_dial(), console_hangup(), and console_sendtext().

    00513 {
    00514    while(alsa.owner && ast_mutex_trylock(&alsa.owner->lock)) {
    00515       ast_mutex_unlock(&alsalock);
    00516       usleep(1);
    00517       ast_mutex_lock(&alsalock);
    00518    }
    00519 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 1137 of file chan_alsa.c.

References ASTERISK_GPL_KEY.

    01138 {
    01139    return ASTERISK_GPL_KEY;
    01140 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

Definition at line 1044 of file chan_alsa.c.

References ast_channel_register(), ast_cli_register(), ast_config_destroy(), ast_config_load(), ast_log(), ast_pthread_create, ast_true(), ast_variable_browse(), ast_verbose(), cfg, LOG_ERROR, ast_variable::name, ast_variable::next, option_verbose, sound_thread(), soundcard_init(), ast_variable::value, and VERBOSE_PREFIX_2.

    01045 {
    01046    int res;
    01047    int x;
    01048    struct ast_config *cfg;
    01049    struct ast_variable *v;
    01050    if ((cfg = ast_config_load(config))) {
    01051       v = ast_variable_browse(cfg, "general");
    01052       while(v) {
    01053          if (!strcasecmp(v->name, "autoanswer"))
    01054             autoanswer = ast_true(v->value);
    01055          else if (!strcasecmp(v->name, "silencesuppression"))
    01056             silencesuppression = ast_true(v->value);
    01057          else if (!strcasecmp(v->name, "silencethreshold"))
    01058             silencethreshold = atoi(v->value);
    01059          else if (!strcasecmp(v->name, "context"))
    01060             strncpy(context, v->value, sizeof(context)-1);
    01061          else if (!strcasecmp(v->name, "language"))
    01062             strncpy(language, v->value, sizeof(language)-1);
    01063          else if (!strcasecmp(v->name, "extension"))
    01064             strncpy(exten, v->value, sizeof(exten)-1);
    01065          else if (!strcasecmp(v->name, "input_device"))
    01066             strncpy(indevname, v->value, sizeof(indevname)-1);
    01067          else if (!strcasecmp(v->name, "output_device"))
    01068             strncpy(outdevname, v->value, sizeof(outdevname)-1);
    01069          v=v->next;
    01070       }
    01071       ast_config_destroy(cfg);
    01072    }
    01073    res = pipe(sndcmd);
    01074    if (res) {
    01075       ast_log(LOG_ERROR, "Unable to create pipe\n");
    01076       return -1;
    01077    }
    01078    res = soundcard_init();
    01079    if (res < 0) {
    01080       if (option_verbose > 1) {
    01081          ast_verbose(VERBOSE_PREFIX_2 "No sound card detected -- console channel will be unavailable\n");
    01082          ast_verbose(VERBOSE_PREFIX_2 "Turn off ALSA support by adding 'noload=chan_alsa.so' in /etc/asterisk/modules.conf\n");
    01083       }
    01084       return 0;
    01085    }
    01086
    01087    res = ast_channel_register(&alsa_tech);
    01088    if (res < 0) {
    01089       ast_log(LOG_ERROR, "Unable to register channel class '%s'\n", type);
    01090       return -1;
    01091    }
    01092    for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
    01093       ast_cli_register(myclis + x);
    01094    ast_pthread_create(&sthread, NULL, sound_thread, NULL);
    01095 #ifdef ALSA_MONITOR
    01096    if (alsa_monitor_start()) {
    01097       ast_log(LOG_ERROR, "Problem starting Monitoring\n");
    01098    }
    01099 #endif
    01100    return 0;
    01101 }

static int send_sound | ( | void |  | ) | `[static]`

Definition at line 200 of file chan_alsa.c.

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

Referenced by sound_thread().

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

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

Definition at line 265 of file chan_alsa.c.

References alsa, ast_log(), ast_select(), 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().

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

static int soundcard_init | ( | void |  | ) | `[static]`

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

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

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 1105 of file chan_alsa.c.

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

    01106 {
    01107    int x;
    01108
    01109    ast_channel_unregister(&alsa_tech);
    01110    for (x=0;x<sizeof(myclis)/sizeof(struct ast_cli_entry); x++)
    01111       ast_cli_unregister(myclis + x);
    01112    if (alsa.icard)
    01113       snd_pcm_close(alsa.icard);
    01114    if (alsa.ocard)
    01115       snd_pcm_close(alsa.ocard);
    01116    if (sndcmd[0] > 0) {
    01117       close(sndcmd[0]);
    01118       close(sndcmd[1]);
    01119    }
    01120    if (alsa.owner)
    01121       ast_softhangup(alsa.owner, AST_SOFTHANGUP_APPUNLOAD);
    01122    if (alsa.owner)
    01123       return -1;
    01124    return 0;
    01125 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 1132 of file chan_alsa.c.

    01133 {
    01134    return usecnt;
    01135 }

## Variable Documentation

struct chan_alsa_pvt alsa`[static]`

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

struct ast_channel_tech alsa_tech`[static]`

Definition at line 184 of file chan_alsa.c.

char answer_usage[]`[static]`

Initial value:

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

Definition at line 948 of file chan_alsa.c.

int autoanswer = 1`[static]`

Definition at line 164 of file chan_alsa.c.

char autoanswer_usage[]`[static]`

Initial value:

    "Usage: 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 876 of file chan_alsa.c.

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

Definition at line 109 of file chan_alsa.c.

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

Definition at line 111 of file chan_alsa.c.

Referenced by __login_exec(), acf_vmcount_exec(), action_agent_callback_login(), action_extensionstate(), action_originate(), action_redirect(), complete_context_add_ignorepat(), complete_context_add_include(), complete_context_dont_include(), complete_context_remove_extension(), directory_exec(), disa_exec(), dundi_do_lookup(), dundi_do_precache(), dundi_do_query(), dundi_lookup_exec(), dundifunc_read(), get_cid_name(), handle_context_remove_extension(), handle_show_dialplan(), hasvoicemail_exec(), load_module(), parkandannounce_exec(), pickup_exec(), process_precache(), reload_config(), retrydial_exec(), rpt_exec(), and wait_for_answer().

int cursound = -1`[static]`

Definition at line 166 of file chan_alsa.c.

const char desc[] = "ALSA Console Channel Driver"`[static]`

Definition at line 107 of file chan_alsa.c.

char dial_usage[]`[static]`

Initial value:

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

Definition at line 1031 of file chan_alsa.c.

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

Definition at line 113 of file chan_alsa.c.

Referenced by __ast_pbx_run(), action_agent_callback_login(), action_extensionstate(), action_originate(), action_redirect(), ast_context_remove_extension2(), ast_feature_interpret(), ast_ivr_menu_run_internal(), ast_park_call(), ast_waitstream_exten(), check_access(), complete_context_remove_extension(), complete_dpreply(), disa_exec(), do_parking_thread(), get_cid_name(), handle_context_add_extension(), handle_context_remove_extension(), handle_show_dialplan(), handle_showfeatures(), leave_voicemail(), load_config(), mgcp_ss(), park_exec(), parkandannounce_exec(), pickup_exec(), remap_feature(), rpt_exec(), skinny_ss(), ss_thread(), and unmap_features().

snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE`[static]`

Definition at line 86 of file chan_alsa.c.

Referenced by acf_strftime(), ast_getformatbyname(), ast_monitor_stop(), ast_parse_allow_disallow(), ast_rtp_lookup_mime_multiple(), build_user(), check_header(), handle_saydatetime(), handle_showfeatures(), handle_showmancmds(), handle_showmanconn(), reload_config(), sayunixtime_exec(), set_config(), socket_read(), start_monitor_action(), start_monitor_exec(), and update_common_options().

char hangup_usage[]`[static]`

Initial value:

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

Definition at line 974 of file chan_alsa.c.

int hookstate = 0`[static]`

Definition at line 115 of file chan_alsa.c.

char indevname[50] = ALSA_INDEV`[static]`

Definition at line 92 of file chan_alsa.c.

char language[MAX_LANGUAGE] = ""`[static]`

Definition at line 112 of file chan_alsa.c.

Referenced by load_module().

struct ast_cli_entry myclis[]`[static]`

Definition at line 1036 of file chan_alsa.c.

int nosound = 0`[static]`

Definition at line 170 of file chan_alsa.c.

int offset = 0`[static]`

Definition at line 169 of file chan_alsa.c.

Referenced by 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_pt(), ast_say_date_with_format_tw(), ast_slinfactory_read(), au_seek(), au_tell(), cliinput(), copy_request(), format_uptimestr(), function_remote(), g729_seek(), g729_tell(), gsm_seek(), gsm_tell(), h263_tell(), ilbc_seek(), ilbc_tell(), macro_exec(), mp3_exec(), NBScat_exec(), pbx_retrieve_variable(), pbx_substitute_variables_helper_full(), pcm_seek(), pcm_tell(), send_waveform_to_channel(), slinear_seek(), slinear_tell(), strcasestr(), vox_seek(), vox_tell(), wav_seek(), and wav_tell().

char outdevname[50] = ALSA_OUTDEV`[static]`

Definition at line 93 of file chan_alsa.c.

int readdev = -1`[static]`

Definition at line 161 of file chan_alsa.c.

int sampsent = 0`[static]`

Definition at line 167 of file chan_alsa.c.

char sendtext_usage[]`[static]`

Initial value:

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

Definition at line 908 of file chan_alsa.c.

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

Definition at line 117 of file chan_alsa.c.

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

int silencelen = 0`[static]`

Definition at line 168 of file chan_alsa.c.

int silencesuppression = 0`[static]`

Definition at line 100 of file chan_alsa.c.

int silencethreshold = 1000`[static]`

Definition at line 101 of file chan_alsa.c.

Referenced by do_waiting().

int sndcmd[2]`[static]`

Definition at line 137 of file chan_alsa.c.

struct sound sounds[]`[static]`

Definition at line 128 of file chan_alsa.c.

pthread_t sthread

Definition at line 156 of file chan_alsa.c.

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

Definition at line 108 of file chan_alsa.c.

const char type[] = "Console"`[static]`

Definition at line 106 of file chan_alsa.c.

int usecnt`[static]`

Definition at line 99 of file chan_alsa.c.

int writedev = -1`[static]`

Definition at line 162 of file chan_alsa.c.