Wed Apr 6 11:29:54 2011

Asterisk developer's documentation


chan_console.c File Reference

Cross-platform console channel driver. More...

#include "asterisk.h"
#include <sys/signal.h>
#include <portaudio.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/causes.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/astobj2.h"

Go to the source code of this file.

Data Structures

struct  console_pvt
 Console pvt structure. More...
#define V_BEGIN   " --- <(\"<) --- "
 Dance, Kirby, Dance!
#define V_END   " --- (>\")> ---\n"
static int console_answer (struct ast_channel *c)
static int console_call (struct ast_channel *c, char *dest, int timeout)
static int console_digit_begin (struct ast_channel *c, char digit)
static int console_digit_end (struct ast_channel *c, char digit, unsigned int duration)
static int console_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int console_hangup (struct ast_channel *c)
static int console_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen)
static struct ast_frameconsole_read (struct ast_channel *chan)
static struct ast_channelconsole_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static int console_text (struct ast_channel *c, const char *text)
static int console_write (struct ast_channel *chan, struct ast_frame *f)

Defines

#define console_pvt_lock(pvt)   ao2_lock(pvt)
 lock a console_pvt struct
#define console_pvt_unlock(pvt)   ao2_unlock(pvt)
 unlock a console_pvt struct
#define INPUT_CHANNELS   1
 Mono Input.
#define NUM_PVT_BUCKETS   7
#define NUM_SAMPLES   320
 The number of samples to configure the portaudio stream for.
#define OUTPUT_CHANNELS   1
 Mono Output.
#define SAMPLE_RATE   16000
 The sample rate to request from PortAudio.
#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )
 Formats natively supported by this module.
#define TEXT_SIZE   256
 Maximum text message length.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * ast_ext_ctx (struct console_pvt *pvt, const char *src, char **ext, char **ctx)
static void build_device (struct ast_config *cfg, const char *name)
static char * cli_console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 answer command from the console
static char * cli_console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Console send text CLI command.
static char * cli_list_available (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_list_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_channelconsole_new (struct console_pvt *pvt, const char *ext, const char *ctx, int state, const char *linkedid)
static void destroy_pvts (void)
static struct console_pvtfind_pvt (const char *name)
static struct console_pvtget_active_pvt (void)
static int init_pvt (struct console_pvt *pvt, const char *name)
static int load_config (int reload)
 Load the configuration.
static int load_module (void)
static int open_stream (struct console_pvt *pvt)
static int pvt_cmp_cb (void *obj, void *arg, int flags)
static void pvt_destructor (void *obj)
static int pvt_hash_cb (const void *obj, const int flags)
static int pvt_mark_destroy_cb (void *obj, void *arg, int flags)
static struct console_pvtref_pvt (struct console_pvt *pvt)
static int reload (void)
static void set_active (struct console_pvt *pvt, const char *value)
static void set_pvt_defaults (struct console_pvt *pvt)
 Set default values for a pvt struct.
static int start_stream (struct console_pvt *pvt)
static int stop_stream (struct console_pvt *pvt)
static void stop_streams (void)
static void store_callerid (struct console_pvt *pvt, const char *value)
static void store_config_core (struct console_pvt *pvt, const char *var, const char *value)
 Store a configuration parameter in a pvt struct.
static void * stream_monitor (void *data)
 Stream monitor thread.
static int unload_module (void)
static struct console_pvtunref_pvt (struct console_pvt *pvt)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static ast_rwlock_t active_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER }
static struct console_pvtactive_pvt
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_console []
static const char config_file [] = "console.conf"
static struct ast_channel_tech console_tech
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration.
static struct ast_jb_conf global_jbconf
static struct console_pvt globals
 Console pvt structure.
static ast_mutex_t globals_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static struct ao2_containerpvts


Detailed Description

Cross-platform console channel driver.

Author:
Russell Bryant <russell@digium.com>
Note:
Some of the code in this file came from chan_oss and chan_alsa. chan_oss, Mark Spencer <markster@digium.com> chan_oss, Luigi Rizzo chan_alsa, Matthew Fredrickson <creslin@digium.com>
ExtRef:
Portaudio http://www.portaudio.com/
To install portaudio v19 from svn, check it out using the following command:

Note:
Since this works with any audio system that libportaudio supports, including ALSA and OSS, this may someday deprecate chan_alsa and chan_oss. However, before that can be done, it needs to *at least* have all of the features that these other channel drivers have. The features implemented in at least one of the other console channel drivers that are not yet implemented here are:

Definition in file chan_console.c.


Define Documentation

#define console_pvt_lock ( pvt   )     ao2_lock(pvt)

lock a console_pvt struct

Definition at line 224 of file chan_console.c.

Referenced by build_device(), cli_console_active(), cli_console_dial(), cli_list_devices(), console_call(), console_request(), start_stream(), and stop_stream().

#define console_pvt_unlock ( pvt   )     ao2_unlock(pvt)

unlock a console_pvt struct

Definition at line 227 of file chan_console.c.

Referenced by build_device(), cli_console_active(), cli_console_dial(), cli_list_devices(), console_call(), console_request(), start_stream(), and stop_stream().

#define INPUT_CHANNELS   1

Mono Input.

Definition at line 92 of file chan_console.c.

Referenced by open_stream().

#define NUM_PVT_BUCKETS   7

Definition at line 166 of file chan_console.c.

Referenced by load_module().

#define NUM_SAMPLES   320

The number of samples to configure the portaudio stream for.

320 samples (20 ms) is the most common frame size in Asterisk. So, the code in this module reads 320 sample frames from the portaudio stream and queues them up on the Asterisk channel. Frames of any size can be written to a portaudio stream, but the portaudio documentation does say that for high performance applications, the data should be written to Pa_WriteStream in the same size as what is used to initialize the stream.

Definition at line 89 of file chan_console.c.

Referenced by open_stream(), and stream_monitor().

#define OUTPUT_CHANNELS   1

Mono Output.

Definition at line 95 of file chan_console.c.

Referenced by open_stream().

#define SAMPLE_RATE   16000

The sample rate to request from PortAudio.

Todo:
Make this optional. If this is only going to talk to 8 kHz endpoints, then it makes sense to use 8 kHz natively.

Definition at line 77 of file chan_console.c.

Referenced by ast_tone_detect_init(), goertzel_init(), and open_stream().

#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )

Formats natively supported by this module.

Definition at line 204 of file chan_console.c.

Referenced by console_request().

#define TEXT_SIZE   256

Maximum text message length.

Note:
This should be changed if there is a common definition somewhere that defines the maximum length of a text message.

Definition at line 102 of file chan_console.c.

Referenced by cli_console_sendtext(), and console_sendtext().

#define V_BEGIN   " --- <(\"<) --- "

Dance, Kirby, Dance!

Definition at line 105 of file chan_console.c.

Referenced by cli_console_mute(), console_answer(), console_call(), console_digit_begin(), console_digit_end(), console_hangup(), console_indicate(), and console_text().

#define V_END   " --- (>\")> ---\n"

Definition at line 106 of file chan_console.c.

Referenced by cli_console_mute(), console_answer(), console_call(), console_digit_begin(), console_digit_end(), console_hangup(), console_indicate(), and console_text().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1529 of file chan_console.c.

static void __unreg_module ( void   )  [static]

Definition at line 1529 of file chan_console.c.

static char* ast_ext_ctx ( struct console_pvt pvt,
const char *  src,
char **  ext,
char **  ctx 
) [static]

