Wed Aug 18 22:34:06 2010

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, int format, 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)
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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static ast_rwlock_t active_lock = 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 = ((ast_mutex_t) 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.

#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 1528 of file chan_console.c.

static void __unreg_module ( void   )  [static]

Definition at line 1528 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 656 of file chan_console.c.

References ast_strdup, and console_pvt::overridecontext.

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

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

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

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

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

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

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

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

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_FRAME_CONTROL, ast_indicate(), ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

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

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

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

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

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, s, 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, 0 };
00801 
00802       if (a->argc == e->args) {  /* argument is mandatory here */
00803          ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
00804          unref_pvt(pvt);
00805          return CLI_FAILURE;
00806       }
00807       s = a->argv[e->args];
00808       /* send the string one char at a time */
00809       for (i = 0; i < strlen(s); i++) {
00810          f.subclass = s[i];
00811          ast_queue_frame(pvt->owner, &f);
00812       }
00813       unref_pvt(pvt);
00814       return CLI_SUCCESS;
00815    }
00816 
00817    /* if we have an argument split it into extension and context */
00818    if (a->argc == e->args + 1) {
00819       char *ext = NULL, *con = NULL;
00820       s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
00821       ast_debug(1, "provided '%s', exten '%s' context '%s'\n", 
00822          a->argv[e->args], mye, myc);
00823       mye = ext;
00824       myc = con;
00825    }
00826 
00827    /* supply default values if needed */
00828    if (ast_strlen_zero(mye))
00829       mye = pvt->exten;
00830    if (ast_strlen_zero(myc))
00831       myc = pvt->context;
00832 
00833    if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
00834       console_pvt_lock(pvt);
00835       pvt->hookstate = 1;
00836       console_new(pvt, mye, myc, AST_STATE_RINGING);
00837       console_pvt_unlock(pvt);
00838    } else
00839       ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
00840 
00841    if (s)
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 738 of file chan_console.c.

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

00739 {
00740    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
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_frame(pvt->owner, &f);
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, s, unref_pvt(), ast_cli_entry::usage, V_BEGIN, and V_END.

00886 {
00887    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 1083 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(), buf, 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.

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

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, num, 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 524 of file chan_console.c.

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

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

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

Definition at line 562 of file chan_console.c.

References AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_indicate(), ast_queue_frame(), ast_verb, console_pvt::autoanswer, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, console_pvt_lock, console_pvt_unlock, f, console_pvt::hookstate, start_stream(), ast_channel::tech_pvt, V_BEGIN, and V_END.

00563 {
00564    struct ast_frame f = { 0, };
00565    struct console_pvt *pvt = c->tech_pvt;
00566 
00567    ast_verb(1, V_BEGIN "Call to device '%s' on console from '%s' <%s>" V_END,
00568       dest, c->cid.cid_name, c->cid.cid_num);
00569 
00570    console_pvt_lock(pvt);
00571 
00572    if (pvt->autoanswer) {
00573       pvt->hookstate = 1;
00574       console_pvt_unlock(pvt);
00575       ast_verb(1, V_BEGIN "Auto-answered" V_END);
00576       f.frametype = AST_FRAME_CONTROL;
00577       f.subclass = AST_CONTROL_ANSWER;
00578    } else {
00579       console_pvt_unlock(pvt);
00580       ast_verb(1, V_BEGIN "Type 'console answer' to answer, or use the 'autoanswer' option "
00581             "for future calls" V_END);
00582       f.frametype = AST_FRAME_CONTROL;
00583       f.subclass = AST_CONTROL_RINGING;
00584       ast_indicate(c, AST_CONTROL_RINGING);
00585    }
00586 
00587    ast_queue_frame(c, &f);
00588 
00589    return start_stream(pvt);
00590 }

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

Definition at line 487 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 494 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 636 of file chan_console.c.

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

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

static int console_hangup ( struct ast_channel c  )  [static]

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

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

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

Definition at line 601 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, chan, LOG_WARNING, console_pvt::mohinterpret, ast_channel::name, ast_channel::tech_pvt, V_BEGIN, and V_END.

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

static struct ast_channel* console_new ( struct console_pvt pvt,
const char *  ext,
const char *  ctx,
int  state 
) [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(), chan, 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, 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 555 of file chan_console.c.

References ast_debug, and ast_null_frame.

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

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

Channel Technology Callbacks

Definition at line 451 of file chan_console.c.

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

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

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

Definition at line 502 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 592 of file chan_console.c.

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

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

static void destroy_pvts ( void   )  [static]

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

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

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 679 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().

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

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

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

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

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 1393 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, 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.

01394 {
01395    struct ast_config *cfg;
01396    struct ast_variable *v;
01397    struct ast_flags config_flags = { 0 };
01398    char *context = NULL;
01399 
01400    /* default values */
01401    memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
01402    ast_mutex_lock(&globals_lock);
01403    set_pvt_defaults(&globals);
01404    ast_mutex_unlock(&globals_lock);
01405 
01406    if (!(cfg = ast_config_load(config_file, config_flags))) {
01407       ast_log(LOG_NOTICE, "Unable to open configuration file %s!\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 1313 of file chan_console.c.

References ast_string_field_free_memory.

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

01314 {
01315    struct console_pvt *pvt = obj;
01316 
01317    ast_string_field_free_memory(pvt);
01318 }

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 1361 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

01362 {
01363    struct console_pvt *pvt = obj;
01364    pvt->destroy = 1;
01365    return 0;
01366 }

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 1136 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().

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

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 1238 of file chan_console.c.

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

Referenced by build_device(), and load_config().

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

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 1269 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().

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

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 1286 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().

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

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(), buf, 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 = 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_DEFAULT , .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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1528 of file chan_console.c.

ast_rwlock_t active_lock = 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 1528 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

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

ast_mutex_t globals_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static]

Definition at line 163 of file chan_console.c.

Referenced by load_config(), and set_pvt_defaults().

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(), pri_create_trunkgroup(), setup_dahdi(), stop_streams(), and unload_module().


Generated on Wed Aug 18 22:34:06 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7