Mon Mar 19 11:30:37 2012

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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static ast_rwlock_t active_lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, 1 }
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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
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 226 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 229 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 93 of file chan_console.c.

Referenced by open_stream().

#define NUM_PVT_BUCKETS   7

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

Referenced by open_stream(), and stream_monitor().

#define OUTPUT_CHANNELS   1

Mono Output.

Definition at line 96 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 78 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 206 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 103 of file chan_console.c.

Referenced by cli_console_sendtext(), and console_sendtext().

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

Dance, Kirby, Dance!

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

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

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

static void __unreg_module ( void   )  [static]

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

References ast_strdup, and console_pvt::overridecontext.

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

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

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 1155 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.

01156 {
01157    struct console_pvt *pvt;
01158 
01159    switch (cmd) {
01160    case CLI_INIT:
01161       e->command = "console {set|show} active";
01162       e->usage =
01163          "Usage: console {set|show} active [<device>]\n"
01164          "       Set or show the active console device for 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 == 3) {
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 - 1]))) {
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 1036 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.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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 1085 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.

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

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

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

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

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

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

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

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 527 of file chan_console.c.

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

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

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

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

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

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

Definition at line 490 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 497 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 640 of file chan_console.c.

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

00641 {
00642    struct console_pvt *pvt = newchan->tech_pvt;
00643 
00644    pvt->owner = newchan;
00645 
00646    return 0;
00647 }

static int console_hangup ( struct ast_channel c  )  [static]

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

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

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

Definition at line 604 of file chan_console.c.

References AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, 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.

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

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

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

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

Definition at line 558 of file chan_console.c.

References ast_debug, and ast_null_frame.

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

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

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

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

Definition at line 505 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 595 of file chan_console.c.

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

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

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

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

static struct console_pvt* get_active_pvt ( void   )  [static]

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

00684 {
00685    struct console_pvt *pvt;
00686 
00687    ast_rwlock_rdlock(&active_lock);
00688    pvt = ref_pvt(active_pvt); 
00689    ast_rwlock_unlock(&active_lock);
00690 
00691    return pvt;
00692 }

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

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    } else if (cfg == CONFIG_STATUS_FILEINVALID) {
01410       ast_log(LOG_NOTICE, "Config file %s has an invalid format\n", config_file);
01411       return -1;
01412    }
01413    
01414    ao2_callback(pvts, OBJ_NODATA, pvt_mark_destroy_cb, NULL);
01415 
01416    ast_mutex_lock(&globals_lock);
01417    for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
01418       store_config_core(&globals, v->name, v->value);
01419    ast_mutex_unlock(&globals_lock);
01420 
01421    while ((context = ast_category_browse(cfg, context))) {
01422       if (strcasecmp(context, "general"))
01423          build_device(cfg, context);
01424    }
01425 
01426    ast_config_destroy(cfg);
01427 
01428    destroy_pvts();
01429 
01430    return 0;
01431 }

static int load_module ( void   )  [static]

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

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

static int open_stream ( struct console_pvt pvt  )  [static]

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

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

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

Definition at line 1440 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module(), and load_objects().

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

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

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module(), and load_objects().

01434 {
01435    const struct console_pvt *pvt = obj;
01436 
01437    return ast_str_case_hash(pvt->name);
01438 }

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

References ao2_ref.

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

00232 {
00233    if (pvt)
00234       ao2_ref(pvt, +1);
00235    return pvt;
00236 }

static int reload ( void   )  [static]

Definition at line 1522 of file chan_console.c.

References load_config().

01523 {
01524    return load_config(1);
01525 }

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

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

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

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

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

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

static int stop_stream ( struct console_pvt pvt  )  [static]

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

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

static void stop_streams ( void   )  [static]

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

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

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

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

static int unload_module ( void   )  [static]

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

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

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

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

00239 {
00240    ao2_ref(pvt, -1);
00241    return NULL;
00242 }


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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 1532 of file chan_console.c.

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

Definition at line 170 of file chan_console.c.

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

struct console_pvt* active_pvt [static]

Definition at line 169 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 1532 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 110 of file chan_console.c.

struct ast_channel_tech console_tech [static]

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

Values shown here match the defaults shown in console.conf.sample

Definition at line 178 of file chan_console.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 185 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 = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

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

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


Generated on Mon Mar 19 11:30:37 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7