split a string in extension-context, returns pointers to malloc'ed strings. If we do not have 'overridecontext' then the last @ is considered as a context separator, and the context is overridden. This is usually not very necessary as you can play with the dialplan, and it is nice not to need it because you have '@' in SIP addresses. Return value is the buffer address.

Note:
came from chan_oss

Definition at line 657 of file chan_console.c.

References ast_strdup, and console_pvt::overridecontext.

Referenced by cli_console_dial(), console_dial(), and console_transfer().

00658 {
00659    if (ext == NULL || ctx == NULL)
00660       return NULL;         /* error */
00661 
00662    *ext = *ctx = NULL;
00663 
00664    if (src && *src != '\0')
00665       *ext = ast_strdup(src);
00666 
00667    if (*ext == NULL)
00668       return NULL;
00669 
00670    if (!pvt->overridecontext) {
00671       /* parse from the right */
00672       *ctx = strrchr(*ext, '@');
00673       if (*ctx)
00674          *(*ctx)++ = '\0';
00675    }
00676 
00677    return *ext;
00678 }

static void build_device ( struct ast_config cfg,
const char *  name 
) [static]

Definition at line 1329 of file chan_console.c.

References ao2_alloc, ao2_link, ast_variable_browse(), console_pvt_lock, console_pvt_unlock, find_pvt(), init_pvt(), ast_variable::name, ast_variable::next, pvt_destructor(), pvts, set_pvt_defaults(), store_config_core(), unref_pvt(), and ast_variable::value.

Referenced by load_config(), and reload_config().

01330 {
01331    struct ast_variable *v;
01332    struct console_pvt *pvt;
01333    int new = 0;
01334 
01335    if ((pvt = find_pvt(name))) {
01336       console_pvt_lock(pvt);
01337       set_pvt_defaults(pvt);
01338       pvt->destroy = 0;
01339    } else {
01340       if (!(pvt = ao2_alloc(sizeof(*pvt), pvt_destructor)))
01341          return;
01342       init_pvt(pvt, name);
01343       set_pvt_defaults(pvt);
01344       new = 1;
01345    }
01346 
01347    for (v = ast_variable_browse(cfg, name); v; v = v->next)
01348       store_config_core(pvt, v->name, v->value);
01349 
01350    if (new)
01351       ao2_link(pvts, pvt);
01352    else
01353       console_pvt_unlock(pvt);
01354    
01355    unref_pvt(pvt);
01356 }

static char* cli_console_active ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1152 of file chan_console.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_strdup, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_pvt_lock, console_pvt_unlock, ast_cli_args::fd, find_pvt(), get_active_pvt(), ast_cli_args::n, console_pvt::name, ast_cli_args::pos, pvts, set_active(), unref_pvt(), ast_cli_entry::usage, and ast_cli_args::word.

01153 {
01154    struct console_pvt *pvt;
01155 
01156    switch (cmd) {
01157    case CLI_INIT:
01158       e->command = "console {set|show} active";
01159       e->usage =
01160          "Usage: console {set|show} active [<device>]\n"
01161          "       Set or show the active console device for the Asterisk CLI.\n";
01162       return NULL;
01163    case CLI_GENERATE:
01164       if (a->pos == e->args) {
01165          struct ao2_iterator i;
01166          int x = 0;
01167          char *res = NULL;
01168          i = ao2_iterator_init(pvts, 0);
01169          while ((pvt = ao2_iterator_next(&i))) {
01170             if (++x > a->n && !strncasecmp(pvt->name, a->word, strlen(a->word)))
01171                res = ast_strdup(pvt->name);
01172             unref_pvt(pvt);
01173             if (res) {
01174                ao2_iterator_destroy(&i);
01175                return res;
01176             }
01177          }
01178          ao2_iterator_destroy(&i);
01179       }
01180       return NULL;
01181    }
01182 
01183    if (a->argc < e->args)
01184       return CLI_SHOWUSAGE;
01185 
01186    if (a->argc == 3) {
01187       pvt = get_active_pvt();
01188 
01189       if (!pvt)
01190          ast_cli(a->fd, "No device is currently set as the active console device.\n");
01191       else {
01192          console_pvt_lock(pvt);
01193          ast_cli(a->fd, "The active console device is '%s'.\n", pvt->name);
01194          console_pvt_unlock(pvt);
01195          pvt = unref_pvt(pvt);
01196       }
01197 
01198       return CLI_SUCCESS;
01199    }
01200 
01201    if (!(pvt = find_pvt(a->argv[e->args - 1]))) {
01202       ast_cli(a->fd, "Could not find a device called '%s'.\n", a->argv[e->args]);
01203       return CLI_FAILURE;
01204    }
01205 
01206    set_active(pvt, "yes");
01207 
01208    console_pvt_lock(pvt);
01209    ast_cli(a->fd, "The active console device has been set to '%s'\n", pvt->name);
01210    console_pvt_unlock(pvt);
01211 
01212    unref_pvt(pvt);
01213 
01214    return CLI_SUCCESS;
01215 }

static char* cli_console_answer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

answer command from the console

Definition at line 1033 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_ANSWER, ast_indicate(), ast_queue_control(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

01034 {
01035    struct console_pvt *pvt = get_active_pvt();
01036 
01037    switch (cmd) {
01038    case CLI_INIT:
01039       e->command = "console answer";
01040       e->usage =
01041          "Usage: console answer\n"
01042          "       Answers an incoming call on the console channel.\n";
01043       return NULL;
01044 
01045    case CLI_GENERATE:
01046       return NULL;   /* no completion */
01047    }
01048 
01049    if (!pvt) {
01050       ast_cli(a->fd, "No console device is set as active\n");
01051       return CLI_FAILURE;
01052    }
01053 
01054    if (a->argc != e->args) {
01055       unref_pvt(pvt);
01056       return CLI_SHOWUSAGE;
01057    }
01058 
01059    if (!pvt->owner) {
01060       ast_cli(a->fd, "No one is calling us\n");
01061       unref_pvt(pvt);
01062       return CLI_FAILURE;
01063    }
01064 
01065    pvt->hookstate = 1;
01066 
01067    ast_indicate(pvt->owner, -1);
01068 
01069    ast_queue_control(pvt->owner, AST_CONTROL_ANSWER);
01070 
01071    unref_pvt(pvt);
01072 
01073    return CLI_SUCCESS;
01074 }

static char* cli_console_autoanswer ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 691 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), console_pvt::autoanswer, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), unref_pvt(), and ast_cli_entry::usage.

00693 {
00694    struct console_pvt *pvt = get_active_pvt();
00695    char *res = CLI_SUCCESS;
00696 
00697    switch (cmd) {
00698    case CLI_INIT:
00699       e->command = "console {set|show} autoanswer [on|off]";
00700       e->usage =
00701          "Usage: console {set|show} autoanswer [on|off]\n"
00702          "       Enables or disables autoanswer feature.  If used without\n"
00703          "       argument, displays the current on/off status of autoanswer.\n"
00704          "       The default value of autoanswer is in 'oss.conf'.\n";
00705       return NULL;
00706 
00707    case CLI_GENERATE:
00708       return NULL;
00709    }
00710 
00711    if (!pvt) {
00712       ast_cli(a->fd, "No console device is set as active.\n");
00713       return CLI_FAILURE;
00714    }
00715 
00716    if (a->argc == e->args - 1) {
00717       ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
00718       unref_pvt(pvt);
00719       return CLI_SUCCESS;
00720    }
00721 
00722    if (a->argc != e->args) {
00723       unref_pvt(pvt);
00724       return CLI_SHOWUSAGE;
00725    }
00726 
00727    if (!strcasecmp(a->argv[e->args-1], "on"))
00728       pvt->autoanswer = 1;
00729    else if (!strcasecmp(a->argv[e->args - 1], "off"))
00730       pvt->autoanswer = 0;
00731    else
00732       res = CLI_SHOWUSAGE;
00733 
00734    unref_pvt(pvt);
00735 
00736    return CLI_SUCCESS;
00737 }

