Fri Feb 19 17:12:55 2010

Asterisk developer's documentation


chan_alsa.c File Reference

ALSA sound card channel driver. More...

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

Go to the source code of this file.

Data Structures

struct  chan_alsa_pvt
struct  sound

Defines

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

Functions

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

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ALSA Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static struct chan_alsa_pvt alsa
static struct ast_channel_tech alsa_tech
static ast_mutex_t alsalock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char answer_usage []
static const struct ast_module_infoast_module_info = &__mod_info
static int autoanswer = 1
static const char autoanswer_usage []
static struct ast_cli_entry cli_alsa []
static struct ast_cli_entry cli_alsa_answer_deprecated
static struct ast_cli_entry cli_alsa_autoanswer_deprecated
static struct ast_cli_entry cli_alsa_dial_deprecated
static struct ast_cli_entry cli_alsa_hangup_deprecated
static struct ast_cli_entry cli_alsa_send_text_deprecated
static const char config [] = "alsa.conf"
static char context [AST_MAX_CONTEXT] = "default"
static int cursound = -1
static struct ast_jb_conf default_jbconf
static char dial_usage []
static char exten [AST_MAX_EXTENSION] = "s"
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE
static struct ast_jb_conf global_jbconf
static char hangup_usage []
static int hookstate = 0
static char indevname [50] = ALSA_INDEV
static char language [MAX_LANGUAGE] = ""
static char mohinterpret [MAX_MUSICCLASS]
static int nosound = 0
static int offset = 0
static char outdevname [50] = ALSA_OUTDEV
static int readdev = -1
static int sampsent = 0
static char sendtext_usage []
static short silence [FRAME_SIZE] = { 0, }
static int silencelen = 0
static int silencesuppression = 0
static int silencethreshold = 1000
static int sndcmd [2]
static struct sound sounds []
pthread_t sthread
static const char tdesc [] = "ALSA Console Channel Driver"
static int writedev = -1


Detailed Description

ALSA sound card channel driver.

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

Definition in file chan_alsa.c.


Define Documentation

#define ALSA_INDEV   "default"

Definition at line 87 of file chan_alsa.c.

#define ALSA_OUTDEV   "default"

Definition at line 88 of file chan_alsa.c.

#define ALSA_PCM_NEW_HW_PARAMS_API

Definition at line 47 of file chan_alsa.c.

#define ALSA_PCM_NEW_SW_PARAMS_API

Definition at line 48 of file chan_alsa.c.

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

Definition at line 98 of file chan_alsa.c.

#define DEBUG   0

Definition at line 85 of file chan_alsa.c.

#define DESIRED_RATE   8000

Definition at line 89 of file chan_alsa.c.

Referenced by alsa_card_init().

#define FRAME_SIZE   160

Definition at line 92 of file chan_alsa.c.

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

#define MAX_BUFFER_SIZE   100

Definition at line 172 of file chan_alsa.c.

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

Referenced by autoanswer_complete().

#define MIN_SWITCH_TIME   600

Definition at line 101 of file chan_alsa.c.

#define PERIOD_FRAMES   80

Definition at line 93 of file chan_alsa.c.

Referenced by alsa_card_init().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1392 of file chan_alsa.c.

static void __unreg_module ( void   )  [static]

Definition at line 1392 of file chan_alsa.c.

static int alsa_answer ( struct ast_channel c  )  [static]

Definition at line 561 of file chan_alsa.c.

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

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

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

Definition at line 518 of file chan_alsa.c.

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

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

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

Definition at line 348 of file chan_alsa.c.

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

Referenced by soundcard_init().

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

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

Definition at line 494 of file chan_alsa.c.

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

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

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

Definition at line 742 of file chan_alsa.c.

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

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

static int alsa_hangup ( struct ast_channel c  )  [static]

Definition at line 574 of file chan_alsa.c.

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

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

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

Definition at line 751 of file chan_alsa.c.

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

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

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

Definition at line 799 of file chan_alsa.c.

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

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

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

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

Definition at line 667 of file chan_alsa.c.

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

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

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

Definition at line 832 of file chan_alsa.c.

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

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

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

Definition at line 503 of file chan_alsa.c.

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

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

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

Definition at line 598 of file chan_alsa.c.

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

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

static void answer_sound ( void   )  [static]

Definition at line 550 of file chan_alsa.c.

References ast_log(), errno, and LOG_WARNING.

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

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

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

Definition at line 901 of file chan_alsa.c.

References ast_strdup, ast_strlen_zero(), and MIN.

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

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

Definition at line 957 of file chan_alsa.c.

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

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

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

Definition at line 925 of file chan_alsa.c.

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

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

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

