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


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 230 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 233 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_mousedown(), 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 173 of file chan_console.c.

Referenced by load_module().

#define NUM_SAMPLES   320

The number of samples to configure the portaudio stream for.

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

Definition at line 89 of file chan_console.c.

Referenced by open_stream(), and stream_monitor().

#define OUTPUT_CHANNELS   1

Mono Output.

Definition at line 95 of file chan_console.c.

Referenced by open_stream().

#define SAMPLE_RATE   16000

The sample rate to request from PortAudio.

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

Definition at line 77 of file chan_console.c.

#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )

Formats natively supported by this module.

Definition at line 210 of file chan_console.c.

Referenced by console_request().

#define TEXT_SIZE   256

Maximum text message length.

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

Definition at line 102 of file chan_console.c.

Referenced by cli_console_sendtext(), and console_sendtext().

#define V_BEGIN   " --- <(\"<) --- "

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

References ast_strdup, and console_pvt::overridecontext.

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

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

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

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

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

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

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

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

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

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

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

Definition at line 689 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), console_pvt::autoanswer, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), unref_pvt(), and ast_cli_entry::usage.

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

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

Definition at line 774 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_debug, ast_exists_extension(), ast_ext_ctx(), AST_FRAME_DTMF, ast_queue_frame(), AST_STATE_RINGING, ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_new(), console_pvt_lock, console_pvt_unlock, console_pvt::context, ext, console_pvt::exten, f, ast_cli_args::fd, free, get_active_pvt(), console_pvt::owner, s, unref_pvt(), and ast_cli_entry::usage.

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

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

Definition at line 737 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), AST_CONTROL_FLASH, AST_FRAME_CONTROL, ast_queue_frame(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, f, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

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

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

Definition at line 848 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), ast_queue_hangup(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), console_pvt::hookstate, console_pvt::owner, unref_pvt(), and ast_cli_entry::usage.

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

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

Definition at line 884 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), ast_verb, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, get_active_pvt(), console_pvt::muted, s, unref_pvt(), ast_cli_entry::usage, V_BEGIN, and V_END.

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

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

Console send text CLI command.

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

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

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

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

Definition at line 923 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, num, and ast_cli_entry::usage.

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

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

Definition at line 971 of file chan_console.c.

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

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

static int console_answer ( struct ast_channel c  )  [static]

Definition at line 523 of file chan_console.c.

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

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

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

Definition at line 561 of file chan_console.c.

References AST_CONTROL_ANSWER, AST_CONTROL_RINGING, AST_FRAME_CONTROL, ast_indicate(), ast_queue_frame(), ast_verb, console_pvt::autoanswer, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, console_pvt_lock, console_pvt_unlock, f, console_pvt::hookstate, start_stream(), ast_channel::tech_pvt, V_BEGIN, and V_END.

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

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

Definition at line 486 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 493 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 635 of file chan_console.c.

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

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

static int console_hangup ( struct ast_channel c  )  [static]

Definition at line 508 of file chan_console.c.

References ast_verb, console_pvt::hookstate, console_pvt::owner, stop_stream(), ast_channel::tech_pvt, unref_pvt(), V_BEGIN, and V_END.

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

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

Definition at line 600 of file chan_console.c.

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

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

static struct ast_channel* console_new ( struct console_pvt pvt,
const char *  ext,
const char *  ctx,
int  state 
) [static]

Note:
Called with the pvt struct locked

Definition at line 416 of file chan_console.c.

References AST_CAUSE_SWITCH_CONGESTION, ast_channel_alloc(), AST_FORMAT_SLINEAR16, ast_hangup(), ast_jb_configure(), ast_pbx_start(), AST_STATE_DOWN, ast_string_field_set, ast_strlen_zero(), chan, console_pvt::cid_name, console_pvt::cid_num, 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().

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

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

Definition at line 554 of file chan_console.c.

References ast_debug, and ast_null_frame.

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

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

Channel Technology Callbacks

Definition at line 450 of file chan_console.c.