static char* cli_console_dial ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 775 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_debug, ast_exists_extension(), ast_ext_ctx(), AST_FRAME_DTMF, ast_queue_frame(), AST_STATE_RINGING, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_new(), console_pvt_lock, console_pvt_unlock, console_pvt::context, ext, console_pvt::exten, f, ast_cli_args::fd, free, get_active_pvt(), console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

00776 {
00777    char *s = NULL;
00778    const char *mye = NULL, *myc = NULL; 
00779    struct console_pvt *pvt = get_active_pvt();
00780 
00781    if (cmd == CLI_INIT) {
00782       e->command = "console dial";
00783       e->usage =
00784          "Usage: console dial [extension[@context]]\n"
00785          "       Dials a given extension (and context if specified)\n";
00786       return NULL;
00787    } else if (cmd == CLI_GENERATE)
00788       return NULL;
00789 
00790    if (!pvt) {
00791       ast_cli(a->fd, "No console device is currently set as active\n");
00792       return CLI_FAILURE;
00793    }
00794    
00795    if (a->argc > e->args + 1)
00796       return CLI_SHOWUSAGE;
00797 
00798    if (pvt->owner) { /* already in a call */
00799       int i;
00800       struct ast_frame f = { AST_FRAME_DTMF };
00801       const char *s;
00802 
00803       if (a->argc == e->args) {  /* argument is mandatory here */
00804          ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
00805          unref_pvt(pvt);
00806          return CLI_FAILURE;
00807       }
00808       s = a->argv[e->args];
00809       /* send the string one char at a time */
00810       for (i = 0; i < strlen(s); i++) {
00811          f.subclass.integer = s[i];
00812          ast_queue_frame(pvt->owner, &f);
00813       }
00814       unref_pvt(pvt);
00815       return CLI_SUCCESS;
00816    }
00817 
00818    /* if we have an argument split it into extension and context */
00819    if (a->argc == e->args + 1) {
00820       char *ext = NULL, *con = NULL;
00821       s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
00822       ast_debug(1, "provided '%s', exten '%s' context '%s'\n", 
00823          a->argv[e->args], mye, myc);
00824       mye = ext;
00825       myc = con;
00826    }
00827 
00828    /* supply default values if needed */
00829    if (ast_strlen_zero(mye))
00830       mye = pvt->exten;
00831    if (ast_strlen_zero(myc))
00832       myc = pvt->context;
00833 
00834    if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
00835       console_pvt_lock(pvt);
00836       pvt->hookstate = 1;
00837       console_new(pvt, mye, myc, AST_STATE_RINGING, NULL);
00838       console_pvt_unlock(pvt);
00839    } else
00840       ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
00841 
00842    free(s);
00843 
00844    unref_pvt(pvt);
00845 
00846    return CLI_SUCCESS;
00847 }

static char* cli_console_flash ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 739 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_FLASH, ast_queue_control(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

00740 {
00741    struct console_pvt *pvt = get_active_pvt();
00742 
00743    if (cmd == CLI_INIT) {
00744       e->command = "console flash";
00745       e->usage =
00746          "Usage: console flash\n"
00747          "       Flashes the call currently placed on the console.\n";
00748       return NULL;
00749    } else if (cmd == CLI_GENERATE)
00750       return NULL;
00751 
00752    if (!pvt) {
00753       ast_cli(a->fd, "No console device is set as active\n");
00754       return CLI_FAILURE;
00755    }
00756 
00757    if (a->argc != e->args)
00758       return CLI_SHOWUSAGE;
00759 
00760    if (!pvt->owner) {
00761       ast_cli(a->fd, "No call to flash\n");
00762       unref_pvt(pvt);
00763       return CLI_FAILURE;
00764    }
00765 
00766    pvt->hookstate = 0;
00767 
00768    ast_queue_control(pvt->owner, AST_CONTROL_FLASH);
00769 
00770    unref_pvt(pvt);
00771 
00772    return CLI_SUCCESS;
00773 }

static char* cli_console_hangup ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 849 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), ast_queue_hangup(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

00850 {
00851    struct console_pvt *pvt = get_active_pvt();
00852 
00853    if (cmd == CLI_INIT) {
00854       e->command = "console hangup";
00855       e->usage =
00856          "Usage: console hangup\n"
00857          "       Hangs up any call currently placed on the console.\n";
00858       return NULL;
00859    } else if (cmd == CLI_GENERATE)
00860       return NULL;
00861 
00862    if (!pvt) {
00863       ast_cli(a->fd, "No console device is set as active\n");
00864       return CLI_FAILURE;
00865    }
00866    
00867    if (a->argc != e->args)
00868       return CLI_SHOWUSAGE;
00869 
00870    if (!pvt->owner && !pvt->hookstate) {
00871       ast_cli(a->fd, "No call to hang up\n");
00872       unref_pvt(pvt);
00873       return CLI_FAILURE;
00874    }
00875 
00876    pvt->hookstate = 0;
00877    if (pvt->owner)
00878       ast_queue_hangup(pvt->owner);
00879 
00880    unref_pvt(pvt);
00881 
00882    return CLI_SUCCESS;
00883 }

static char* cli_console_mute ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 885 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_verb, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), console_pvt::muted, unref_pvt(), ast_cli_entry::usage, V_BEGIN, and V_END.

00886 {
00887    const char *s;
00888    struct console_pvt *pvt = get_active_pvt();
00889    char *res = CLI_SUCCESS;
00890 
00891    if (cmd == CLI_INIT) {
00892       e->command = "console {mute|unmute}";
00893       e->usage =
00894          "Usage: console {mute|unmute}\n"
00895          "       Mute/unmute the microphone.\n";
00896       return NULL;
00897    } else if (cmd == CLI_GENERATE)
00898       return NULL;
00899 
00900    if (!pvt) {
00901       ast_cli(a->fd, "No console device is set as active\n");
00902       return CLI_FAILURE;
00903    }
00904 
00905    if (a->argc != e->args)
00906       return CLI_SHOWUSAGE;
00907 
00908    s = a->argv[e->args-1];
00909    if (!strcasecmp(s, "mute"))
00910       pvt->muted = 1;
00911    else if (!strcasecmp(s, "unmute"))
00912       pvt->muted = 0;
00913    else
00914       res = CLI_SHOWUSAGE;
00915 
00916    ast_verb(1, V_BEGIN "The Console is now %s" V_END, 
00917       pvt->muted ? "Muted" : "Unmuted");
00918 
00919    unref_pvt(pvt);
00920 
00921    return res;
00922 }

static char* cli_console_sendtext ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Console send text CLI command.

Note:
concatenate all arguments into a single string. argv is NULL-terminated so we can use it right away