Definition at line 881 of file chan_alsa.c.

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

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

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

Definition at line 856 of file chan_alsa.c.

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

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

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

Definition at line 1196 of file chan_alsa.c.

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

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

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

Definition at line 1139 of file chan_alsa.c.

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

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

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

Definition at line 1107 of file chan_alsa.c.

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

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

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

Definition at line 1079 of file chan_alsa.c.

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

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

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

Definition at line 1034 of file chan_alsa.c.

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

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

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

Definition at line 993 of file chan_alsa.c.

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

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

static void grab_owner ( void   )  [static]

Definition at line 511 of file chan_alsa.c.

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

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

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

static int load_module ( void   )  [static]

Definition at line 1304 of file chan_alsa.c.

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

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

static int send_sound ( void   )  [static]

Definition at line 214 of file chan_alsa.c.

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

Referenced by sound_thread().

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

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

Definition at line 278 of file chan_alsa.c.

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

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

static int soundcard_init ( void   )  [static]

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

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

static int unload_module ( void   )  [static]

Definition at line 1372 of file chan_alsa.c.

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

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


Variable Documentation

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

Definition at line 1392 of file chan_alsa.c.

struct chan_alsa_pvt alsa [static]

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

struct ast_channel_tech alsa_tech [static]

Definition at line 198 of file chan_alsa.c.

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

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

Definition at line 119 of file chan_alsa.c.

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

char answer_usage[] [static]

Initial value:

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

Definition at line 1075 of file chan_alsa.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

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

struct ast_cli_entry cli_alsa[] [static]

Definition at line 1282 of file chan_alsa.c.

Referenced by load_module(), and unload_module().

struct ast_cli_entry cli_alsa_answer_deprecated [static]

Initial value:

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

Definition at line 1257 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_autoanswer_deprecated [static]

Initial value:

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

Definition at line 1277 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_dial_deprecated [static]

Initial value:

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

Definition at line 1267 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_hangup_deprecated [static]

Initial value:

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

Definition at line 1262 of file chan_alsa.c.

struct ast_cli_entry cli_alsa_send_text_deprecated [static]

Initial value:

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

Definition at line 1272 of file chan_alsa.c.

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

Definition at line 122 of file chan_alsa.c.

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

Definition at line 124 of file chan_alsa.c.

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

int cursound = -1 [static]

Definition at line 180 of file chan_alsa.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 77 of file chan_alsa.c.

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

char dial_usage[] [static]

Initial value:

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

Definition at line 1253 of file chan_alsa.c.

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

Definition at line 126 of file chan_alsa.c.

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

snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE [static]

Definition at line 104 of file chan_alsa.c.

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

struct ast_jb_conf global_jbconf [static]

Definition at line 83 of file chan_alsa.c.

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

char hangup_usage[] [static]

Initial value:

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

Definition at line 1135 of file chan_alsa.c.

int hookstate = 0 [static]

Definition at line 129 of file chan_alsa.c.

char indevname[50] = ALSA_INDEV [static]

Definition at line 109 of file chan_alsa.c.

char language[MAX_LANGUAGE] = "" [static]

Definition at line 125 of file chan_alsa.c.

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

char mohinterpret[MAX_MUSICCLASS] [static]

Definition at line 127 of file chan_alsa.c.

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

int nosound = 0 [static]

Definition at line 184 of file chan_alsa.c.

int offset = 0 [static]

Definition at line 183 of file chan_alsa.c.

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

char outdevname[50] = ALSA_OUTDEV [static]

Definition at line 110 of file chan_alsa.c.

int readdev = -1 [static]

Definition at line 175 of file chan_alsa.c.

int sampsent = 0 [static]

Definition at line 181 of file chan_alsa.c.

char sendtext_usage[] [static]

Initial value:

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

Definition at line 989 of file chan_alsa.c.

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

Definition at line 131 of file chan_alsa.c.

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

int silencelen = 0 [static]

Definition at line 182 of file chan_alsa.c.

int silencesuppression = 0 [static]

Definition at line 116 of file chan_alsa.c.

int silencethreshold = 1000 [static]

Definition at line 117 of file chan_alsa.c.

Referenced by ast_record_review(), and do_waiting().

int sndcmd[2] [static]

Definition at line 151 of file chan_alsa.c.

struct sound sounds[] [static]

Definition at line 142 of file chan_alsa.c.

Referenced by send_sound(), and sound_thread().

pthread_t sthread

Definition at line 170 of file chan_alsa.c.

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

Definition at line 121 of file chan_alsa.c.

int writedev = -1 [static]

Definition at line 176 of file chan_alsa.c.


Generated on Fri Feb 19 17:12:55 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7