Thu Apr 8 01:21:56 2010

Asterisk developer's documentation


chan_console.c File Reference

Cross-platform console channel driver. More...

#include "asterisk.h"
#include <sys/signal.h>
#include <portaudio.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/causes.h"
#include "asterisk/cli.h"
#include "asterisk/musiconhold.h"
#include "asterisk/callerid.h"
#include "asterisk/astobj2.h"
Include dependency graph for chan_console.c:

Go to the source code of this file.

Data Structures

struct  console_pvt
 Console pvt structure. More...

Defines

#define console_pvt_lock(pvt)   ao2_lock(pvt)
 lock a console_pvt struct
#define console_pvt_unlock(pvt)   ao2_unlock(pvt)
 unlock a console_pvt struct
#define INPUT_CHANNELS   1
 Mono Input.
#define NUM_PVT_BUCKETS   7
#define NUM_SAMPLES   320
 The number of samples to configure the portaudio stream for.
#define OUTPUT_CHANNELS   1
 Mono Output.
#define SAMPLE_RATE   16000
 The sample rate to request from PortAudio.
#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )
 Formats natively supported by this module.
#define TEXT_SIZE   256
 Maximum text message length.

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * ast_ext_ctx (struct console_pvt *pvt, const char *src, char **ext, char **ctx)
static void build_device (struct ast_config *cfg, const char *name)
static char * cli_console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 answer command from the console
static char * cli_console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Console send text CLI command.
static char * cli_list_available (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_list_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_channelconsole_new (struct console_pvt *pvt, const char *ext, const char *ctx, int state)
static void destroy_pvts (void)
static struct console_pvtfind_pvt (const char *name)
static struct console_pvtget_active_pvt (void)
static int init_pvt (struct console_pvt *pvt, const char *name)
static int load_config (int reload)
 Load the configuration.
static int load_module (void)
static int open_stream (struct console_pvt *pvt)
static int pvt_cmp_cb (void *obj, void *arg, int flags)
static void pvt_destructor (void *obj)
static int pvt_hash_cb (const void *obj, const int flags)
static int pvt_mark_destroy_cb (void *obj, void *arg, int flags)
static struct console_pvtref_pvt (struct console_pvt *pvt)
static int reload (void)
static void set_active (struct console_pvt *pvt, const char *value)
static void set_pvt_defaults (struct console_pvt *pvt)
 Set default values for a pvt struct.
static int start_stream (struct console_pvt *pvt)
static int stop_stream (struct console_pvt *pvt)
static void stop_streams (void)
static void store_callerid (struct console_pvt *pvt, const char *value)
static void store_config_core (struct console_pvt *pvt, const char *var, const char *value)
 Store a configuration parameter in a pvt struct.
static void * stream_monitor (void *data)
 Stream monitor thread.
static int unload_module (void)
static struct console_pvtunref_pvt (struct console_pvt *pvt)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, }
static ast_rwlock_t active_lock = PTHREAD_RWLOCK_INITIALIZER
static struct console_pvtactive_pvt
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_console []
static const char config_file [] = "console.conf"
static struct ast_channel_tech console_tech
static struct ast_jb_conf default_jbconf
 Global jitterbuffer configuration.
static struct ast_jb_conf global_jbconf
static struct console_pvt globals
 Console pvt structure.
static ast_mutex_t globals_lock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static struct ao2_containerpvts



#define V_BEGIN   " --- <(\"<) --- "
 Dance, Kirby, Dance!
#define V_END   " --- (>\")> ---\n"
static int console_answer (struct ast_channel *c)
static int console_call (struct ast_channel *c, char *dest, int timeout)
static int console_digit_begin (struct ast_channel *c, char digit)
static int console_digit_end (struct ast_channel *c, char digit, unsigned int duration)
static int console_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static int console_hangup (struct ast_channel *c)
static int console_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen)
static struct ast_frameconsole_read (struct ast_channel *chan)
static struct ast_channelconsole_request (const char *type, int format, void *data, int *cause)
static int console_text (struct ast_channel *c, const char *text)
static int console_write (struct ast_channel *chan, struct ast_frame *f)

Detailed Description

Cross-platform console channel driver.

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

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

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

Definition in file chan_console.c.


Define Documentation

#define console_pvt_lock ( pvt   )     ao2_lock(pvt)
#define console_pvt_unlock ( pvt   )     ao2_unlock(pvt)
#define INPUT_CHANNELS   1

Mono Input.

Definition at line 92 of file chan_console.c.

Referenced by open_stream().

#define NUM_PVT_BUCKETS   7

Definition at line 166 of file chan_console.c.

Referenced by load_module().

#define NUM_SAMPLES   320

The number of samples to configure the portaudio stream for.

320 samples (20 ms) is the most common frame size in Asterisk. So, the code in this module reads 320 sample frames from the portaudio stream and queues them up on the Asterisk channel. Frames of any size can be written to a portaudio stream, but the portaudio documentation does say that for high performance applications, the data should be written to Pa_WriteStream in the same size as what is used to initialize the stream.

Definition at line 89 of file chan_console.c.

Referenced by open_stream(), and stream_monitor().

#define OUTPUT_CHANNELS   1

Mono Output.

Definition at line 95 of file chan_console.c.

Referenced by open_stream().

#define SAMPLE_RATE   16000

The sample rate to request from PortAudio.

Todo:
Make this optional. If this is only going to talk to 8 kHz endpoints, then it makes sense to use 8 kHz natively.

Definition at line 77 of file chan_console.c.

#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )

Formats natively supported by this module.

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

static void __unreg_module ( void   )  [static]

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

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

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

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 autoanswer [on|off]";
00692       e->usage =
00693          "Usage: console set 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::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 1361 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().

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

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

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

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

References ao2_callback, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), build_device(), context, destroy_pvts(), global_jbconf, globals, globals_lock, LOG_NOTICE, ast_variable::name, ast_variable::next, OBJ_NODATA, pvt_mark_destroy_cb(), set_pvt_defaults(), store_config_core(), and ast_variable::value.

Referenced by load_module(), and reload().

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

static int load_module ( void   )  [static]

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

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

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

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module().

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

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1306 of file chan_console.c.

References ast_string_field_free_memory.

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

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

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

Definition at line 1423 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module().

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

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

Definition at line 1354 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

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

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

References load_config().

01513 {
01514    return load_config(1);
01515 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Console Channel Driver" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

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

struct ast_cli_entry cli_console[] [static]

Definition at line 1213 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 on 8 Apr 2010 for Asterisk - the Open Source PBX by  doxygen 1.6.1