Definition at line 1082 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join(), ast_queue_frame(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, get_active_pvt(), len(), console_pvt::owner, TEXT_SIZE, unref_pvt(), and ast_cli_entry::usage.

01083 {
01084    char buf[TEXT_SIZE];
01085    struct console_pvt *pvt = get_active_pvt();
01086    struct ast_frame f = {
01087       .frametype = AST_FRAME_TEXT,
01088       .data.ptr = buf,
01089       .src = "console_send_text",
01090    };
01091    int len;
01092 
01093    if (cmd == CLI_INIT) {
01094       e->command = "console send text";
01095       e->usage =
01096          "Usage: console send text <message>\n"
01097          "       Sends a text message for display on the remote terminal.\n";
01098       return NULL;
01099    } else if (cmd == CLI_GENERATE)
01100       return NULL;
01101 
01102    if (!pvt) {
01103       ast_cli(a->fd, "No console device is set as active\n");
01104       return CLI_FAILURE;
01105    }
01106 
01107    if (a->argc < e->args + 1) {
01108       unref_pvt(pvt);
01109       return CLI_SHOWUSAGE;
01110    }
01111 
01112    if (!pvt->owner) {
01113       ast_cli(a->fd, "Not in a call\n");
01114       unref_pvt(pvt);
01115       return CLI_FAILURE;
01116    }
01117 
01118    ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
01119    if (ast_strlen_zero(buf)) {
01120       unref_pvt(pvt);
01121       return CLI_SHOWUSAGE;
01122    }
01123 
01124    len = strlen(buf);
01125    buf[len] = '\n';
01126    f.datalen = len + 1;
01127 
01128    ast_queue_frame(pvt->owner, &f);
01129 
01130    unref_pvt(pvt);
01131 
01132    return CLI_SUCCESS;
01133 }

static char* cli_list_available ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 924 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, and ast_cli_entry::usage.

00925 {
00926    PaDeviceIndex idx, num, def_input, def_output;
00927 
00928    if (cmd == CLI_INIT) {
00929       e->command = "console list available";
00930       e->usage =
00931          "Usage: console list available\n"
00932          "       List all available devices.\n";
00933       return NULL;
00934    } else if (cmd == CLI_GENERATE)
00935       return NULL;
00936 
00937    if (a->argc != e->args)
00938       return CLI_SHOWUSAGE;
00939 
00940    ast_cli(a->fd, "\n"
00941                "=============================================================\n"
00942                "=== Available Devices =======================================\n"
00943                "=============================================================\n"
00944                "===\n");
00945 
00946    num = Pa_GetDeviceCount();
00947    if (!num) {
00948       ast_cli(a->fd, "(None)\n");
00949       return CLI_SUCCESS;
00950    }
00951 
00952    def_input = Pa_GetDefaultInputDevice();
00953    def_output = Pa_GetDefaultOutputDevice();
00954    for (idx = 0; idx < num; idx++) {
00955       const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
00956       if (!dev)
00957          continue;
00958       ast_cli(a->fd, "=== ---------------------------------------------------------\n"
00959                      "=== Device Name: %s\n", dev->name);
00960       if (dev->maxInputChannels)
00961          ast_cli(a->fd, "=== ---> %sInput Device\n", (idx == def_input) ? "Default " : "");
00962       if (dev->maxOutputChannels)
00963          ast_cli(a->fd, "=== ---> %sOutput Device\n", (idx == def_output) ? "Default " : "");
00964       ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
00965    }
00966 
00967    ast_cli(a->fd, "=============================================================\n\n");
00968 
00969    return CLI_SUCCESS;
00970 }

static char* cli_list_devices ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 972 of file chan_console.c.

References active_pvt, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli_args::argc, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_pvt_lock, console_pvt_unlock, ast_cli_args::fd, pvts, unref_pvt(), and ast_cli_entry::usage.

00973 {
00974    struct ao2_iterator i;
00975    struct console_pvt *pvt;
00976 
00977    if (cmd == CLI_INIT) {
00978       e->command = "console list devices";
00979       e->usage =
00980          "Usage: console list devices\n"
00981          "       List all configured devices.\n";
00982       return NULL;
00983    } else if (cmd == CLI_GENERATE)
00984       return NULL;
00985 
00986    if (a->argc != e->args)
00987       return CLI_SHOWUSAGE;
00988 
00989    ast_cli(a->fd, "\n"
00990                "=============================================================\n"
00991                "=== Configured Devices ======================================\n"
00992                "=============================================================\n"
00993                "===\n");
00994 
00995    i = ao2_iterator_init(pvts, 0);
00996    while ((pvt = ao2_iterator_next(&i))) {
00997       console_pvt_lock(pvt);
00998 
00999       ast_cli(a->fd, "=== ---------------------------------------------------------\n"
01000                      "=== Device Name: %s\n"
01001                      "=== ---> Active:           %s\n"
01002                      "=== ---> Input Device:     %s\n"
01003                      "=== ---> Output Device:    %s\n"
01004                      "=== ---> Context:          %s\n"
01005                      "=== ---> Extension:        %s\n"
01006                      "=== ---> CallerID Num:     %s\n"
01007                      "=== ---> CallerID Name:    %s\n"
01008                      "=== ---> MOH Interpret:    %s\n"
01009                      "=== ---> Language:         %s\n"
01010                      "=== ---> Parkinglot:       %s\n"
01011                      "=== ---> Muted:            %s\n"
01012                      "=== ---> Auto-Answer:      %s\n"
01013                      "=== ---> Override Context: %s\n"
01014                      "=== ---------------------------------------------------------\n===\n",
01015          pvt->name, (pvt == active_pvt) ? "Yes" : "No",
01016          pvt->input_device, pvt->output_device, pvt->context,
01017          pvt->exten, pvt->cid_num, pvt->cid_name, pvt->mohinterpret,
01018          pvt->language, pvt->parkinglot, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
01019          pvt->overridecontext ? "Yes" : "No");
01020 
01021       console_pvt_unlock(pvt);
01022       unref_pvt(pvt);
01023    }
01024    ao2_iterator_destroy(&i);
01025 
01026    ast_cli(a->fd, "=============================================================\n\n");
01027 
01028    return CLI_SUCCESS;
01029 }

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 525 of file chan_console.c.

References ast_setstate(), AST_STATE_UP, ast_verb, start_stream(), ast_channel::tech_pvt, V_BEGIN, and V_END.

00526 {
00527    struct console_pvt *pvt = c->tech_pvt;
00528 
00529    ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
00530 
00531    ast_setstate(c, AST_STATE_UP);
00532 
00533    return start_stream(pvt);
00534 }

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

Definition at line 563 of file chan_console.c.

References AST_CONTROL_ANSWER, AST_CONTROL_RINGING, ast_indicate(), ast_queue_control(), ast_verb, console_pvt::autoanswer, ast_channel::caller, console_pvt_lock, console_pvt_unlock, console_pvt::hookstate, ast_party_caller::id, ast_party_id::name, ast_party_id::number, S_COR, start_stream(), ast_party_number::str, ast_party_name::str, ast_channel::tech_pvt, V_BEGIN, V_END, ast_party_number::valid, and ast_party_name::valid.

00564 {
00565    struct console_pvt *pvt = c->tech_pvt;
00566    enum ast_control_frame_type ctrl;
00567 
00568    ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
00569       dest,
00570       S_COR(c->caller.id.name.valid, c->caller.id.name.str, ""),
00571       S_COR(c->caller.id.number.valid, c->caller.id.number.str, ""));
00572 
00573    console_pvt_lock(pvt);
00574 
00575    if (pvt->autoanswer) {
00576       pvt->hookstate = 1;
00577       console_pvt_unlock(pvt);
00578       ast_verb(1, V_BEGIN "Auto-answered" V_END);
00579       ctrl = AST_CONTROL_ANSWER;
00580    } else {
00581       console_pvt_unlock(pvt);
00582       ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
00583             "for future calls" V_END);
00584       ctrl = AST_CONTROL_RINGING;
00585       ast_indicate(c, AST_CONTROL_RINGING);
00586    }
00587 
00588    ast_queue_control(c, ctrl);
00589 
00590    return start_stream(pvt);
00591 }

