Wed Oct 28 11:51:49 2009

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 MAX(a, b)   ((a) > (b) ? (a) : (b))
#define MIN(a, b)   ((a) < (b) ? (a) : (b))
#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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static ast_rwlock_t active_lock = { 0 }
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_MUTEX_INITIALIZER )
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 MAX ( a,
 )     ((a) > (b) ? (a) : (b))

Definition at line 108 of file chan_console.c.

Referenced by __ast_answer(), and handle_response_register().

#define MIN ( a,
 )     ((a) < (b) ? (a) : (b))

Definition at line 105 of file chan_console.c.

#define NUM_PVT_BUCKETS   7

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

static void __unreg_module ( void   )  [static]

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

References ast_strdup, and console_pvt::overridecontext.

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

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

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

Definition at line 1331 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(), and reload_config().

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

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

Definition at line 1152 of file chan_console.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Console send text CLI command.

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

Definition at line 1082 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join(), ast_queue_frame(), ast_strlen_zero(), 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.

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

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

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

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

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

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

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

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 523 of file chan_console.c.

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

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

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

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

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

static int console_digit_begin ( struct ast_channel c,
char  digit 
) [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 Beginning of Digit %c" V_END, digit);
00489 
00490    return -1; /* non-zero to request inband audio */
00491 }

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

Definition at line 493 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 635 of file chan_console.c.

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

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

static int console_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

Definition at line 554 of file chan_console.c.

References ast_debug, and ast_null_frame.

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

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

Channel Technology Callbacks

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

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

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

Definition at line 501 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 591 of file chan_console.c.

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

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

static void destroy_pvts ( void   )  [static]

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

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

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

Definition at line 248 of file chan_console.c.

References ao2_find, console_pvt::name, and OBJ_POINTER.

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

00249 {
00250    struct console_pvt tmp_pvt = {
00251       .name = name,
00252    };
00253 
00254    return ao2_find(pvts, &tmp_pvt, OBJ_POINTER);
00255 }

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

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

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

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

static int load_module ( void   )  [static]

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

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

static int open_stream ( struct console_pvt pvt  )  [static]

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

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

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

Definition at line 1436 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module(), and load_objects().

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

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1312 of file chan_console.c.

References ast_string_field_free_memory.

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

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

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

Definition at line 1429 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module(), and load_objects().

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

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

Definition at line 1360 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

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

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

Definition at line 235 of file chan_console.c.

References ao2_ref.

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

00236 {
00237    if (pvt)
00238       ao2_ref(pvt, +1);
00239    return pvt;
00240 }

static int reload ( void   )  [static]

Definition at line 1517 of file chan_console.c.

References load_config().

01518 {
01519    return load_config(1);
01520 }

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

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

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

static void set_pvt_defaults ( struct console_pvt pvt  )  [static]

Set default values for a pvt struct.

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

Definition at line 1237 of file chan_console.c.

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

Referenced by build_device(), and load_config().

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

static int start_stream ( struct console_pvt pvt  )  [static]

Definition at line 354 of file chan_console.c.

References ast_debug, ast_log(), ast_pthread_create_background, console_pvt_lock, console_pvt_unlock, LOG_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().

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

static int stop_stream ( struct console_pvt pvt  )  [static]

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

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

static void stop_streams ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

Definition at line 1457 of file chan_console.c.

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

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

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

Definition at line 1526 of file chan_console.c.

ast_rwlock_t active_lock = { 0 } [static]

Definition at line 176 of file chan_console.c.

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

struct console_pvt* active_pvt [static]

Definition at line 175 of file chan_console.c.

Definition at line 1526 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

Definition at line 1219 of file chan_console.c.

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

Definition at line 116 of file chan_console.c.

struct ast_channel_tech console_tech [static]

Definition at line 212 of file chan_console.c.

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration.

Note:
Disabled by default.

Definition at line 183 of file chan_console.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 189 of file chan_console.c.

struct console_pvt globals [static]

Console pvt structure.

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

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

Definition at line 170 of file chan_console.c.

Referenced by load_config(), and set_pvt_defaults().

struct ao2_container* pvts [static]

Definition at line 172 of file chan_console.c.

Referenced by setup_dahdi().


Generated on Wed Oct 28 11:51:49 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6