Tue Mar 2 17:32:47 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"
Include dependency graph for chan_console.c:

Go to the source code of this file.

Data Structures

struct  console_pvt
 Console pvt structure. More...

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



#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)

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)
#define console_pvt_unlock ( pvt   )     ao2_unlock(pvt)
#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 203 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   " --- <(\"<) --- "
#define V_END   " --- (>\")> ---\n"

Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1519 of file chan_console.c.

static void __unreg_module ( void   )  [static]

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

References ast_strdup, and console_pvt::overridecontext.

Referenced by cli_console_dial().

00649 {
00650    if (ext == NULL || ctx == NULL)
00651       return NULL;         /* error */
00652 
00653    *ext = *ctx = NULL;
00654 
00655    if (src && *src != '\0')
00656       *ext = ast_strdup(src);
00657 
00658    if (*ext == NULL)
00659       return NULL;
00660 
00661    if (!pvt->overridecontext) {
00662       /* parse from the right */
00663       *ctx = strrchr(*ext, '@');
00664       if (*ctx)
00665          *(*ctx)++ = '\0';
00666    }
00667 
00668    return *ext;
00669 }

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

Definition at line 1324 of file chan_console.c.

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

Referenced by load_config().

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

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

Definition at line 1145 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, set_active(), unref_pvt(), ast_cli_entry::usage, and ast_cli_args::word.

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

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 1025 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, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

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

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

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

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

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

Definition at line 767 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, ast_cli_args::fd, free, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, s, ast_frame::subclass, unref_pvt(), and ast_cli_entry::usage.

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

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

Definition at line 730 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, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

00731 {
00732    struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
00733    struct console_pvt *pvt = get_active_pvt();
00734 
00735    if (cmd == CLI_INIT) {
00736       e->command = "console flash";
00737       e->usage =
00738          "Usage: console flash\n"
00739          "       Flashes the call currently placed on the console.\n";
00740       return NULL;
00741    } else if (cmd == CLI_GENERATE)
00742       return NULL;
00743 
00744    if (!pvt) {
00745       ast_cli(a->fd, "No console device is set as active\n");
00746       return CLI_FAILURE;
00747    }
00748 
00749    if (a->argc != e->args)
00750       return CLI_SHOWUSAGE;
00751 
00752    if (!pvt->owner) {
00753       ast_cli(a->fd, "No call to flash\n");
00754       unref_pvt(pvt);
00755       return CLI_FAILURE;
00756    }
00757 
00758    pvt->hookstate = 0;
00759 
00760    ast_queue_frame(pvt->owner, &f);
00761 
00762    unref_pvt(pvt);
00763 
00764    return CLI_SUCCESS;
00765 }

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

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

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

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

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

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

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 1075 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, ast_frame::datalen, ast_cli_args::fd, ast_frame::frametype, get_active_pvt(), len(), console_pvt::owner, TEXT_SIZE, unref_pvt(), and ast_cli_entry::usage.

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

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

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

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

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

Definition at line 964 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(), console_pvt::autoanswer, console_pvt::cid_name, console_pvt::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_pvt_lock, console_pvt_unlock, console_pvt::context, console_pvt::exten, ast_cli_args::fd, console_pvt::input_device, console_pvt::language, console_pvt::mohinterpret, console_pvt::muted, console_pvt::name, console_pvt::output_device, console_pvt::overridecontext, console_pvt::parkinglot, unref_pvt(), and ast_cli_entry::usage.

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

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 516 of file chan_console.c.

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

00517 {
00518    struct console_pvt *pvt = c->tech_pvt;
00519 
00520    ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);
00521 
00522    ast_setstate(c, AST_STATE_UP);
00523 
00524    return start_stream(pvt);
00525 }

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

Definition at line 554 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, ast_frame::frametype, console_pvt::hookstate, start_stream(), ast_frame::subclass, ast_channel::tech_pvt, V_BEGIN, and V_END.

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

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

Definition at line 479 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

00480 {
00481    ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
00482 
00483    return -1; /* non-zero to request inband audio */
00484 }

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

Definition at line 486 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 628 of file chan_console.c.

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

00629 {
00630    struct console_pvt *pvt = newchan->tech_pvt;
00631 
00632    pvt->owner = newchan;
00633 
00634    return 0;
00635 }