static int console_digit_begin ( struct ast_channel c,
char  digit 
) [static]

Definition at line 488 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

00489 {
00490    ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
00491 
00492    return -1; /* non-zero to request inband audio */
00493 }

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

Definition at line 495 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

00496 {
00497    ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END, 
00498       digit, duration);
00499 
00500    return -1; /* non-zero to request inband audio */
00501 }

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

Definition at line 637 of file chan_console.c.

References console_pvt::owner, and ast_channel::tech_pvt.

00638 {
00639    struct console_pvt *pvt = newchan->tech_pvt;
00640 
00641    pvt->owner = newchan;
00642 
00643    return 0;
00644 }

static int console_hangup ( struct ast_channel c  )  [static]

Definition at line 510 of file chan_console.c.

References ast_verb, console_pvt::hookstate, console_pvt::owner, stop_stream(), ast_channel::tech_pvt, unref_pvt(), V_BEGIN, and V_END.

00511 {
00512    struct console_pvt *pvt = c->tech_pvt;
00513 
00514    ast_verb(1, V_BEGIN "Hangup on Console" V_END);
00515 
00516    pvt->hookstate = 0;
00517    pvt->owner = NULL;
00518    stop_stream(pvt);
00519 
00520    c->tech_pvt = unref_pvt(pvt);
00521 
00522    return 0;
00523 }

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

Definition at line 602 of file chan_console.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, AST_CONTROL_VIDUPDATE, ast_log(), ast_moh_start(), ast_moh_stop(), ast_verb, LOG_WARNING, console_pvt::mohinterpret, ast_channel::name, ast_channel::tech_pvt, V_BEGIN, and V_END.

00603 {
00604    struct console_pvt *pvt = chan->tech_pvt;
00605    int res = 0;
00606 
00607    switch (cond) {
00608    case AST_CONTROL_BUSY:
00609    case AST_CONTROL_CONGESTION:
00610    case AST_CONTROL_RINGING:
00611    case -1:
00612       res = -1;  /* Ask for inband indications */
00613       break;
00614    case AST_CONTROL_PROGRESS:
00615    case AST_CONTROL_PROCEEDING:
00616    case AST_CONTROL_VIDUPDATE:
00617    case AST_CONTROL_SRCUPDATE:
00618       break;
00619    case AST_CONTROL_HOLD:
00620       ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
00621       ast_moh_start(chan, data, pvt->mohinterpret);
00622       break;
00623    case AST_CONTROL_UNHOLD:
00624       ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
00625       ast_moh_stop(chan);
00626       break;
00627    default:
00628       ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", 
00629          cond, chan->name);
00630       /* The core will play inband indications for us if appropriate */
00631       res = -1;
00632    }
00633 
00634    return res;
00635 }

static struct ast_channel* console_new ( struct console_pvt pvt,
const char *  ext,
const char *  ctx,
int  state,
const char *  linkedid 
) [static]

Note:
Called with the pvt struct locked

Definition at line 417 of file chan_console.c.

References AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc, AST_FORMAT_SLINEAR16, ast_hangup(), ast_jb_configure(), ast_pbx_start(), AST_STATE_DOWN, ast_string_field_set, ast_strlen_zero(), console_pvt::cid_name, console_pvt::cid_num, console_tech, global_jbconf, language, console_pvt::language, console_pvt::name, ast_channel::nativeformats, console_pvt::owner, ast_channel::readformat, ref_pvt(), start_stream(), ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

Referenced by cli_console_dial(), and console_request().

00418 {
00419    struct ast_channel *chan;
00420 
00421    if (!(chan = ast_channel_alloc(1, state, pvt->cid_num, pvt->cid_name, NULL, 
00422       ext, ctx, linkedid, 0, "Console/%s", pvt->name))) {
00423       return NULL;
00424    }
00425 
00426    chan->tech = &console_tech;
00427    chan->nativeformats = AST_FORMAT_SLINEAR16;
00428    chan->readformat = AST_FORMAT_SLINEAR16;
00429    chan->writeformat = AST_FORMAT_SLINEAR16;
00430    chan->tech_pvt = ref_pvt(pvt);
00431 
00432    pvt->owner = chan;
00433 
00434    if (!ast_strlen_zero(pvt->language))
00435       ast_string_field_set(chan, language, pvt->language);
00436 
00437    ast_jb_configure(chan, &global_jbconf);
00438 
00439    if (state != AST_STATE_DOWN) {
00440       if (ast_pbx_start(chan)) {
00441          chan->hangupcause = AST_CAUSE_SWITCH_CONGESTION;
00442          ast_hangup(chan);
00443          chan = NULL;
00444       } else
00445          start_stream(pvt);
00446    }
00447 
00448    return chan;
00449 }

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

Definition at line 556 of file chan_console.c.

References ast_debug, and ast_null_frame.

00557 {
00558    ast_debug(1, "I should not be called ...\n");
00559 
00560    return &ast_null_frame;
00561 }

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

Channel Technology Callbacks

Definition at line 451 of file chan_console.c.

References AST_CAUSE_BUSY, ast_getformatname_multiple(), ast_log(), AST_STATE_DOWN, console_new(), console_pvt_lock, console_pvt_unlock, find_pvt(), ast_channel::linkedid, LOG_NOTICE, LOG_WARNING, console_pvt::owner, SUPPORTED_FORMATS, and unref_pvt().

00452 {
00453    format_t oldformat = format;
00454    struct ast_channel *chan = NULL;
00455    struct console_pvt *pvt;
00456    char buf[512];
00457 
00458    if (!(pvt = find_pvt(data))) {
00459       ast_log(LOG_ERROR, "Console device '%s' not found\n", (char *) data);
00460       return NULL;
00461    }
00462 
00463    format &= SUPPORTED_FORMATS;
00464    if (!format) {
00465       ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), oldformat));
00466       goto return_unref;
00467    }
00468 
00469    if (pvt->owner) {
00470       ast_log(LOG_NOTICE, "Console channel already active!\n");
00471       *cause = AST_CAUSE_BUSY;
00472       goto return_unref;
00473    }
00474 
00475    console_pvt_lock(pvt);
00476    chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
00477    console_pvt_unlock(pvt);
00478 
00479    if (!chan)
00480       ast_log(LOG_WARNING, "Unable to create new Console channel!\n");
00481 
00482 return_unref:
00483    unref_pvt(pvt);
00484 
00485    return chan;
00486 }

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

Definition at line 503 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

00504 {
00505    ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
00506 
00507    return 0;
00508 }

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

Definition at line 593 of file chan_console.c.

References f, console_pvt::stream, and ast_channel::tech_pvt.

00594 {
00595    struct console_pvt *pvt = chan->tech_pvt;
00596 
00597    Pa_WriteStream(pvt->stream, f->data.ptr, f->samples);
00598 
00599    return 0;
00600 }

static void destroy_pvts ( void   )  [static]

Definition at line 1365 of file chan_console.c.

References active_lock, active_pvt, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ao2_unlink, ast_rwlock_unlock, ast_rwlock_wrlock, console_pvt::destroy, pvts, and unref_pvt().

