Fri Nov 12 11:55:08 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.

#define V_BEGIN   " --- <(\"<) --- "
 Dance, Kirby, Dance!
#define V_END   " --- (>\")> ---\n"

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)

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)

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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, }
static ast_rwlock_t active_lock = PTHREAD_RWLOCK_INITIALIZER
static struct console_pvtactive_pvt
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_console []
static const char config_file [] = "console.conf"
static struct ast_channel_tech console_tech
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration.
static struct ast_jb_conf global_jbconf
static struct console_pvt globals
 Console pvt structure.
static ast_mutex_t globals_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct ao2_containerpvts

Detailed Description

Cross-platform console channel driver.

Author:
Russell Bryant <russell@digium.com>
Note:
Some of the code in this file came from chan_oss and chan_alsa. chan_oss, Mark Spencer <markster@digium.com> chan_oss, Luigi Rizzo chan_alsa, Matthew Fredrickson <creslin@digium.com>
ExtRef:
Portaudio http://www.portaudio.com/

To install portaudio v19 from svn, check it out using the following command:

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

Definition in file chan_console.c.


Define Documentation

#define console_pvt_lock ( pvt   )     ao2_lock(pvt)
#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.

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

#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )

Formats natively supported by this module.

Definition at line 204 of file chan_console.c.

Referenced by console_request().

#define TEXT_SIZE   256

Maximum text message length.

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

Definition at line 102 of file chan_console.c.

Referenced by cli_console_sendtext(), and console_sendtext().

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

Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1522 of file chan_console.c.

static void __unreg_module ( void   )  [static]

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

References ast_strdup, and console_pvt::overridecontext.

Referenced by cli_console_dial().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 517 of file chan_console.c.

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

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

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

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

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

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

Definition at line 480 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 487 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 629 of file chan_console.c.

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

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

static int console_hangup ( struct ast_channel c  )  [static]

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

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

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

Definition at line 594 of file chan_console.c.

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

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

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

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

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

Definition at line 548 of file chan_console.c.

References ast_debug, and ast_null_frame.

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

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

Channel Technology Callbacks

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

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

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

Definition at line 495 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

00496 {
00497    ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);
00498 
00499    return 0;
00500 }

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

Definition at line 585 of file chan_console.c.

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

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

static void destroy_pvts ( void   )  [static]

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

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

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

Definition at line 242 of file chan_console.c.

References ao2_find, console_pvt::name, and OBJ_POINTER.

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

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

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

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

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

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

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

static int load_module ( void   )  [static]

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

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

static int open_stream ( struct console_pvt pvt  )  [static]

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

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

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

Definition at line 1431 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module().

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

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1304 of file chan_console.c.

References ast_string_field_free_memory.

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

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

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

Definition at line 1424 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module().

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

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

Definition at line 1352 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

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

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

Definition at line 229 of file chan_console.c.

References ao2_ref.

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

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

static int reload ( void   )  [static]

Definition at line 1513 of file chan_console.c.

References load_config().

01514 {
01515    return load_config(1);
01516 }

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

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

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

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

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

static int start_stream ( struct console_pvt pvt  )  [static]

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

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

static int stop_stream ( struct console_pvt pvt  )  [static]

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

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

static void stop_streams ( void   )  [static]

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

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

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 1452 of file chan_console.c.

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

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

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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

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

struct ast_cli_entry cli_console[] [static]

Definition at line 1211 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 206 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 183 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 by  doxygen 1.6.2