static int console_hangup ( struct ast_channel c  )  [static]

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

00502 {
00503    struct console_pvt *pvt = c->tech_pvt;
00504 
00505    ast_verb(1, V_BEGIN "Hangup on Console" V_END);
00506 
00507    pvt->hookstate = 0;
00508    pvt->owner = NULL;
00509    stop_stream(pvt);
00510 
00511    c->tech_pvt = unref_pvt(pvt);
00512 
00513    return 0;
00514 }

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

Definition at line 593 of file chan_console.c.

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

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

static struct ast_channel* console_new ( struct console_pvt pvt,
const char *  ext,
const char *  ctx,
int  state 
) [static, read]
Note:
Called with the pvt struct locked

Definition at line 409 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, global_jbconf, ast_channel::hangupcause, 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().

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

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

Definition at line 547 of file chan_console.c.

References ast_debug, and ast_null_frame.

00548 {
00549    ast_debug(1, "I should not be called ...\n");
00550 
00551    return &ast_null_frame;
00552 }

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

Channel Technology Callbacks

Definition at line 443 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_ERROR, LOG_NOTICE, LOG_WARNING, console_pvt::owner, SUPPORTED_FORMATS, and unref_pvt().

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

static int console_text ( struct ast_channel c,
const char *  text 
) [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 Text '%s'" V_END, text);
00497 
00498    return 0;
00499 }

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

Definition at line 584 of file chan_console.c.

References ast_frame::data, ast_frame::ptr, ast_frame::samples, console_pvt::stream, and ast_channel::tech_pvt.

00585 {
00586    struct console_pvt *pvt = chan->tech_pvt;
00587 
00588    Pa_WriteStream(pvt->stream, f->data.ptr, f->samples);
00589 
00590    return 0;
00591 }

static void destroy_pvts ( void   )  [static]

Definition at line 1360 of file chan_console.c.

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

Referenced by load_config().

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

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

Definition at line 241 of file chan_console.c.

References ao2_find, console_pvt::name, and OBJ_POINTER.

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

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

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

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

01313 {
01314    pvt->thread = AST_PTHREADT_NULL;
01315 
01316    if (ast_string_field_init(pvt, 32))
01317       return -1;
01318 
01319    ast_string_field_set(pvt, name, S_OR(name, ""));
01320 
01321    return 0;
01322 }

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 1385 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(), context, destroy_pvts(), global_jbconf, globals, globals_lock, LOG_NOTICE, ast_variable::name, ast_variable::next, OBJ_NODATA, pvt_mark_destroy_cb(), set_pvt_defaults(), store_config_core(), and ast_variable::value.

Referenced by load_module(), and reload().

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

static int load_module ( void   )  [static]

Definition at line 1467 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, globals, init_pvt(), load_config(), LOG_ERROR, LOG_WARNING, NUM_PVT_BUCKETS, pvt_cmp_cb(), pvt_destructor(), and pvt_hash_cb().

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

static int open_stream ( struct console_pvt pvt  )  [static]

Definition at line 286 of file chan_console.c.

References ast_log(), INPUT_CHANNELS, console_pvt::input_device, LOG_ERROR, console_pvt::name, NUM_SAMPLES, OUTPUT_CHANNELS, console_pvt::output_device, SAMPLE_RATE, and console_pvt::stream.

Referenced by start_stream().

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

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

Definition at line 1429 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module().