Referenced by load_config().

01366 {
01367    struct ao2_iterator i;
01368    struct console_pvt *pvt;
01369 
01370    i = ao2_iterator_init(pvts, 0);
01371    while ((pvt = ao2_iterator_next(&i))) {
01372       if (pvt->destroy) {
01373          ao2_unlink(pvts, pvt);
01374          ast_rwlock_wrlock(&active_lock);
01375          if (active_pvt == pvt)
01376             active_pvt = unref_pvt(pvt);
01377          ast_rwlock_unlock(&active_lock);
01378       }
01379       unref_pvt(pvt);
01380    }
01381    ao2_iterator_destroy(&i);
01382 }

static struct console_pvt* find_pvt ( const char *  name  )  [static]

Definition at line 242 of file chan_console.c.

References ao2_find, console_pvt::name, OBJ_POINTER, and pvts.

Referenced by build_device(), cli_console_active(), and console_request().

00243 {
00244    struct console_pvt tmp_pvt = {
00245       .name = name,
00246    };
00247 
00248    return ao2_find(pvts, &tmp_pvt, OBJ_POINTER);
00249 }

static struct console_pvt* get_active_pvt ( void   )  [static]

Definition at line 680 of file chan_console.c.

References active_lock, active_pvt, ast_rwlock_rdlock, ast_rwlock_unlock, and ref_pvt().

Referenced by cli_console_active(), cli_console_answer(), cli_console_autoanswer(), cli_console_dial(), cli_console_flash(), cli_console_hangup(), cli_console_mute(), and cli_console_sendtext().

00681 {
00682    struct console_pvt *pvt;
00683 
00684    ast_rwlock_rdlock(&active_lock);
00685    pvt = ref_pvt(active_pvt); 
00686    ast_rwlock_unlock(&active_lock);
00687 
00688    return pvt;
00689 }

static int init_pvt ( struct console_pvt pvt,
const char *  name 
) [static]

Definition at line 1317 of file chan_console.c.

References AST_PTHREADT_NULL, ast_string_field_init, ast_string_field_set, S_OR, and console_pvt::thread.

Referenced by build_device(), and load_module().

01318 {
01319    pvt->thread = AST_PTHREADT_NULL;
01320 
01321    if (ast_string_field_init(pvt, 32))
01322       return -1;
01323 
01324    ast_string_field_set(pvt, name, S_OR(name, ""));
01325 
01326    return 0;
01327 }

static int load_config ( int  reload  )  [static]

Load the configuration.

Parameters:
reload if this was called due to a reload
Return values:
0 success
-1 failure

Definition at line 1390 of file chan_console.c.

References ao2_callback, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_variable_browse(), build_device(), config_flags, CONFIG_STATUS_FILEINVALID, context, default_jbconf, destroy_pvts(), global_jbconf, globals, globals_lock, LOG_NOTICE, ast_variable::name, ast_variable::next, OBJ_NODATA, pvt_mark_destroy_cb(), pvts, set_pvt_defaults(), store_config_core(), and ast_variable::value.

01391 {
01392    struct ast_config *cfg;
01393    struct ast_variable *v;
01394    struct ast_flags config_flags = { 0 };
01395    char *context = NULL;
01396 
01397    /* default values */
01398    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
01399    ast_mutex_lock(&globals_lock);
01400    set_pvt_defaults(&globals);
01401    ast_mutex_unlock(&globals_lock);
01402 
01403    if (!(cfg = ast_config_load(config_file, config_flags))) {
01404       ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
01405       return -1;
01406    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01407       ast_log(LOG_NOTICE, "Config file %s has an invalid format\n", config_file);
01408       return -1;
01409    }
01410    
01411    ao2_callback(pvts, OBJ_NODATA, pvt_mark_destroy_cb, NULL);
01412 
01413    ast_mutex_lock(&globals_lock);
01414    for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
01415       store_config_core(&globals, v->name, v->value);
01416    ast_mutex_unlock(&globals_lock);
01417 
01418    while ((context = ast_category_browse(cfg, context))) {
01419       if (strcasecmp(context, "general"))
01420          build_device(cfg, context);
01421    }
01422 
01423    ast_config_destroy(cfg);
01424 
01425    destroy_pvts();
01426 
01427    return 0;
01428 }

static int load_module ( void   )  [static]

Definition at line 1475 of file chan_console.c.

References ao2_container_alloc, ao2_ref, ARRAY_LEN, ast_channel_register(), ast_channel_unregister(), ast_cli_register_multiple(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, cli_console, console_tech, globals, init_pvt(), load_config(), LOG_WARNING, NUM_PVT_BUCKETS, pvt_cmp_cb(), pvt_destructor(), pvt_hash_cb(), and pvts.

01476 {
01477    PaError res;
01478 
01479    init_pvt(&globals, NULL);
01480 
01481    if (!(pvts = ao2_container_alloc(NUM_PVT_BUCKETS, pvt_hash_cb, pvt_cmp_cb)))
01482       goto return_error;
01483 
01484    if (load_config(0))
01485       goto return_error;
01486 
01487    res = Pa_Initialize();
01488    if (res != paNoError) {
01489       ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
01490          res, Pa_GetErrorText(res));
01491       goto return_error_pa_init;
01492    }
01493 
01494    if (ast_channel_register(&console_tech)) {
01495       ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
01496       goto return_error_chan_reg;
01497    }
01498 
01499    if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
01500       goto return_error_cli_reg;
01501 
01502    return AST_MODULE_LOAD_SUCCESS;
01503 
01504 return_error_cli_reg:
01505    ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
01506 return_error_chan_reg:
01507    ast_channel_unregister(&console_tech);
01508 return_error_pa_init:
01509    Pa_Terminate();
01510 return_error:
01511    if (pvts)
01512       ao2_ref(pvts, -1);
01513    pvts = NULL;
01514    pvt_destructor(&globals);
01515 
01516    return AST_MODULE_LOAD_DECLINE;
01517 }

static int open_stream ( struct console_pvt pvt  )  [static]

Definition at line 291 of file chan_console.c.

References INPUT_CHANNELS, console_pvt::input_device, NUM_SAMPLES, OUTPUT_CHANNELS, console_pvt::output_device, SAMPLE_RATE, and console_pvt::stream.

Referenced by start_stream().

00292 {
00293    int res = paInternalError;
00294 
00295    if (!strcasecmp(pvt->input_device, "default") && 
00296       !strcasecmp(pvt->output_device, "default")) {
00297       res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS, 
00298          paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
00299    } else {
00300       PaStreamParameters input_params = { 
00301          .channelCount = 1,
00302          .sampleFormat = paInt16,
00303          .suggestedLatency = (1.0 / 50.0), /* 20 ms */
00304          .device = paNoDevice,
00305       };
00306       PaStreamParameters output_params = { 
00307          .channelCount = 1, 
00308          .sampleFormat = paInt16,
00309          .suggestedLatency = (1.0 / 50.0), /* 20 ms */
00310          .device = paNoDevice,
00311       };
00312       PaDeviceIndex idx, num_devices, def_input, def_output;
00313 
00314       if (!(num_devices = Pa_GetDeviceCount()))
00315          return res;
00316 
00317       def_input = Pa_GetDefaultInputDevice();
00318       def_output = Pa_GetDefaultOutputDevice();
00319 
00320       for (idx = 0; 
00321          idx < num_devices && (input_params.device == paNoDevice 
00322             || output_params.device == paNoDevice); 
00323          idx++) 
00324       {
00325          const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
00326 
00327          if (dev->maxInputChannels) {
00328             if ( (idx == def_input && !strcasecmp(pvt->input_device, "default")) ||
00329                !strcasecmp(pvt->input_device, dev->name) )
00330                input_params.device = idx;
00331          }
00332 
00333          if (dev->maxOutputChannels) {
00334             if ( (idx == def_output && !strcasecmp(pvt->output_device, "default")) ||
00335                !strcasecmp(pvt->output_device, dev->name) )
00336                output_params.device = idx;
00337          }
00338       }
00339 
00340       if (input_params.device == paNoDevice)
00341          ast_log(LOG_ERROR, "No input device found for console device '%s'\n", pvt->name);
00342       if (output_params.device == paNoDevice)
00343          ast_log(LOG_ERROR, "No output device found for console device '%s'\n", pvt->name);
00344 
00345       res = Pa_OpenStream(&pvt->stream, &input_params, &output_params,
00346          SAMPLE_RATE, NUM_SAMPLES, paNoFlag, NULL, NULL);
00347    }
00348 
00349    return res;
00350 }