References AST_CAUSE_BUSY, ast_log(), AST_STATE_DOWN, chan, console_new(), console_pvt_lock, console_pvt_unlock, find_pvt(), LOG_NOTICE, LOG_WARNING, console_pvt::owner, SUPPORTED_FORMATS, and unref_pvt().

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

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

Definition at line 501 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

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

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

Definition at line 591 of file chan_console.c.

References chan, f, console_pvt::stream, and ast_channel::tech_pvt.

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

static void destroy_pvts ( void   )  [static]

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

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

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

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

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

static struct console_pvt* get_active_pvt ( void   )  [static]

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

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

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

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

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

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

References ao2_callback, ast_category_browse(), ast_config_destroy(), ast_config_load, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_variable_browse(), build_device(), config_flags, 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.

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

static int load_module ( void   )  [static]

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

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

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

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

Definition at line 1431 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module().

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

static void pvt_destructor ( void *  obj  )  [static]

Definition at line 1308 of file chan_console.c.

References ast_string_field_free_memory.

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

01309 {
01310    struct console_pvt *pvt = obj;
01311 
01312    ast_string_field_free_memory(pvt);
01313 }

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

Definition at line 1424 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module().

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

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

Definition at line 1356 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

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

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

Definition at line 235 of file chan_console.c.

References ao2_ref.

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

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

static int reload ( void   )  [static]

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

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

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

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

Referenced by build_device(), and load_config().

01234 {
01235    if (pvt == &globals) {
01236       ast_string_field_set(pvt, mohinterpret, "default");
01237       ast_string_field_set(pvt, context, "default");
01238       ast_string_field_set(pvt, exten, "s");
01239       ast_string_field_set(pvt, language, "");
01240       ast_string_field_set(pvt, cid_num, "");
01241       ast_string_field_set(pvt, cid_name, "");
01242       ast_string_field_set(pvt, parkinglot, "");
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       ast_string_field_set(pvt, parkinglot, globals.parkinglot);
01256 
01257       pvt->overridecontext = globals.overridecontext;
01258       pvt->autoanswer = globals.autoanswer;
01259 
01260       ast_mutex_unlock(&globals_lock);
01261    }
01262 }

static int start_stream ( struct console_pvt pvt  )  [static]

Definition at line 354 of file chan_console.c.

References ast_debug, ast_log(), ast_pthread_create_background, console_pvt_lock, console_pvt_unlock, LOG_WARNING, open_stream(), console_pvt::stream, stream_monitor(), console_pvt::streamstate, and console_pvt::thread.

Referenced by console_answer(), console_call(), and console_new().

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

static int stop_stream ( struct console_pvt pvt  )  [static]

Definition at line 394 of file chan_console.c.

References AST_PTHREADT_NULL, console_pvt_lock, console_pvt_unlock, console_pvt::stream, console_pvt::streamstate, and console_pvt::thread.

Referenced by console_hangup(), and stop_streams().

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

static void stop_streams ( void   )  [static]

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

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

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

Definition at line 1264 of file chan_console.c.

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

Referenced by store_config(), and store_config_core().

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

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

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

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

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

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

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

static int unload_module ( void   )  [static]

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

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  )  [inline, static]

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

00243 {
00244    ao2_ref(pvt, -1);
00245    return NULL;
00246 }


Variable Documentation

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

Definition at line 1520 of file chan_console.c.

ast_rwlock_t active_lock = PTHREAD_RWLOCK_INITIALIZER [static]

Definition at line 176 of file chan_console.c.

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

struct console_pvt* active_pvt [static]

Definition at line 175 of file chan_console.c.

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

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 1215 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 212 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 183 of file chan_console.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 189 of file chan_console.c.

struct console_pvt globals [static]

Console pvt structure.

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

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

Definition at line 170 of file chan_console.c.

Referenced by load_config(), and set_pvt_defaults().

struct ao2_container* pvts [static]

Definition at line 172 of file chan_console.c.

Referenced by 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 Fri Jul 24 00:41:20 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7