Wed Oct 28 11:45:52 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 void fini_active_lock (void)
static struct console_pvtget_active_pvt (void)
static void init_active_lock (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
static struct console_pvtactive_pvt
static const struct
ast_module_info
ast_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 171 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 208 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 1520 of file chan_console.c.

static void __unreg_module ( void   )  [static]

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

References ast_strdup, and console_pvt::overridecontext.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 521 of file chan_console.c.

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

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

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

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

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

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

Definition at line 484 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

00485 {
00486    ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);
00487 
00488    return -1; /* non-zero to request inband audio */
00489 }

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

Definition at line 491 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 633 of file chan_console.c.

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

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

static int console_hangup ( struct ast_channel c  )  [static]

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

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

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

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

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

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

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

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

Definition at line 552 of file chan_console.c.

References ast_debug, and ast_null_frame.

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

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

Channel Technology Callbacks

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

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

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

Definition at line 499 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 589 of file chan_console.c.

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

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

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

References ao2_find(), console_pvt::name, and OBJ_POINTER.

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

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

static void fini_active_lock ( void   )  [static]

Definition at line 174 of file chan_console.c.

00181 {

static struct console_pvt* get_active_pvt ( void   )  [static, read]

static void init_active_lock ( void   )  [static]

Definition at line 174 of file chan_console.c.

00181 {

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.

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    pvt_destructor(&globals);
01507 
01508    return AST_MODULE_LOAD_DECLINE;
01509 }

static int open_stream ( struct console_pvt pvt  )  [static]

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

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

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

Definition at line 1430 of file chan_console.c.

References CMP_MATCH, and console_pvt::name.

Referenced by load_module(), and load_objects().

01431 {
01432    struct console_pvt *pvt = obj, *pvt2 = arg;
01433 
01434    return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH : 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(), new_iax(), 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_hash(), and console_pvt::name.

Referenced by load_module(), and load_objects().

01424 {
01425    const struct console_pvt *pvt = obj;
01426 
01427    return ast_str_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 233 of file chan_console.c.

References ao2_ref().

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

00234 {
00235    if (pvt)
00236       ao2_ref(pvt, +1);
00237    return pvt;
00238 }

static int reload ( void   )  [static]

Definition at line 1511 of file chan_console.c.

References load_config().

01512 {
01513    return load_config(1);
01514 }

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

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

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

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 1234 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, and console_pvt::overridecontext.

Referenced by build_device(), and load_config().

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

static int start_stream ( struct console_pvt pvt  )  [static]

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

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

static int stop_stream ( struct console_pvt pvt  )  [static]

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

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

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

References ast_callerid_split(), ast_string_field_set, cid_name, and cid_num.

Referenced by store_config_core().

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

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 1280 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, set_active(), and store_callerid().

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

01281 {
01282    if (pvt == &globals && !ast_jb_read_conf(&global_jbconf, var, value))
01283       return;
01284 
01285    CV_START(var, value);
01286 
01287    CV_STRFIELD("context", pvt, context);
01288    CV_STRFIELD("extension", pvt, exten);
01289    CV_STRFIELD("mohinterpret", pvt, mohinterpret);
01290    CV_STRFIELD("language", pvt, language);
01291    CV_F("callerid", store_callerid(pvt, value));
01292    CV_BOOL("overridecontext", pvt->overridecontext);
01293    CV_BOOL("autoanswer", pvt->autoanswer);
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 265 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().

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

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

Definition at line 1520 of file chan_console.c.

Definition at line 174 of file chan_console.c.

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

struct console_pvt* active_pvt [static]

Definition at line 173 of file chan_console.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1520 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

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

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration.

Note:
Disabled by default.

Definition at line 181 of file chan_console.c.

struct ast_jb_conf global_jbconf [static]

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

Referenced by load_config(), and set_pvt_defaults().

struct ao2_container* pvts [static]

Definition at line 170 of file chan_console.c.

Referenced by setup_dahdi().


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