static int pvt_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1437 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module(), and load_objects().

01438 {
01439    struct console_pvt *pvt = obj, *pvt2 = arg;
01440 
01441    return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH | CMP_STOP : 0;
01442 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1310 of file chan_console.c.

References ast_string_field_free_memory.

Referenced by build_device(), load_module(), new_iax(), and unload_module().

01311 {
01312    struct console_pvt *pvt = obj;
01313 
01314    ast_string_field_free_memory(pvt);
01315 }

static int pvt_hash_cb ( const void *  obj,
const int  flags 
) [static]

Definition at line 1430 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module(), and load_objects().

01431 {
01432    const struct console_pvt *pvt = obj;
01433 
01434    return ast_str_case_hash(pvt->name);
01435 }

static int pvt_mark_destroy_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1358 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

01359 {
01360    struct console_pvt *pvt = obj;
01361    pvt->destroy = 1;
01362    return 0;
01363 }

static struct console_pvt* ref_pvt ( struct console_pvt pvt  )  [inline, static]

Definition at line 229 of file chan_console.c.

References ao2_ref.

Referenced by console_new(), get_active_pvt(), and set_active().

00230 {
00231    if (pvt)
00232       ao2_ref(pvt, +1);
00233    return pvt;
00234 }

static int reload ( void   )  [static]

Definition at line 1519 of file chan_console.c.

References load_config().

01520 {
01521    return load_config(1);
01522 }

static void set_active ( struct console_pvt pvt,
const char *  value 
) [static]

Definition at line 1135 of file chan_console.c.

References active_lock, active_pvt, ast_log(), ast_rwlock_unlock, ast_rwlock_wrlock, ast_true(), globals, ref_pvt(), and unref_pvt().

Referenced by cli_console_active(), and store_config_core().

01136 {
01137    if (pvt == &globals) {
01138       ast_log(LOG_ERROR, "active is only valid as a per-device setting\n");
01139       return;
01140    }
01141 
01142    if (!ast_true(value))
01143       return;
01144 
01145    ast_rwlock_wrlock(&active_lock);
01146    if (active_pvt)
01147       unref_pvt(active_pvt);
01148    active_pvt = ref_pvt(pvt);
01149    ast_rwlock_unlock(&active_lock);
01150 }

static void set_pvt_defaults ( struct console_pvt pvt  )  [static]

Set default values for a pvt struct.

Note:
This function expects the pvt lock to be held.

Definition at line 1235 of file chan_console.c.

References ast_mutex_lock, ast_mutex_unlock, ast_string_field_set, console_pvt::autoanswer, console_pvt::cid_name, cid_name, console_pvt::cid_num, cid_num, console_pvt::context, context, console_pvt::exten, exten, globals, globals_lock, console_pvt::language, language, console_pvt::mohinterpret, mohinterpret, console_pvt::overridecontext, console_pvt::parkinglot, and parkinglot.

Referenced by build_device(), and load_config().

01236 {
01237    if (pvt == &globals) {
01238       ast_string_field_set(pvt, mohinterpret, "default");
01239       ast_string_field_set(pvt, context, "default");
01240       ast_string_field_set(pvt, exten, "s");
01241       ast_string_field_set(pvt, language, "");
01242       ast_string_field_set(pvt, cid_num, "");
01243       ast_string_field_set(pvt, cid_name, "");
01244       ast_string_field_set(pvt, parkinglot, "");
01245    
01246       pvt->overridecontext = 0;
01247       pvt->autoanswer = 0;
01248    } else {
01249       ast_mutex_lock(&globals_lock);
01250 
01251       ast_string_field_set(pvt, mohinterpret, globals.mohinterpret);
01252       ast_string_field_set(pvt, context, globals.context);
01253       ast_string_field_set(pvt, exten, globals.exten);
01254       ast_string_field_set(pvt, language, globals.language);
01255       ast_string_field_set(pvt, cid_num, globals.cid_num);
01256       ast_string_field_set(pvt, cid_name, globals.cid_name);
01257       ast_string_field_set(pvt, parkinglot, globals.parkinglot);
01258 
01259       pvt->overridecontext = globals.overridecontext;
01260       pvt->autoanswer = globals.autoanswer;
01261 
01262       ast_mutex_unlock(&globals_lock);
01263    }
01264 }

static int start_stream ( struct console_pvt pvt  )  [static]

Definition at line 352 of file chan_console.c.

References ast_debug, ast_log(), ast_pthread_create_background, console_pvt_lock, console_pvt_unlock, LOG_WARNING, open_stream(), console_pvt::owner, console_pvt::stream, stream_monitor(), console_pvt::streamstate, and console_pvt::thread.

Referenced by console_answer(), console_call(), and console_new().

00353 {
00354    PaError res;
00355    int ret_val = 0;
00356 
00357    console_pvt_lock(pvt);
00358 
00359    /* It is possible for console_hangup to be called before the
00360     * stream is started, if this is the case pvt->owner will be NULL
00361     * and start_stream should be aborted. */
00362    if (pvt->streamstate || !pvt->owner)
00363       goto return_unlock;
00364 
00365    pvt->streamstate = 1;
00366    ast_debug(1, "Starting stream\n");
00367 
00368    res = open_stream(pvt);
00369    if (res != paNoError) {
00370       ast_log(LOG_WARNING, "Failed to open stream - (%d) %s\n",
00371          res, Pa_GetErrorText(res));
00372       ret_val = -1;
00373       goto return_unlock;
00374    }
00375 
00376    res = Pa_StartStream(pvt->stream);
00377    if (res != paNoError) {
00378       ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
00379          res, Pa_GetErrorText(res));
00380       ret_val = -1;
00381       goto return_unlock;
00382    }
00383 
00384    if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
00385       ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
00386       ret_val = -1;
00387    }
00388 
00389 return_unlock:
00390    console_pvt_unlock(pvt);
00391 
00392    return ret_val;
00393 }

static int stop_stream ( struct console_pvt pvt  )  [static]

Definition at line 395 of file chan_console.c.

References AST_PTHREADT_NULL, console_pvt_lock, console_pvt_unlock, console_pvt::stream, console_pvt::streamstate, and console_pvt::thread.

Referenced by console_hangup(), and stop_streams().

