Thu Jul 9 13:40:54 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"

Go to the source code of this file.

Data Structures

struct  console_pvt
 Console pvt structure. More...
#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)

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.

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


Detailed Description

Cross-platform console channel driver.

Author:
Russell Bryant <russell@digium.com>
Note:
Some of the code in this file came from chan_oss and chan_alsa. chan_oss, Mark Spencer <markster@digium.com> chan_oss, Luigi Rizzo chan_alsa, Matthew Fredrickson <creslin@digium.com>
ExtRef:
Portaudio http://www.portaudio.com/
To install portaudio v19 from svn, check it out using the following command:

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

Definition in file chan_console.c.


Define Documentation

#define console_pvt_lock ( pvt   )     ao2_lock(pvt)

lock a console_pvt struct

Definition at line 228 of file chan_console.c.

Referenced by build_device(), cli_console_active(), cli_console_dial(), cli_list_devices(), console_call(), console_request(), start_stream(), and stop_stream().

#define console_pvt_unlock ( pvt   )     ao2_unlock(pvt)

unlock a console_pvt struct

Definition at line 231 of file chan_console.c.

Referenced by build_device(), cli_console_active(), cli_console_dial(), cli_list_devices(), console_call(), console_request(), start_stream(), and stop_stream().

#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(), handle_response_register(), and sdl_setup().

#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   " --- <(\"<) --- "

Dance, Kirby, Dance!

Definition at line 112 of file chan_console.c.

Referenced by cli_console_mute(), console_answer(), console_call(), console_digit_begin(), console_digit_end(), console_hangup(), console_indicate(), and console_text().

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

Definition at line 113 of file chan_console.c.

Referenced by cli_console_mute(), console_answer(), console_call(), console_digit_begin(), console_digit_end(), console_hangup(), console_indicate(), and console_text().


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 1514 of file chan_console.c.

static void __unreg_module ( void   )  [static]

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

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

Referenced by load_config(), and reload_config().

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

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

Definition at line 1148 of file chan_console.c.

References 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, pvts, set_active(), unref_pvt(), ast_cli_entry::usage, and ast_cli_args::word.

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

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

answer command from the console

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

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

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, f, ast_cli_args::fd, free, get_active_pvt(), console_pvt::owner, s, 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, f, 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 1078 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, f, ast_cli_args::fd, get_active_pvt(), len(), console_pvt::owner, TEXT_SIZE, unref_pvt(), and ast_cli_entry::usage.

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

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 active_pvt, ao2_iterator_init(), ao2_iterator_next(), ast_cli_args::argc, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_pvt_lock, console_pvt_unlock, ast_cli_args::fd, pvts, 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 
01021    ast_cli(a->fd, "=============================================================\n\n");
01022 
01023    return CLI_SUCCESS;
01024 }

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, f, console_pvt::hookstate, start_stream(), 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, chan, 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]

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, console_tech, global_jbconf, 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]

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]

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_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 chan, f, 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 1357 of file chan_console.c.

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

Referenced by load_config().

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

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

Definition at line 246 of file chan_console.c.

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

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 struct console_pvt* get_active_pvt ( void   )  [static]

Definition at line 676 of file chan_console.c.

References active_lock, active_pvt, ast_rwlock_rdlock(), ast_rwlock_unlock(), and ref_pvt().

Referenced by cli_console_active(), cli_console_answer(), cli_console_autoanswer(), cli_console_dial(), cli_console_flash(), cli_console_hangup(), cli_console_mute(), and cli_console_sendtext().

00677 {
00678    struct console_pvt *pvt;
00679 
00680    ast_rwlock_rdlock(&active_lock);
00681    pvt = ref_pvt(active_pvt); 
00682    ast_rwlock_unlock(&active_lock);
00683 
00684    return pvt;
00685 }

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

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

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

static int load_config ( int  reload  )  [static]

Load the configuration.

Parameters:
reload if this was called due to a reload
Return values:
0 succcess
-1 failure

Definition at line 1381 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, default_jbconf, destroy_pvts(), global_jbconf, globals, globals_lock, LOG_NOTICE, ast_variable::name, ast_variable::next, OBJ_NODATA, pvt_mark_destroy_cb(), pvts, set_pvt_defaults(), store_config_core(), and ast_variable::value.

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

static int load_module ( void   )  [static]

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

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

static int open_stream ( struct console_pvt pvt  )  [static]

Definition at line 291 of file chan_console.c.

References INPUT_CHANNELS, console_pvt::input_device, 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 1425 of file chan_console.c.

References CMP_MATCH, and console_pvt::name.

Referenced by load_module().

01426 {
01427    struct console_pvt *pvt = obj, *pvt2 = arg;
01428 
01429    return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH : 0;
01430 }

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1302 of file chan_console.c.

References ast_string_field_free_memory.

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

01303 {
01304    struct console_pvt *pvt = obj;
01305 
01306    ast_string_field_free_memory(pvt);
01307 }

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

Definition at line 1418 of file chan_console.c.

References ast_str_hash(), and console_pvt::name.

Referenced by load_module().

01419 {
01420    const struct console_pvt *pvt = obj;
01421 
01422    return ast_str_hash(pvt->name);
01423 }

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

Definition at line 1350 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

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

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

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

References load_config().

01506 {
01507    return load_config(1);
01508 }

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

Definition at line 1131 of file chan_console.c.

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

Referenced by cli_console_active(), and store_config_core().

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

static void set_pvt_defaults ( struct console_pvt pvt  )  [static]

Set default values for a pvt struct.

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

Definition at line 1230 of file chan_console.c.

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

Referenced by build_device(), and load_config().

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

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

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

Referenced by unload_module().

01433 {
01434    struct console_pvt *pvt;
01435    struct ao2_iterator i;
01436 
01437    i = ao2_iterator_init(pvts, 0);
01438    while ((pvt = ao2_iterator_next(&i))) {
01439       if (pvt->hookstate)
01440          stop_stream(pvt);
01441       unref_pvt(pvt);
01442    }
01443 }

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

Definition at line 1259 of file chan_console.c.

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

Referenced by store_config_core().

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

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

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

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

Stream monitor thread.

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, f, 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 1445 of file chan_console.c.

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

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

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

Definition at line 240 of file chan_console.c.

References ao2_ref().

Referenced by build_device(), cli_console_active(), cli_console_answer(), cli_console_autoanswer(), cli_console_dial(), cli_console_flash(), cli_console_hangup(), cli_console_mute(), cli_console_sendtext(), cli_list_devices(), console_hangup(), console_request(), destroy_pvts(), set_active(), and stop_streams().

00241 {
00242    ao2_ref(pvt, -1);
00243    return NULL;
00244 }


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

Definition at line 1514 of file chan_console.c.

ast_rwlock_t active_lock = PTHREAD_RWLOCK_INITIALIZER [static]

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.

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

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 1514 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

Definition at line 1212 of file chan_console.c.

Referenced by load_module(), and unload_module().

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.

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

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_RECURSIVE_MUTEX_INITIALIZER_NP ) [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 build_device(), cli_console_active(), cli_list_devices(), destroy_pvts(), find_pvt(), load_config(), load_module(), pri_create_trunkgroup(), setup_dahdi(), stop_streams(), and unload_module().


Generated on Thu Jul 9 13:40:55 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7