01430 {
01431    struct console_pvt *pvt = obj, *pvt2 = arg;
01432 
01433    return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH | CMP_STOP : 0;
01434 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1305 of file chan_console.c.

References ast_string_field_free_memory.

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

01306 {
01307    struct console_pvt *pvt = obj;
01308 
01309    ast_string_field_free_memory(pvt);
01310 }

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

Definition at line 1422 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module().

01423 {
01424    const struct console_pvt *pvt = obj;
01425 
01426    return ast_str_case_hash(pvt->name);
01427 }

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

Definition at line 1353 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

01354 {
01355    struct console_pvt *pvt = obj;
01356    pvt->destroy = 1;
01357    return 0;
01358 }

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

Definition at line 228 of file chan_console.c.

References ao2_ref.

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

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

static int reload ( void   )  [static]

Definition at line 1510 of file chan_console.c.

References load_config().

01511 {
01512    return load_config(1);
01513 }

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

Definition at line 1128 of file chan_console.c.

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

Referenced by cli_console_active(), and store_config_core().

01129 {
01130    if (pvt == &globals) {
01131       ast_log(LOG_ERROR, "active is only valid as a per-device setting\n");
01132       return;
01133    }
01134 
01135    if (!ast_true(value))
01136       return;
01137 
01138    ast_rwlock_wrlock(&active_lock);
01139    if (active_pvt)
01140       unref_pvt(active_pvt);
01141    active_pvt = ref_pvt(pvt);
01142    ast_rwlock_unlock(&active_lock);
01143 }

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

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

static int start_stream ( struct console_pvt pvt  )  [static]

Definition at line 347 of file chan_console.c.

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

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

00348 {
00349    PaError res;
00350    int ret_val = 0;
00351 
00352    console_pvt_lock(pvt);
00353 
00354    if (pvt->streamstate)
00355       goto return_unlock;
00356 
00357    pvt->streamstate = 1;
00358    ast_debug(1, "Starting stream\n");
00359 
00360    res = open_stream(pvt);
00361    if (res != paNoError) {
00362       ast_log(LOG_WARNING, "Failed to open stream - (%d) %s\n",
00363          res, Pa_GetErrorText(res));
00364       ret_val = -1;
00365       goto return_unlock;
00366    }
00367 
00368    res = Pa_StartStream(pvt->stream);
00369    if (res != paNoError) {
00370       ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
00371          res, Pa_GetErrorText(res));
00372       ret_val = -1;
00373       goto return_unlock;
00374    }
00375 
00376    if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
00377       ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
00378       ret_val = -1;
00379    }
00380 
00381 return_unlock:
00382    console_pvt_unlock(pvt);
00383 
00384    return ret_val;
00385 }

static int stop_stream ( struct console_pvt pvt  )  [static]

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

00388 {
00389    if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
00390       return 0;
00391 
00392    pthread_cancel(pvt->thread);
00393    pthread_kill(pvt->thread, SIGURG);
00394    pthread_join(pvt->thread, NULL);
00395 
00396    console_pvt_lock(pvt);
00397    Pa_AbortStream(pvt->stream);
00398    Pa_CloseStream(pvt->stream);
00399    pvt->stream = NULL;
00400    pvt->streamstate = 0;
00401    console_pvt_unlock(pvt);
00402 
00403    return 0;
00404 }

static void stop_streams ( void   )  [static]

Definition at line 1436 of file chan_console.c.

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

Referenced by unload_module().

01437 {
01438    struct console_pvt *pvt;
01439    struct ao2_iterator i;
01440 
01441    i = ao2_iterator_init(pvts, 0);
01442    while ((pvt = ao2_iterator_next(&i))) {
01443       if (pvt->hookstate)
01444          stop_stream(pvt);
01445       unref_pvt(pvt);
01446    }
01447    ao2_iterator_destroy(&i);
01448 }

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

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

01262 {
01263    char cid_name[256];
01264    char cid_num[256];
01265 
01266    ast_callerid_split(value, cid_name, sizeof(cid_name), 
01267       cid_num, sizeof(cid_num));
01268 
01269    ast_string_field_set(pvt, cid_name, cid_name);
01270    ast_string_field_set(pvt, cid_num, cid_num);
01271 }

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

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

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

Stream monitor thread.

  • data A pointer to the console_pvt structure that contains the portaudio stream that needs to be monitored.

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

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

Referenced by start_stream().

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

static int unload_module ( void   )  [static]

Definition at line 1450 of file chan_console.c.

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

01451 {
01452    ast_channel_unregister(&console_tech);
01453    ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
01454 
01455    stop_streams();
01456 
01457    Pa_Terminate();
01458 
01459    /* Will unref all the pvts so they will get destroyed, too */
01460    ao2_ref(pvts, -1);
01461 
01462    pvt_destructor(&globals);
01463 
01464    return 0;
01465 }

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

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

Definition at line 1519 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

Definition at line 1212 of file chan_console.c.

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

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

Referenced by console_new(), load_config(), and store_config_core().

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 load_config(), load_module(), set_active(), set_pvt_defaults(), store_config_core(), and unload_module().

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]

Generated on 2 Mar 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1