00396 {
00397    if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
00398       return 0;
00399 
00400    pthread_cancel(pvt->thread);
00401    pthread_kill(pvt->thread, SIGURG);
00402    pthread_join(pvt->thread, NULL);
00403 
00404    console_pvt_lock(pvt);
00405    Pa_AbortStream(pvt->stream);
00406    Pa_CloseStream(pvt->stream);
00407    pvt->stream = NULL;
00408    pvt->streamstate = 0;
00409    console_pvt_unlock(pvt);
00410 
00411    return 0;
00412 }

static void stop_streams ( void   )  [static]

Definition at line 1444 of file chan_console.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, console_pvt::hookstate, pvts, stop_stream(), and unref_pvt().

Referenced by unload_module().

01445 {
01446    struct console_pvt *pvt;
01447    struct ao2_iterator i;
01448 
01449    i = ao2_iterator_init(pvts, 0);
01450    while ((pvt = ao2_iterator_next(&i))) {
01451       if (pvt->hookstate)
01452          stop_stream(pvt);
01453       unref_pvt(pvt);
01454    }
01455    ao2_iterator_destroy(&i);
01456 }

static void store_callerid ( struct console_pvt pvt,
const char *  value 
) [static]

Definition at line 1266 of file chan_console.c.

References ast_callerid_split(), ast_string_field_set, cid_name, and cid_num.

Referenced by store_config(), and store_config_core().

01267 {
01268    char cid_name[256];
01269    char cid_num[256];
01270 
01271    ast_callerid_split(value, cid_name, sizeof(cid_name), 
01272       cid_num, sizeof(cid_num));
01273 
01274    ast_string_field_set(pvt, cid_name, cid_name);
01275    ast_string_field_set(pvt, cid_num, cid_num);
01276 }

static void store_config_core ( struct console_pvt pvt,
const char *  var,
const char *  value 
) [static]

Store a configuration parameter in a pvt struct.

Note:
This function expects the pvt lock to be held.

Definition at line 1283 of file chan_console.c.

References ast_jb_read_conf(), ast_log(), console_pvt::autoanswer, context, CV_BOOL, CV_END, CV_F, CV_START, CV_STRFIELD, exten, global_jbconf, globals, language, LOG_WARNING, mohinterpret, console_pvt::overridecontext, parkinglot, set_active(), and store_callerid().

Referenced by build_device(), console_cmd(), load_config(), and store_config().

01284 {
01285    if (pvt == &globals && !ast_jb_read_conf(&global_jbconf, var, value))
01286       return;
01287 
01288    CV_START(var, value);
01289 
01290    CV_STRFIELD("context", pvt, context);
01291    CV_STRFIELD("extension", pvt, exten);
01292    CV_STRFIELD("mohinterpret", pvt, mohinterpret);
01293    CV_STRFIELD("language", pvt, language);
01294    CV_F("callerid", store_callerid(pvt, value));
01295    CV_BOOL("overridecontext", pvt->overridecontext);
01296    CV_BOOL("autoanswer", pvt->autoanswer);
01297    CV_STRFIELD("parkinglot", pvt, parkinglot);
01298 
01299    if (pvt != &globals) {
01300       CV_F("active", set_active(pvt, value))
01301       CV_STRFIELD("input_device", pvt, input_device);
01302       CV_STRFIELD("output_device", pvt, output_device);
01303    }
01304 
01305    ast_log(LOG_WARNING, "Unknown option '%s'\n", var);
01306 
01307    CV_END;
01308 }

static void* stream_monitor ( void *  data  )  [static]

Stream monitor thread.

This function runs in its own thread to monitor data coming in from a portaudio stream. When enough data is available, it is queued up to be read from the Asterisk channel.

Definition at line 261 of file chan_console.c.

References AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_queue_frame(), f, NUM_SAMPLES, console_pvt::owner, ast_frame::samples, and console_pvt::stream.

Referenced by start_stream().

00262 {
00263    struct console_pvt *pvt = data;
00264    char buf[NUM_SAMPLES * sizeof(int16_t)];
00265    PaError res;
00266    struct ast_frame f = {
00267       .frametype = AST_FRAME_VOICE,
00268       .subclass.codec = AST_FORMAT_SLINEAR16,
00269       .src = "console_stream_monitor",
00270       .data.ptr = buf,
00271       .datalen = sizeof(buf),
00272       .samples = sizeof(buf) / sizeof(int16_t),
00273    };
00274 
00275    for (;;) {
00276       pthread_testcancel();
00277       res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
00278       pthread_testcancel();
00279 
00280       if (!pvt->owner) {
00281          return NULL;
00282       }
00283 
00284       if (res == paNoError)
00285          ast_queue_frame(pvt->owner, &f);
00286    }
00287 
00288    return NULL;
00289 }

static int unload_module ( void   )  [static]

Definition at line 1458 of file chan_console.c.

References ao2_ref, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), cli_console, console_tech, globals, pvt_destructor(), pvts, and stop_streams().

01459 {
01460    ast_channel_unregister(&console_tech);
01461    ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
01462 
01463    stop_streams();
01464 
01465    Pa_Terminate();
01466 
01467    /* Will unref all the pvts so they will get destroyed, too */
01468    ao2_ref(pvts, -1);
01469 
01470    pvt_destructor(&globals);
01471 
01472    return 0;
01473 }

static struct console_pvt* unref_pvt ( struct console_pvt pvt  )  [inline, static]

Definition at line 236 of file chan_console.c.

References ao2_ref.

Referenced by build_device(), cli_console_active(), cli_console_answer(), cli_console_autoanswer(), cli_console_dial(), cli_console_flash(), cli_console_hangup(), cli_console_mute(), cli_console_sendtext(), cli_list_devices(), console_hangup(), console_request(), destroy_pvts(), set_active(), and stop_streams().

00237 {
00238    ao2_ref(pvt, -1);
00239    return NULL;
00240 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 1529 of file chan_console.c.

ast_rwlock_t active_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RWLOCK_INITIALIZER } [static]

Definition at line 169 of file chan_console.c.

Referenced by destroy_pvts(), get_active_pvt(), and set_active().

struct console_pvt* active_pvt [static]

Definition at line 168 of file chan_console.c.

Referenced by cli_list_devices(), destroy_pvts(), get_active_pvt(), and set_active().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1529 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

Definition at line 1217 of file chan_console.c.

Referenced by load_module(), and unload_module().

const char config_file[] = "console.conf" [static]

Definition at line 109 of file chan_console.c.

struct ast_channel_tech console_tech [static]

Definition at line 206 of file chan_console.c.

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration.

Note:
Disabled by default.

Definition at line 176 of file chan_console.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 183 of file chan_console.c.

struct console_pvt globals [static]

Console pvt structure.

Currently, this is a singleton object. However, multiple instances will be needed when this module is updated for multiple device support.

Referenced by ast_str_retrieve_variable(), handle_show_globals(), load_config(), load_module(), pbx_builtin_clear_globals(), pbx_builtin_getvar_helper(), pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), set_active(), set_pvt_defaults(), store_config_core(), and unload_module().

ast_mutex_t globals_lock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } [static]

Definition at line 163 of file chan_console.c.

Referenced by load_config(), load_module(), reload(), set_config(), set_pvt_defaults(), and unload_module().

struct ao2_container* pvts [static]

Definition at line 165 of file chan_console.c.

Referenced by build_device(), cli_console_active(), cli_list_devices(), destroy_pvts(), find_pvt(), load_config(), load_module(), sig_pri_handle_retrieve(), stop_streams(), and unload_module().


Generated on Wed Apr 6 11:29:54 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7