Thu Apr 28 2011 17:15:38

Asterisk developer's documentation


chan_console.c File Reference

Cross-platform console channel driver. More...

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

Go to the source code of this file.

Data Structures

struct  console_pvt
 Console pvt structure. More...

Defines

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

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * ast_ext_ctx (struct console_pvt *pvt, const char *src, char **ext, char **ctx)
static void build_device (struct ast_config *cfg, const char *name)
static char * cli_console_active (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_answer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 answer command from the console
static char * cli_console_autoanswer (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_dial (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_flash (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_hangup (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_mute (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_console_sendtext (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Console send text CLI command.
static char * cli_list_available (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * cli_list_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_channelconsole_new (struct console_pvt *pvt, const char *ext, const char *ctx, int state)
static void destroy_pvts (void)
static struct console_pvtfind_pvt (const char *name)
static struct console_pvtget_active_pvt (void)
static int init_pvt (struct console_pvt *pvt, const char *name)
static int load_config (int reload)
 Load the configuration.
static int load_module (void)
static int open_stream (struct console_pvt *pvt)
static int pvt_cmp_cb (void *obj, void *arg, int flags)
static void pvt_destructor (void *obj)
static int pvt_hash_cb (const void *obj, const int flags)
static int pvt_mark_destroy_cb (void *obj, void *arg, int flags)
static struct console_pvtref_pvt (struct console_pvt *pvt)
static int reload (void)
static void set_active (struct console_pvt *pvt, const char *value)
static void set_pvt_defaults (struct console_pvt *pvt)
 Set default values for a pvt struct.
static int start_stream (struct console_pvt *pvt)
static int stop_stream (struct console_pvt *pvt)
static void stop_streams (void)
static void store_callerid (struct console_pvt *pvt, const char *value)
static void store_config_core (struct console_pvt *pvt, const char *var, const char *value)
 Store a configuration parameter in a pvt struct.
static void * stream_monitor (void *data)
 Stream monitor thread.
static int unload_module (void)
static struct console_pvtunref_pvt (struct console_pvt *pvt)
static struct ast_channelconsole_request (const char *type, int format, void *data, int *cause)
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_text (struct ast_channel *c, const char *text)
static int console_hangup (struct ast_channel *c)
static int console_answer (struct ast_channel *c)
static struct ast_frameconsole_read (struct ast_channel *chan)
static int console_call (struct ast_channel *c, char *dest, int timeout)
static int console_write (struct ast_channel *chan, struct ast_frame *f)
static int console_indicate (struct ast_channel *chan, int cond, const void *data, size_t datalen)
static int console_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)

Variables

static struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Console Channel Driver" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static ast_rwlock_t active_lock = AST_RWLOCK_INIT_VALUE
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
static ast_mutex_t globals_lock = AST_MUTEX_INIT_VALUE
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:
  • Set Auto-answer from the dialplan
  • transfer CLI command
  • boost CLI command and .conf option
  • console_video support

Definition in file chan_console.c.


Define Documentation

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

Mono Input.

Definition at line 92 of file chan_console.c.

Referenced by open_stream().

#define NUM_PVT_BUCKETS   7

Definition at line 166 of file chan_console.c.

Referenced by load_module().

#define NUM_SAMPLES   320

The number of samples to configure the portaudio stream for.

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

Definition at line 89 of file chan_console.c.

Referenced by open_stream(), and stream_monitor().

#define OUTPUT_CHANNELS   1

Mono Output.

Definition at line 95 of file chan_console.c.

Referenced by open_stream().

#define SAMPLE_RATE   16000

The sample rate to request from PortAudio.

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

Definition at line 77 of file chan_console.c.

Referenced by open_stream().

#define SUPPORTED_FORMATS   ( AST_FORMAT_SLINEAR16 )

Formats natively supported by this module.

Definition at line 204 of file chan_console.c.

Referenced by console_request().

#define TEXT_SIZE   256

Maximum text message length.

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

Definition at line 102 of file chan_console.c.

Referenced by cli_console_sendtext().

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

Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 1529 of file chan_console.c.

static void __unreg_module ( void  ) [static]

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

References ast_strdup, ext, and console_pvt::overridecontext.

Referenced by cli_console_dial().

{
   if (ext == NULL || ctx == NULL)
      return NULL;         /* error */

   *ext = *ctx = NULL;

   if (src && *src != '\0')
      *ext = ast_strdup(src);

   if (*ext == NULL)
      return NULL;

   if (!pvt->overridecontext) {
      /* parse from the right */
      *ctx = strrchr(*ext, '@');
      if (*ctx)
         *(*ctx)++ = '\0';
   }

   return *ext;
}
static void build_device ( struct ast_config cfg,
const char *  name 
) [static]

Definition at line 1330 of file chan_console.c.

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

Referenced by load_config().

{
   struct ast_variable *v;
   struct console_pvt *pvt;
   int new = 0;

   if ((pvt = find_pvt(name))) {
      console_pvt_lock(pvt);
      set_pvt_defaults(pvt);
      pvt->destroy = 0;
   } else {
      if (!(pvt = ao2_alloc(sizeof(*pvt), pvt_destructor)))
         return;
      init_pvt(pvt, name);
      set_pvt_defaults(pvt);
      new = 1;
   }

   for (v = ast_variable_browse(cfg, name); v; v = v->next)
      store_config_core(pvt, v->name, v->value);

   if (new)
      ao2_link(pvts, pvt);
   else
      console_pvt_unlock(pvt);
   
   unref_pvt(pvt);
}
static char* cli_console_active ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 1153 of file chan_console.c.

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

{
   struct console_pvt *pvt;

   switch (cmd) {
   case CLI_INIT:
      e->command = "console {set|show} active";
      e->usage =
         "Usage: console {set|show} active [<device>]\n"
         "       Set or show the active console device for the Asterisk CLI.\n";
      return NULL;
   case CLI_GENERATE:
      if (a->pos == e->args) {
         struct ao2_iterator i;
         int x = 0;
         char *res = NULL;
         i = ao2_iterator_init(pvts, 0);
         while ((pvt = ao2_iterator_next(&i))) {
            if (++x > a->n && !strncasecmp(pvt->name, a->word, strlen(a->word)))
               res = ast_strdup(pvt->name);
            unref_pvt(pvt);
            if (res) {
               ao2_iterator_destroy(&i);
               return res;
            }
         }
         ao2_iterator_destroy(&i);
      }
      return NULL;
   }

   if (a->argc < e->args)
      return CLI_SHOWUSAGE;

   if (a->argc == 3) {
      pvt = get_active_pvt();

      if (!pvt)
         ast_cli(a->fd, "No device is currently set as the active console device.\n");
      else {
         console_pvt_lock(pvt);
         ast_cli(a->fd, "The active console device is '%s'.\n", pvt->name);
         console_pvt_unlock(pvt);
         pvt = unref_pvt(pvt);
      }

      return CLI_SUCCESS;
   }

   if (!(pvt = find_pvt(a->argv[e->args - 1]))) {
      ast_cli(a->fd, "Could not find a device called '%s'.\n", a->argv[e->args]);
      return CLI_FAILURE;
   }

   set_active(pvt, "yes");

   console_pvt_lock(pvt);
   ast_cli(a->fd, "The active console device has been set to '%s'\n", pvt->name);
   console_pvt_unlock(pvt);

   unref_pvt(pvt);

   return CLI_SUCCESS;
}
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 1033 of file chan_console.c.

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

{
   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
   struct console_pvt *pvt = get_active_pvt();

   switch (cmd) {
   case CLI_INIT:
      e->command = "console answer";
      e->usage =
         "Usage: console answer\n"
         "       Answers an incoming call on the console channel.\n";
      return NULL;

   case CLI_GENERATE:
      return NULL;   /* no completion */
   }

   if (!pvt) {
      ast_cli(a->fd, "No console device is set as active\n");
      return CLI_FAILURE;
   }

   if (a->argc != e->args) {
      unref_pvt(pvt);
      return CLI_SHOWUSAGE;
   }

   if (!pvt->owner) {
      ast_cli(a->fd, "No one is calling us\n");
      unref_pvt(pvt);
      return CLI_FAILURE;
   }

   pvt->hookstate = 1;

   ast_indicate(pvt->owner, -1);

   ast_queue_frame(pvt->owner, &f);

   unref_pvt(pvt);

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

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

{
   struct console_pvt *pvt = get_active_pvt();
   char *res = CLI_SUCCESS;

   switch (cmd) {
   case CLI_INIT:
      e->command = "console {set|show} autoanswer [on|off]";
      e->usage =
         "Usage: console {set|show} autoanswer [on|off]\n"
         "       Enables or disables autoanswer feature.  If used without\n"
         "       argument, displays the current on/off status of autoanswer.\n"
         "       The default value of autoanswer is in 'oss.conf'.\n";
      return NULL;

   case CLI_GENERATE:
      return NULL;
   }

   if (!pvt) {
      ast_cli(a->fd, "No console device is set as active.\n");
      return CLI_FAILURE;
   }

   if (a->argc == e->args - 1) {
      ast_cli(a->fd, "Auto answer is %s.\n", pvt->autoanswer ? "on" : "off");
      unref_pvt(pvt);
      return CLI_SUCCESS;
   }

   if (a->argc != e->args) {
      unref_pvt(pvt);
      return CLI_SHOWUSAGE;
   }

   if (!strcasecmp(a->argv[e->args-1], "on"))
      pvt->autoanswer = 1;
   else if (!strcasecmp(a->argv[e->args - 1], "off"))
      pvt->autoanswer = 0;
   else
      res = CLI_SHOWUSAGE;

   unref_pvt(pvt);

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

Definition at line 775 of file chan_console.c.

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

{
   char *s = NULL;
   const char *mye = NULL, *myc = NULL; 
   struct console_pvt *pvt = get_active_pvt();

   if (cmd == CLI_INIT) {
      e->command = "console dial";
      e->usage =
         "Usage: console dial [extension[@context]]\n"
         "       Dials a given extension (and context if specified)\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (!pvt) {
      ast_cli(a->fd, "No console device is currently set as active\n");
      return CLI_FAILURE;
   }
   
   if (a->argc > e->args + 1)
      return CLI_SHOWUSAGE;

   if (pvt->owner) { /* already in a call */
      int i;
      struct ast_frame f = { AST_FRAME_DTMF, 0 };

      if (a->argc == e->args) {  /* argument is mandatory here */
         ast_cli(a->fd, "Already in a call. You can only dial digits until you hangup.\n");
         unref_pvt(pvt);
         return CLI_FAILURE;
      }
      s = a->argv[e->args];
      /* send the string one char at a time */
      for (i = 0; i < strlen(s); i++) {
         f.subclass = s[i];
         ast_queue_frame(pvt->owner, &f);
      }
      unref_pvt(pvt);
      return CLI_SUCCESS;
   }

   /* if we have an argument split it into extension and context */
   if (a->argc == e->args + 1) {
      char *ext = NULL, *con = NULL;
      s = ast_ext_ctx(pvt, a->argv[e->args], &ext, &con);
      ast_debug(1, "provided '%s', exten '%s' context '%s'\n", 
         a->argv[e->args], mye, myc);
      mye = ext;
      myc = con;
   }

   /* supply default values if needed */
   if (ast_strlen_zero(mye))
      mye = pvt->exten;
   if (ast_strlen_zero(myc))
      myc = pvt->context;

   if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
      console_pvt_lock(pvt);
      pvt->hookstate = 1;
      console_new(pvt, mye, myc, AST_STATE_RINGING);
      console_pvt_unlock(pvt);
   } else
      ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);

   if (s)
      free(s);

   unref_pvt(pvt);

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

Definition at line 738 of file chan_console.c.

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

{
   struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_FLASH };
   struct console_pvt *pvt = get_active_pvt();

   if (cmd == CLI_INIT) {
      e->command = "console flash";
      e->usage =
         "Usage: console flash\n"
         "       Flashes the call currently placed on the console.\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (!pvt) {
      ast_cli(a->fd, "No console device is set as active\n");
      return CLI_FAILURE;
   }

   if (a->argc != e->args)
      return CLI_SHOWUSAGE;

   if (!pvt->owner) {
      ast_cli(a->fd, "No call to flash\n");
      unref_pvt(pvt);
      return CLI_FAILURE;
   }

   pvt->hookstate = 0;

   ast_queue_frame(pvt->owner, &f);

   unref_pvt(pvt);

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

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

{
   struct console_pvt *pvt = get_active_pvt();

   if (cmd == CLI_INIT) {
      e->command = "console hangup";
      e->usage =
         "Usage: console hangup\n"
         "       Hangs up any call currently placed on the console.\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (!pvt) {
      ast_cli(a->fd, "No console device is set as active\n");
      return CLI_FAILURE;
   }
   
   if (a->argc != e->args)
      return CLI_SHOWUSAGE;

   if (!pvt->owner && !pvt->hookstate) {
      ast_cli(a->fd, "No call to hang up\n");
      unref_pvt(pvt);
      return CLI_FAILURE;
   }

   pvt->hookstate = 0;
   if (pvt->owner)
      ast_queue_hangup(pvt->owner);

   unref_pvt(pvt);

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

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

{
   char *s;
   struct console_pvt *pvt = get_active_pvt();
   char *res = CLI_SUCCESS;

   if (cmd == CLI_INIT) {
      e->command = "console {mute|unmute}";
      e->usage =
         "Usage: console {mute|unmute}\n"
         "       Mute/unmute the microphone.\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (!pvt) {
      ast_cli(a->fd, "No console device is set as active\n");
      return CLI_FAILURE;
   }

   if (a->argc != e->args)
      return CLI_SHOWUSAGE;

   s = a->argv[e->args-1];
   if (!strcasecmp(s, "mute"))
      pvt->muted = 1;
   else if (!strcasecmp(s, "unmute"))
      pvt->muted = 0;
   else
      res = CLI_SHOWUSAGE;

   ast_verb(1, V_BEGIN "The Console is now %s" V_END, 
      pvt->muted ? "Muted" : "Unmuted");

   unref_pvt(pvt);

   return res;
}
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 1083 of file chan_console.c.

References ast_cli_args::argc, ast_cli_entry::args, ast_cli_args::argv, ast_cli(), AST_FRAME_TEXT, ast_join(), ast_queue_frame(), ast_strlen_zero(), buf, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_frame::datalen, ast_cli_args::fd, ast_frame::frametype, get_active_pvt(), len(), console_pvt::owner, TEXT_SIZE, unref_pvt(), and ast_cli_entry::usage.

{
   char buf[TEXT_SIZE];
   struct console_pvt *pvt = get_active_pvt();
   struct ast_frame f = {
      .frametype = AST_FRAME_TEXT,
      .data.ptr = buf,
      .src = "console_send_text",
   };
   int len;

   if (cmd == CLI_INIT) {
      e->command = "console send text";
      e->usage =
         "Usage: console send text <message>\n"
         "       Sends a text message for display on the remote terminal.\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (!pvt) {
      ast_cli(a->fd, "No console device is set as active\n");
      return CLI_FAILURE;
   }

   if (a->argc < e->args + 1) {
      unref_pvt(pvt);
      return CLI_SHOWUSAGE;
   }

   if (!pvt->owner) {
      ast_cli(a->fd, "Not in a call\n");
      unref_pvt(pvt);
      return CLI_FAILURE;
   }

   ast_join(buf, sizeof(buf) - 1, a->argv + e->args);
   if (ast_strlen_zero(buf)) {
      unref_pvt(pvt);
      return CLI_SHOWUSAGE;
   }

   len = strlen(buf);
   buf[len] = '\n';
   f.datalen = len + 1;

   ast_queue_frame(pvt->owner, &f);

   unref_pvt(pvt);

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

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

{
   PaDeviceIndex idx, num, def_input, def_output;

   if (cmd == CLI_INIT) {
      e->command = "console list available";
      e->usage =
         "Usage: console list available\n"
         "       List all available devices.\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (a->argc != e->args)
      return CLI_SHOWUSAGE;

   ast_cli(a->fd, "\n"
               "=============================================================\n"
               "=== Available Devices =======================================\n"
               "=============================================================\n"
               "===\n");

   num = Pa_GetDeviceCount();
   if (!num) {
      ast_cli(a->fd, "(None)\n");
      return CLI_SUCCESS;
   }

   def_input = Pa_GetDefaultInputDevice();
   def_output = Pa_GetDefaultOutputDevice();
   for (idx = 0; idx < num; idx++) {
      const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);
      if (!dev)
         continue;
      ast_cli(a->fd, "=== ---------------------------------------------------------\n"
                     "=== Device Name: %s\n", dev->name);
      if (dev->maxInputChannels)
         ast_cli(a->fd, "=== ---> %sInput Device\n", (idx == def_input) ? "Default " : "");
      if (dev->maxOutputChannels)
         ast_cli(a->fd, "=== ---> %sOutput Device\n", (idx == def_output) ? "Default " : "");
      ast_cli(a->fd, "=== ---------------------------------------------------------\n===\n");
   }

   ast_cli(a->fd, "=============================================================\n\n");

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

Definition at line 972 of file chan_console.c.

References ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, ast_cli_args::argc, ast_cli_entry::args, ast_cli(), console_pvt::autoanswer, console_pvt::cid_name, console_pvt::cid_num, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, console_pvt_lock, console_pvt_unlock, console_pvt::context, console_pvt::exten, ast_cli_args::fd, console_pvt::input_device, console_pvt::language, console_pvt::mohinterpret, console_pvt::muted, console_pvt::name, console_pvt::output_device, console_pvt::overridecontext, console_pvt::parkinglot, unref_pvt(), and ast_cli_entry::usage.

{
   struct ao2_iterator i;
   struct console_pvt *pvt;

   if (cmd == CLI_INIT) {
      e->command = "console list devices";
      e->usage =
         "Usage: console list devices\n"
         "       List all configured devices.\n";
      return NULL;
   } else if (cmd == CLI_GENERATE)
      return NULL;

   if (a->argc != e->args)
      return CLI_SHOWUSAGE;

   ast_cli(a->fd, "\n"
               "=============================================================\n"
               "=== Configured Devices ======================================\n"
               "=============================================================\n"
               "===\n");

   i = ao2_iterator_init(pvts, 0);
   while ((pvt = ao2_iterator_next(&i))) {
      console_pvt_lock(pvt);

      ast_cli(a->fd, "=== ---------------------------------------------------------\n"
                     "=== Device Name: %s\n"
                     "=== ---> Active:           %s\n"
                     "=== ---> Input Device:     %s\n"
                     "=== ---> Output Device:    %s\n"
                     "=== ---> Context:          %s\n"
                     "=== ---> Extension:        %s\n"
                     "=== ---> CallerID Num:     %s\n"
                     "=== ---> CallerID Name:    %s\n"
                     "=== ---> MOH Interpret:    %s\n"
                     "=== ---> Language:         %s\n"
                     "=== ---> Parkinglot:       %s\n"
                     "=== ---> Muted:            %s\n"
                     "=== ---> Auto-Answer:      %s\n"
                     "=== ---> Override Context: %s\n"
                     "=== ---------------------------------------------------------\n===\n",
         pvt->name, (pvt == active_pvt) ? "Yes" : "No",
         pvt->input_device, pvt->output_device, pvt->context,
         pvt->exten, pvt->cid_num, pvt->cid_name, pvt->mohinterpret,
         pvt->language, pvt->parkinglot, pvt->muted ? "Yes" : "No", pvt->autoanswer ? "Yes" : "No",
         pvt->overridecontext ? "Yes" : "No");

      console_pvt_unlock(pvt);
      unref_pvt(pvt);
   }
   ao2_iterator_destroy(&i);

   ast_cli(a->fd, "=============================================================\n\n");

   return CLI_SUCCESS;
}
static int console_answer ( struct ast_channel c) [static]

Definition at line 524 of file chan_console.c.

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

{
   struct console_pvt *pvt = c->tech_pvt;

   ast_verb(1, V_BEGIN "Call from Console has been Answered" V_END);

   ast_setstate(c, AST_STATE_UP);

   return start_stream(pvt);
}
static int console_call ( struct ast_channel c,
char *  dest,
int  timeout 
) [static]
static int console_digit_begin ( struct ast_channel c,
char  digit 
) [static]

Definition at line 487 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

{
   ast_verb(1, V_BEGIN "Console Received Beginning of Digit %c" V_END, digit);

   return -1; /* non-zero to request inband audio */
}
static int console_digit_end ( struct ast_channel c,
char  digit,
unsigned int  duration 
) [static]

Definition at line 494 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

{
   ast_verb(1, V_BEGIN "Console Received End of Digit %c (duration %u)" V_END, 
      digit, duration);

   return -1; /* non-zero to request inband audio */
}
static int console_fixup ( struct ast_channel oldchan,
struct ast_channel newchan 
) [static]

Definition at line 636 of file chan_console.c.

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

{
   struct console_pvt *pvt = newchan->tech_pvt;

   pvt->owner = newchan;

   return 0;
}
static int console_hangup ( struct ast_channel c) [static]

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

{
   struct console_pvt *pvt = c->tech_pvt;

   ast_verb(1, V_BEGIN "Hangup on Console" V_END);

   pvt->hookstate = 0;
   pvt->owner = NULL;
   stop_stream(pvt);

   c->tech_pvt = unref_pvt(pvt);

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

Definition at line 601 of file chan_console.c.

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

{
   struct console_pvt *pvt = chan->tech_pvt;
   int res = 0;

   switch (cond) {
   case AST_CONTROL_BUSY:
   case AST_CONTROL_CONGESTION:
   case AST_CONTROL_RINGING:
   case -1:
      res = -1;  /* Ask for inband indications */
      break;
   case AST_CONTROL_PROGRESS:
   case AST_CONTROL_PROCEEDING:
   case AST_CONTROL_VIDUPDATE:
   case AST_CONTROL_SRCUPDATE:
      break;
   case AST_CONTROL_HOLD:
      ast_verb(1, V_BEGIN "Console Has Been Placed on Hold" V_END);
      ast_moh_start(chan, data, pvt->mohinterpret);
      break;
   case AST_CONTROL_UNHOLD:
      ast_verb(1, V_BEGIN "Console Has Been Retrieved from Hold" V_END);
      ast_moh_stop(chan);
      break;
   default:
      ast_log(LOG_WARNING, "Don't know how to display condition %d on %s\n", 
         cond, chan->name);
      /* The core will play inband indications for us if appropriate */
      res = -1;
   }

   return res;
}
static struct ast_frame * console_read ( struct ast_channel chan) [static, read]

Definition at line 555 of file chan_console.c.

References ast_debug, and ast_null_frame.

{
   ast_debug(1, "I should not be called ...\n");

   return &ast_null_frame;
}
static struct ast_channel * console_request ( const char *  type,
int  format,
void *  data,
int *  cause 
) [static, read]

Channel Technology Callbacks

Definition at line 451 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(), format, LOG_ERROR, LOG_NOTICE, LOG_WARNING, console_pvt::owner, SUPPORTED_FORMATS, and unref_pvt().

{
   int oldformat = format;
   struct ast_channel *chan = NULL;
   struct console_pvt *pvt;

   if (!(pvt = find_pvt(data))) {
      ast_log(LOG_ERROR, "Console device '%s' not found\n", (char *) data);
      return NULL;
   }

   format &= SUPPORTED_FORMATS;
   if (!format) {
      ast_log(LOG_NOTICE, "Channel requested with unsupported format(s): '%d'\n", oldformat);
      goto return_unref;
   }

   if (pvt->owner) {
      ast_log(LOG_NOTICE, "Console channel already active!\n");
      *cause = AST_CAUSE_BUSY;
      goto return_unref;
   }

   console_pvt_lock(pvt);
   chan = console_new(pvt, NULL, NULL, AST_STATE_DOWN);
   console_pvt_unlock(pvt);

   if (!chan)
      ast_log(LOG_WARNING, "Unable to create new Console channel!\n");

return_unref:
   unref_pvt(pvt);

   return chan;
}
static int console_text ( struct ast_channel c,
const char *  text 
) [static]

Definition at line 502 of file chan_console.c.

References ast_verb, V_BEGIN, and V_END.

{
   ast_verb(1, V_BEGIN "Console Received Text '%s'" V_END, text);

   return 0;
}
static int console_write ( struct ast_channel chan,
struct ast_frame f 
) [static]

Definition at line 592 of file chan_console.c.

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

{
   struct console_pvt *pvt = chan->tech_pvt;

   Pa_WriteStream(pvt->stream, f->data.ptr, f->samples);

   return 0;
}
static void destroy_pvts ( void  ) [static]
static struct console_pvt* find_pvt ( const char *  name) [static, read]

Definition at line 242 of file chan_console.c.

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

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

{
   struct console_pvt tmp_pvt = {
      .name = name,
   };

   return ao2_find(pvts, &tmp_pvt, OBJ_POINTER);
}
static int init_pvt ( struct console_pvt pvt,
const char *  name 
) [static]

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

{
   pvt->thread = AST_PTHREADT_NULL;

   if (ast_string_field_init(pvt, 32))
      return -1;

   ast_string_field_set(pvt, name, S_OR(name, ""));

   return 0;
}
static int load_config ( int  reload) [static]

Load the configuration.

Parameters:
reloadif this was called due to a reload
Return values:
0success
-1failure

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

Referenced by load_module(), and reload().

{
   struct ast_config *cfg;
   struct ast_variable *v;
   struct ast_flags config_flags = { 0 };
   char *context = NULL;

   /* default values */
   memcpy(&global_jbconf, &default_jbconf, sizeof(global_jbconf));
   ast_mutex_lock(&globals_lock);
   set_pvt_defaults(&globals);
   ast_mutex_unlock(&globals_lock);

   if (!(cfg = ast_config_load(config_file, config_flags))) {
      ast_log(LOG_NOTICE, "Unable to open configuration file %s!\n", config_file);
      return -1;
   } else if (cfg == CONFIG_STATUS_FILEINVALID) {
      ast_log(LOG_NOTICE, "Config file %s has an invalid format\n", config_file);
      return -1;
   }
   
   ao2_callback(pvts, OBJ_NODATA, pvt_mark_destroy_cb, NULL);

   ast_mutex_lock(&globals_lock);
   for (v = ast_variable_browse(cfg, "general"); v; v = v->next)
      store_config_core(&globals, v->name, v->value);
   ast_mutex_unlock(&globals_lock);

   while ((context = ast_category_browse(cfg, context))) {
      if (strcasecmp(context, "general"))
         build_device(cfg, context);
   }

   ast_config_destroy(cfg);

   destroy_pvts();

   return 0;
}
static int load_module ( void  ) [static]

Definition at line 1476 of file chan_console.c.

References ao2_container_alloc, ao2_ref, ARRAY_LEN, ast_channel_register(), ast_channel_unregister(), ast_cli_register_multiple(), ast_cli_unregister_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, globals, init_pvt(), load_config(), LOG_ERROR, LOG_WARNING, NUM_PVT_BUCKETS, pvt_cmp_cb(), pvt_destructor(), and pvt_hash_cb().

{
   PaError res;

   init_pvt(&globals, NULL);

   if (!(pvts = ao2_container_alloc(NUM_PVT_BUCKETS, pvt_hash_cb, pvt_cmp_cb)))
      goto return_error;

   if (load_config(0))
      goto return_error;

   res = Pa_Initialize();
   if (res != paNoError) {
      ast_log(LOG_WARNING, "Failed to initialize audio system - (%d) %s\n",
         res, Pa_GetErrorText(res));
      goto return_error_pa_init;
   }

   if (ast_channel_register(&console_tech)) {
      ast_log(LOG_ERROR, "Unable to register channel type 'Console'\n");
      goto return_error_chan_reg;
   }

   if (ast_cli_register_multiple(cli_console, ARRAY_LEN(cli_console)))
      goto return_error_cli_reg;

   return AST_MODULE_LOAD_SUCCESS;

return_error_cli_reg:
   ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));
return_error_chan_reg:
   ast_channel_unregister(&console_tech);
return_error_pa_init:
   Pa_Terminate();
return_error:
   if (pvts)
      ao2_ref(pvts, -1);
   pvts = NULL;
   pvt_destructor(&globals);

   return AST_MODULE_LOAD_DECLINE;
}
static int open_stream ( struct console_pvt pvt) [static]

Definition at line 291 of file chan_console.c.

References ast_log(), INPUT_CHANNELS, console_pvt::input_device, LOG_ERROR, console_pvt::name, NUM_SAMPLES, OUTPUT_CHANNELS, console_pvt::output_device, SAMPLE_RATE, and console_pvt::stream.

Referenced by start_stream().

{
   int res = paInternalError;

   if (!strcasecmp(pvt->input_device, "default") && 
      !strcasecmp(pvt->output_device, "default")) {
      res = Pa_OpenDefaultStream(&pvt->stream, INPUT_CHANNELS, OUTPUT_CHANNELS, 
         paInt16, SAMPLE_RATE, NUM_SAMPLES, NULL, NULL);
   } else {
      PaStreamParameters input_params = { 
         .channelCount = 1,
         .sampleFormat = paInt16,
         .suggestedLatency = (1.0 / 50.0), /* 20 ms */
         .device = paNoDevice,
      };
      PaStreamParameters output_params = { 
         .channelCount = 1, 
         .sampleFormat = paInt16,
         .suggestedLatency = (1.0 / 50.0), /* 20 ms */
         .device = paNoDevice,
      };
      PaDeviceIndex idx, num_devices, def_input, def_output;

      if (!(num_devices = Pa_GetDeviceCount()))
         return res;

      def_input = Pa_GetDefaultInputDevice();
      def_output = Pa_GetDefaultOutputDevice();

      for (idx = 0; 
         idx < num_devices && (input_params.device == paNoDevice 
            || output_params.device == paNoDevice); 
         idx++) 
      {
         const PaDeviceInfo *dev = Pa_GetDeviceInfo(idx);

         if (dev->maxInputChannels) {
            if ( (idx == def_input && !strcasecmp(pvt->input_device, "default")) ||
               !strcasecmp(pvt->input_device, dev->name) )
               input_params.device = idx;
         }

         if (dev->maxOutputChannels) {
            if ( (idx == def_output && !strcasecmp(pvt->output_device, "default")) ||
               !strcasecmp(pvt->output_device, dev->name) )
               output_params.device = idx;
         }
      }

      if (input_params.device == paNoDevice)
         ast_log(LOG_ERROR, "No input device found for console device '%s'\n", pvt->name);
      if (output_params.device == paNoDevice)
         ast_log(LOG_ERROR, "No output device found for console device '%s'\n", pvt->name);

      res = Pa_OpenStream(&pvt->stream, &input_params, &output_params,
         SAMPLE_RATE, NUM_SAMPLES, paNoFlag, NULL, NULL);
   }

   return res;
}
static int pvt_cmp_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1438 of file chan_console.c.

References CMP_MATCH, CMP_STOP, and console_pvt::name.

Referenced by load_module().

{
   struct console_pvt *pvt = obj, *pvt2 = arg;

   return !strcasecmp(pvt->name, pvt2->name) ? CMP_MATCH | CMP_STOP : 0;
}
static void pvt_destructor ( void *  obj) [static]

Definition at line 1311 of file chan_console.c.

References ast_string_field_free_memory.

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

{
   struct console_pvt *pvt = obj;

   ast_string_field_free_memory(pvt);
}
static int pvt_hash_cb ( const void *  obj,
const int  flags 
) [static]

Definition at line 1431 of file chan_console.c.

References ast_str_case_hash(), and console_pvt::name.

Referenced by load_module().

{
   const struct console_pvt *pvt = obj;

   return ast_str_case_hash(pvt->name);
}
static int pvt_mark_destroy_cb ( void *  obj,
void *  arg,
int  flags 
) [static]

Definition at line 1359 of file chan_console.c.

References console_pvt::destroy.

Referenced by load_config().

{
   struct console_pvt *pvt = obj;
   pvt->destroy = 1;
   return 0;
}
static struct console_pvt* ref_pvt ( struct console_pvt pvt) [static, read]

Definition at line 229 of file chan_console.c.

References ao2_ref.

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

{
   if (pvt)
      ao2_ref(pvt, +1);
   return pvt;
}
static int reload ( void  ) [static]

Definition at line 1520 of file chan_console.c.

References load_config().

{
   return load_config(1);
}
static void set_active ( struct console_pvt pvt,
const char *  value 
) [static]

Definition at line 1136 of file chan_console.c.

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

Referenced by cli_console_active(), and store_config_core().

{
   if (pvt == &globals) {
      ast_log(LOG_ERROR, "active is only valid as a per-device setting\n");
      return;
   }

   if (!ast_true(value))
      return;

   ast_rwlock_wrlock(&active_lock);
   if (active_pvt)
      unref_pvt(active_pvt);
   active_pvt = ref_pvt(pvt);
   ast_rwlock_unlock(&active_lock);
}
static void set_pvt_defaults ( struct console_pvt pvt) [static]
static int start_stream ( struct console_pvt pvt) [static]

Definition at line 352 of file chan_console.c.

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

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

{
   PaError res;
   int ret_val = 0;

   console_pvt_lock(pvt);

   /* It is possible for console_hangup to be called before the
    * stream is started, if this is the case pvt->owner will be NULL
    * and start_stream should be aborted. */
   if (pvt->streamstate || !pvt->owner)
      goto return_unlock;

   pvt->streamstate = 1;
   ast_debug(1, "Starting stream\n");

   res = open_stream(pvt);
   if (res != paNoError) {
      ast_log(LOG_WARNING, "Failed to open stream - (%d) %s\n",
         res, Pa_GetErrorText(res));
      ret_val = -1;
      goto return_unlock;
   }

   res = Pa_StartStream(pvt->stream);
   if (res != paNoError) {
      ast_log(LOG_WARNING, "Failed to start stream - (%d) %s\n",
         res, Pa_GetErrorText(res));
      ret_val = -1;
      goto return_unlock;
   }

   if (ast_pthread_create_background(&pvt->thread, NULL, stream_monitor, pvt)) {
      ast_log(LOG_ERROR, "Failed to start stream monitor thread\n");
      ret_val = -1;
   }

return_unlock:
   console_pvt_unlock(pvt);

   return ret_val;
}
static int stop_stream ( struct console_pvt pvt) [static]

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

{
   if (!pvt->streamstate || pvt->thread == AST_PTHREADT_NULL)
      return 0;

   pthread_cancel(pvt->thread);
   pthread_kill(pvt->thread, SIGURG);
   pthread_join(pvt->thread, NULL);

   console_pvt_lock(pvt);
   Pa_AbortStream(pvt->stream);
   Pa_CloseStream(pvt->stream);
   pvt->stream = NULL;
   pvt->streamstate = 0;
   console_pvt_unlock(pvt);

   return 0;
}
static void stop_streams ( void  ) [static]

Definition at line 1445 of file chan_console.c.

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

Referenced by unload_module().

{
   struct console_pvt *pvt;
   struct ao2_iterator i;

   i = ao2_iterator_init(pvts, 0);
   while ((pvt = ao2_iterator_next(&i))) {
      if (pvt->hookstate)
         stop_stream(pvt);
      unref_pvt(pvt);
   }
   ao2_iterator_destroy(&i);
}
static void store_callerid ( struct console_pvt pvt,
const char *  value 
) [static]

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

{
   char cid_name[256];
   char cid_num[256];

   ast_callerid_split(value, cid_name, sizeof(cid_name), 
      cid_num, sizeof(cid_num));

   ast_string_field_set(pvt, cid_name, cid_name);
   ast_string_field_set(pvt, cid_num, cid_num);
}
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 1284 of file chan_console.c.

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

Referenced by build_device(), and load_config().

{
   if (pvt == &globals && !ast_jb_read_conf(&global_jbconf, var, value))
      return;

   CV_START(var, value);

   CV_STRFIELD("context", pvt, context);
   CV_STRFIELD("extension", pvt, exten);
   CV_STRFIELD("mohinterpret", pvt, mohinterpret);
   CV_STRFIELD("language", pvt, language);
   CV_F("callerid", store_callerid(pvt, value));
   CV_BOOL("overridecontext", pvt->overridecontext);
   CV_BOOL("autoanswer", pvt->autoanswer);
   CV_STRFIELD("parkinglot", pvt, parkinglot);

   if (pvt != &globals) {
      CV_F("active", set_active(pvt, value))
      CV_STRFIELD("input_device", pvt, input_device);
      CV_STRFIELD("output_device", pvt, output_device);
   }

   ast_log(LOG_WARNING, "Unknown option '%s'\n", var);

   CV_END;
}
static void* stream_monitor ( void *  data) [static]

Stream monitor thread.

  • data A pointer to the console_pvt structure that contains the portaudio stream that needs to be monitored.

This function runs in its own thread to monitor data coming in from a portaudio stream. When enough data is available, it is queued up to be read from the Asterisk channel.

Definition at line 261 of file chan_console.c.

References AST_FORMAT_SLINEAR16, AST_FRAME_VOICE, ast_queue_frame(), buf, ast_frame::frametype, NUM_SAMPLES, console_pvt::owner, ast_frame::samples, and console_pvt::stream.

Referenced by start_stream().

{
   struct console_pvt *pvt = data;
   char buf[NUM_SAMPLES * sizeof(int16_t)];
   PaError res;
   struct ast_frame f = {
      .frametype = AST_FRAME_VOICE,
      .subclass = AST_FORMAT_SLINEAR16,
      .src = "console_stream_monitor",
      .data.ptr = buf,
      .datalen = sizeof(buf),
      .samples = sizeof(buf) / sizeof(int16_t),
   };

   for (;;) {
      pthread_testcancel();
      res = Pa_ReadStream(pvt->stream, buf, sizeof(buf) / sizeof(int16_t));
      pthread_testcancel();

      if (!pvt->owner) {
         return NULL;
      }

      if (res == paNoError)
         ast_queue_frame(pvt->owner, &f);
   }

   return NULL;
}
static int unload_module ( void  ) [static]

Definition at line 1459 of file chan_console.c.

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

{
   ast_channel_unregister(&console_tech);
   ast_cli_unregister_multiple(cli_console, ARRAY_LEN(cli_console));

   stop_streams();

   Pa_Terminate();

   /* Will unref all the pvts so they will get destroyed, too */
   ao2_ref(pvts, -1);

   pvt_destructor(&globals);

   return 0;
}

Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Console Channel Driver" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 1529 of file chan_console.c.

ast_rwlock_t active_lock = AST_RWLOCK_INIT_VALUE [static]

Definition at line 169 of file chan_console.c.

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

struct console_pvt* active_pvt [static]

Definition at line 168 of file chan_console.c.

Definition at line 1529 of file chan_console.c.

struct ast_cli_entry cli_console[] [static]

Definition at line 1218 of file chan_console.c.

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

Definition at line 109 of file chan_console.c.

struct ast_channel_tech console_tech [static]

Definition at line 206 of file chan_console.c.

Referenced by console_new().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration.

Note:
Disabled by default.

Definition at line 176 of file chan_console.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 183 of file chan_console.c.

Referenced by console_new(), load_config(), and store_config_core().

ast_mutex_t globals_lock = AST_MUTEX_INIT_VALUE [static]

Definition at line 163 of file chan_console.c.

Referenced by load_config(), and set_pvt_defaults().

struct ao2_container* pvts [static]

Definition at line 165 of file chan_console.c.

Referenced by setup_dahdi().