Wed Oct 28 11:51:25 2009

Asterisk developer's documentation


app_mixmonitor.c File Reference

MixMonitor() - Record a call and mix the audio during the recording. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/audiohook.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"

Include dependency graph for app_mixmonitor.c:

Go to the source code of this file.

Data Structures

struct  mixmonitor
struct  mixmonitor_ds

Defines

#define get_volfactor(x)   x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
#define SAMPLES_PER_FRAME   160

Enumerations

enum  {
  MUXFLAG_APPEND = (1 << 1), MUXFLAG_BRIDGED = (1 << 2), MUXFLAG_VOLUME = (1 << 3), MUXFLAG_READVOLUME = (1 << 4),
  MUXFLAG_WRITEVOLUME = (1 << 5)
}
enum  { OPT_ARG_READVOLUME = 0, OPT_ARG_WRITEVOLUME, OPT_ARG_VOLUME, OPT_ARG_ARRAY_SIZE }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static char * handle_cli_mixmonitor (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void launch_monitor_thread (struct ast_channel *chan, const char *filename, unsigned int flags, int readvol, int writevol, const char *post_process)
static int load_module (void)
static void mixmonitor_ds_chan_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
static void mixmonitor_ds_close_fs (struct mixmonitor_ds *mixmonitor_ds)
static void mixmonitor_ds_destroy (void *data)
static int mixmonitor_exec (struct ast_channel *chan, void *data)
static void mixmonitor_free (struct mixmonitor *mixmonitor)
static void * mixmonitor_thread (void *obj)
static int setup_mixmonitor_ds (struct mixmonitor *mixmonitor, struct ast_channel *chan)
static int startmon (struct ast_channel *chan, struct ast_audiohook *audiohook)
static int stop_mixmonitor_exec (struct ast_channel *chan, void *data)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mixed Audio Monitoring Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static const char * app = "MixMonitor"
static struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_mixmonitor []
static const char * desc
struct module_symbols * me
enum { ... }  mixmonitor_args
static struct ast_datastore_info mixmonitor_ds_info
enum { ... }  mixmonitor_flags
static struct ast_app_option mixmonitor_opts [128] = { [ 'a' ] = { .flag = MUXFLAG_APPEND }, [ 'b' ] = { .flag = MUXFLAG_BRIDGED }, [ 'v' ] = { .flag = MUXFLAG_READVOLUME , .arg_index = OPT_ARG_READVOLUME + 1 }, [ 'V' ] = { .flag = MUXFLAG_WRITEVOLUME , .arg_index = OPT_ARG_WRITEVOLUME + 1 }, [ 'W' ] = { .flag = MUXFLAG_VOLUME , .arg_index = OPT_ARG_VOLUME + 1 },}
static const char * mixmonitor_spy_type = "MixMonitor"
static const char * stop_app = "StopMixMonitor"
static const char * stop_desc
static const char * stop_synopsis = "Stop recording a call through MixMonitor"
static const char * synopsis = "Record a call and mix the audio during the recording"


Detailed Description

MixMonitor() - Record a call and mix the audio during the recording.

Author:
Mark Spencer <markster@digium.com>

Kevin P. Fleming <kpfleming@digium.com>

Note:
Based on app_muxmon.c provided by Anthony Minessale II <anthmct@yahoo.com>

Definition in file app_mixmonitor.c.


Define Documentation

#define get_volfactor (  )     x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0

Definition at line 49 of file app_mixmonitor.c.

Referenced by mixmonitor_exec().

#define SAMPLES_PER_FRAME   160

Definition at line 199 of file app_mixmonitor.c.

Referenced by mixmonitor_thread().


Enumeration Type Documentation

anonymous enum

Enumerator:
MUXFLAG_APPEND 
MUXFLAG_BRIDGED 
MUXFLAG_VOLUME 
MUXFLAG_READVOLUME 
MUXFLAG_WRITEVOLUME 

Definition at line 99 of file app_mixmonitor.c.

00099      {
00100    MUXFLAG_APPEND = (1 << 1),
00101    MUXFLAG_BRIDGED = (1 << 2),
00102    MUXFLAG_VOLUME = (1 << 3),
00103    MUXFLAG_READVOLUME = (1 << 4),
00104    MUXFLAG_WRITEVOLUME = (1 << 5),
00105 } mixmonitor_flags;

anonymous enum

Enumerator:
OPT_ARG_READVOLUME 
OPT_ARG_WRITEVOLUME 
OPT_ARG_VOLUME 
OPT_ARG_ARRAY_SIZE 

Definition at line 107 of file app_mixmonitor.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 553 of file app_mixmonitor.c.

static void __unreg_module ( void   )  [static]

Definition at line 553 of file app_mixmonitor.c.

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

Definition at line 491 of file app_mixmonitor.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_audiohook_detach_source(), ast_channel_unlock, ast_cli(), ast_complete_channels(), ast_get_channel_by_name_prefix_locked(), chan, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, ast_cli_args::line, mixmonitor_exec(), ast_cli_args::n, ast_cli_args::pos, ast_cli_entry::usage, and ast_cli_args::word.

00492 {
00493    struct ast_channel *chan;
00494 
00495    switch (cmd) {
00496    case CLI_INIT:
00497       e->command = "mixmonitor [start|stop]";
00498       e->usage =
00499          "Usage: mixmonitor <start|stop> <chan_name> [args]\n"
00500          "       The optional arguments are passed to the MixMonitor\n"
00501          "       application when the 'start' command is used.\n";
00502       return NULL;
00503    case CLI_GENERATE:
00504       return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
00505    }
00506 
00507    if (a->argc < 3)
00508       return CLI_SHOWUSAGE;
00509 
00510    if (!(chan = ast_get_channel_by_name_prefix_locked(a->argv[2], strlen(a->argv[2])))) {
00511       ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]);
00512       /* Technically this is a failure, but we don't want 2 errors printing out */
00513       return CLI_SUCCESS;
00514    }
00515 
00516    if (!strcasecmp(a->argv[1], "start")) {
00517       mixmonitor_exec(chan, a->argv[3]);
00518       ast_channel_unlock(chan);
00519    } else {
00520       ast_channel_unlock(chan);
00521       ast_audiohook_detach_source(chan, mixmonitor_spy_type);
00522    }
00523 
00524    return CLI_SUCCESS;
00525 }

static void launch_monitor_thread ( struct ast_channel chan,
const char *  filename,
unsigned int  flags,
int  readvol,
int  writevol,
const char *  post_process 
) [static]

Definition at line 325 of file app_mixmonitor.c.

References ast_audiohook_destroy(), ast_audiohook_init(), AST_AUDIOHOOK_TRIGGER_SYNC, AST_AUDIOHOOK_TYPE_SPY, ast_calloc, ast_log(), ast_pthread_create_detached_background, ast_set_flag, ast_strdupa, ast_strlen_zero(), mixmonitor::audiohook, mixmonitor::filename, mixmonitor::flags, len(), LOG_WARNING, mixmonitor_free(), mixmonitor_thread(), mixmonitor::name, ast_channel::name, ast_audiohook::options, pbx_substitute_variables_helper(), mixmonitor::post_process, ast_audiohook_options::read_volume, setup_mixmonitor_ds(), startmon(), thread, and ast_audiohook_options::write_volume.

Referenced by mixmonitor_exec().

00327 {
00328    pthread_t thread;
00329    struct mixmonitor *mixmonitor;
00330    char postprocess2[1024] = "";
00331    size_t len;
00332 
00333    len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2;
00334 
00335    postprocess2[0] = 0;
00336    /* If a post process system command is given attach it to the structure */
00337    if (!ast_strlen_zero(post_process)) {
00338       char *p1, *p2;
00339 
00340       p1 = ast_strdupa(post_process);
00341       for (p2 = p1; *p2 ; p2++) {
00342          if (*p2 == '^' && *(p2+1) == '{') {
00343             *p2 = '$';
00344          }
00345       }
00346       pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
00347       if (!ast_strlen_zero(postprocess2))
00348          len += strlen(postprocess2) + 1;
00349    }
00350 
00351    /* Pre-allocate mixmonitor structure and spy */
00352    if (!(mixmonitor = ast_calloc(1, len))) {
00353       return;
00354    }
00355 
00356    /* Copy over flags and channel name */
00357    mixmonitor->flags = flags;
00358    if (setup_mixmonitor_ds(mixmonitor, chan)) {
00359       mixmonitor_free(mixmonitor);
00360       return;
00361    }
00362    mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
00363    strcpy(mixmonitor->name, chan->name);
00364    if (!ast_strlen_zero(postprocess2)) {
00365       mixmonitor->post_process = mixmonitor->name + strlen(mixmonitor->name) + strlen(filename) + 2;
00366       strcpy(mixmonitor->post_process, postprocess2);
00367    }
00368 
00369    mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1;
00370    strcpy(mixmonitor->filename, filename);
00371 
00372    /* Setup the actual spy before creating our thread */
00373    if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
00374       mixmonitor_free(mixmonitor);
00375       return;
00376    }
00377 
00378    ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
00379 
00380    if (readvol)
00381       mixmonitor->audiohook.options.read_volume = readvol;
00382    if (writevol)
00383       mixmonitor->audiohook.options.write_volume = writevol;
00384 
00385    if (startmon(chan, &mixmonitor->audiohook)) {
00386       ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
00387          mixmonitor_spy_type, chan->name);
00388       ast_audiohook_destroy(&mixmonitor->audiohook);
00389       mixmonitor_free(mixmonitor);
00390       return;
00391    }
00392 
00393    ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
00394 }

static int load_module ( void   )  [static]

static void mixmonitor_ds_chan_fixup ( void *  data,
struct ast_channel old_chan,
struct ast_channel new_chan 
) [static]

Definition at line 168 of file app_mixmonitor.c.

References ast_mutex_lock(), ast_mutex_unlock(), mixmonitor_ds::chan, and mixmonitor_ds::lock.

00169 {
00170    struct mixmonitor_ds *mixmonitor_ds = data;
00171 
00172    ast_mutex_lock(&mixmonitor_ds->lock);
00173    mixmonitor_ds->chan = new_chan;
00174    ast_mutex_unlock(&mixmonitor_ds->lock);
00175 }

static void mixmonitor_ds_close_fs ( struct mixmonitor_ds mixmonitor_ds  )  [static]

Definition at line 145 of file app_mixmonitor.c.

References ast_closestream(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, mixmonitor_ds::fs, mixmonitor_ds::fs_quit, and mixmonitor_ds::lock.

Referenced by mixmonitor_thread(), and stop_mixmonitor_exec().

00146 {
00147    ast_mutex_lock(&mixmonitor_ds->lock);
00148    if (mixmonitor_ds->fs) {
00149       ast_closestream(mixmonitor_ds->fs);
00150       mixmonitor_ds->fs = NULL;
00151       mixmonitor_ds->fs_quit = 1;
00152       ast_verb(2, "MixMonitor close filestream\n");
00153    }
00154    ast_mutex_unlock(&mixmonitor_ds->lock);
00155 }

static void mixmonitor_ds_destroy ( void *  data  )  [static]

Definition at line 157 of file app_mixmonitor.c.

References ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), mixmonitor_ds::chan, mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, and mixmonitor_ds::lock.

00158 {
00159    struct mixmonitor_ds *mixmonitor_ds = data;
00160 
00161    ast_mutex_lock(&mixmonitor_ds->lock);
00162    mixmonitor_ds->chan = NULL;
00163    mixmonitor_ds->destruction_ok = 1;
00164    ast_cond_signal(&mixmonitor_ds->destruction_condition);
00165    ast_mutex_unlock(&mixmonitor_ds->lock);
00166 }

static int mixmonitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 396 of file app_mixmonitor.c.

References AST_APP_ARG, ast_app_parse_options(), ast_config_AST_MONITOR_DIR, AST_DECLARE_APP_ARGS, ast_log(), ast_mkdir(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_flags::flags, get_volfactor, launch_monitor_thread(), LOG_NOTICE, LOG_WARNING, mixmonitor_opts, MUXFLAG_READVOLUME, MUXFLAG_VOLUME, MUXFLAG_WRITEVOLUME, OPT_ARG_ARRAY_SIZE, OPT_ARG_READVOLUME, OPT_ARG_VOLUME, OPT_ARG_WRITEVOLUME, parse(), and pbx_builtin_setvar_helper().

Referenced by handle_cli_mixmonitor(), and load_module().

00397 {
00398    int x, readvol = 0, writevol = 0;
00399    struct ast_flags flags = {0};
00400    char *parse, *tmp, *slash;
00401    AST_DECLARE_APP_ARGS(args,
00402       AST_APP_ARG(filename);
00403       AST_APP_ARG(options);
00404       AST_APP_ARG(post_process);
00405    );
00406    
00407    if (ast_strlen_zero(data)) {
00408       ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
00409       return -1;
00410    }
00411 
00412    parse = ast_strdupa(data);
00413 
00414    AST_STANDARD_APP_ARGS(args, parse);
00415    
00416    if (ast_strlen_zero(args.filename)) {
00417       ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
00418       return -1;
00419    }
00420 
00421    if (args.options) {
00422       char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
00423 
00424       ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options);
00425 
00426       if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
00427          if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
00428             ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
00429          } else if ((sscanf(opts[OPT_ARG_READVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
00430             ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
00431          } else {
00432             readvol = get_volfactor(x);
00433          }
00434       }
00435       
00436       if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
00437          if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
00438             ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
00439          } else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
00440             ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
00441          } else {
00442             writevol = get_volfactor(x);
00443          }
00444       }
00445       
00446       if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
00447          if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
00448             ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
00449          } else if ((sscanf(opts[OPT_ARG_VOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
00450             ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
00451          } else {
00452             readvol = writevol = get_volfactor(x);
00453          }
00454       }
00455    }
00456 
00457    /* if not provided an absolute path, use the system-configured monitoring directory */
00458    if (args.filename[0] != '/') {
00459       char *build;
00460 
00461       build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(args.filename) + 3);
00462       sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, args.filename);
00463       args.filename = build;
00464    }
00465 
00466    tmp = ast_strdupa(args.filename);
00467    if ((slash = strrchr(tmp, '/')))
00468       *slash = '\0';
00469    ast_mkdir(tmp, 0777);
00470 
00471    pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
00472    launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
00473 
00474    return 0;
00475 }

static void mixmonitor_free ( struct mixmonitor mixmonitor  )  [static]

Definition at line 201 of file app_mixmonitor.c.

References ast_cond_destroy(), ast_free, ast_mutex_destroy(), mixmonitor_ds::destruction_condition, mixmonitor_ds::lock, and mixmonitor::mixmonitor_ds.

Referenced by launch_monitor_thread(), and mixmonitor_thread().

00202 {
00203    if (mixmonitor) {
00204       if (mixmonitor->mixmonitor_ds) {
00205          ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
00206          ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
00207          ast_free(mixmonitor->mixmonitor_ds);
00208       }
00209       ast_free(mixmonitor);
00210    }
00211 }

static void* mixmonitor_thread ( void *  obj  )  [static]

Definition at line 213 of file app_mixmonitor.c.

References ast_audiohook_destroy(), ast_audiohook_detach(), AST_AUDIOHOOK_DIRECTION_BOTH, ast_audiohook_lock, ast_audiohook_read_frame(), AST_AUDIOHOOK_STATUS_RUNNING, ast_audiohook_trigger_wait(), ast_audiohook_unlock, ast_bridged_channel(), ast_cond_wait(), AST_FORMAT_SLINEAR, ast_frame_free(), AST_LIST_NEXT, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_safe_system(), ast_test_flag, ast_verb, ast_writefile(), ast_writestream(), mixmonitor::audiohook, mixmonitor_ds::chan, mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, ext, mixmonitor::filename, ast_frame::frame_list, mixmonitor_ds::fs, mixmonitor_ds::fs_quit, mixmonitor_ds::lock, LOG_ERROR, mixmonitor::mixmonitor_ds, mixmonitor_ds_close_fs(), mixmonitor_free(), MUXFLAG_APPEND, MUXFLAG_BRIDGED, mixmonitor::name, mixmonitor::post_process, SAMPLES_PER_FRAME, and ast_audiohook::status.

Referenced by launch_monitor_thread().

00214 {
00215    struct mixmonitor *mixmonitor = obj;
00216    struct ast_filestream **fs = NULL;
00217    unsigned int oflags;
00218    char *ext;
00219    int errflag = 0;
00220 
00221    ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
00222 
00223    ast_audiohook_lock(&mixmonitor->audiohook);
00224 
00225    fs = &mixmonitor->mixmonitor_ds->fs;
00226 
00227    while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
00228       struct ast_frame *fr = NULL;
00229 
00230       ast_audiohook_trigger_wait(&mixmonitor->audiohook);
00231 
00232       if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING)
00233          break;
00234 
00235       if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR)))
00236          continue;
00237 
00238       ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
00239       if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) {
00240          /* Initialize the file if not already done so */
00241          if (!*fs && !errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
00242             oflags = O_CREAT | O_WRONLY;
00243             oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
00244 
00245             if ((ext = strrchr(mixmonitor->filename, '.')))
00246                *(ext++) = '\0';
00247             else
00248                ext = "raw";
00249 
00250             if (!(*fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0666))) {
00251                ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
00252                errflag = 1;
00253             }
00254          }
00255 
00256          /* Write out the frame(s) */
00257          if (*fs) {
00258             struct ast_frame *cur;
00259 
00260             for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
00261                ast_writestream(*fs, cur);
00262             }
00263          }
00264       }
00265       ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
00266 
00267       /* All done! free it. */
00268       ast_frame_free(fr, 0);
00269    }
00270 
00271    ast_audiohook_detach(&mixmonitor->audiohook);
00272    ast_audiohook_unlock(&mixmonitor->audiohook);
00273    ast_audiohook_destroy(&mixmonitor->audiohook);
00274 
00275 
00276    mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds);
00277 
00278    if (mixmonitor->post_process) {
00279       ast_verb(2, "Executing [%s]\n", mixmonitor->post_process);
00280       ast_safe_system(mixmonitor->post_process);
00281    }
00282 
00283    ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
00284    if (!mixmonitor->mixmonitor_ds->destruction_ok) {
00285       ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock);
00286    }
00287    ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
00288 
00289    ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
00290    mixmonitor_free(mixmonitor);
00291    return NULL;
00292 }

static int setup_mixmonitor_ds ( struct mixmonitor mixmonitor,
struct ast_channel chan 
) [static]

Definition at line 294 of file app_mixmonitor.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_cond_destroy(), ast_cond_init(), ast_datastore_alloc, ast_free, ast_mutex_destroy(), ast_mutex_init(), mixmonitor_ds::chan, ast_datastore::data, mixmonitor_ds::destruction_condition, mixmonitor_ds::lock, and mixmonitor::mixmonitor_ds.

Referenced by launch_monitor_thread().

00295 {
00296    struct ast_datastore *datastore = NULL;
00297    struct mixmonitor_ds *mixmonitor_ds;
00298 
00299    if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
00300       return -1;
00301    }
00302 
00303    ast_mutex_init(&mixmonitor_ds->lock);
00304    ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
00305 
00306    if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, NULL))) {
00307       ast_mutex_destroy(&mixmonitor_ds->lock);
00308       ast_cond_destroy(&mixmonitor_ds->destruction_condition);
00309       ast_free(mixmonitor_ds);
00310       return -1;
00311    }
00312 
00313    /* No need to lock mixmonitor_ds since this is still operating in the channel's thread */
00314    mixmonitor_ds->chan = chan;
00315    datastore->data = mixmonitor_ds;
00316 
00317    ast_channel_lock(chan);
00318    ast_channel_datastore_add(chan, datastore);
00319    ast_channel_unlock(chan);
00320 
00321    mixmonitor->mixmonitor_ds = mixmonitor_ds;
00322    return 0;
00323 }

static int startmon ( struct ast_channel chan,
struct ast_audiohook audiohook 
) [static]

Definition at line 183 of file app_mixmonitor.c.

References ast_audiohook_attach(), ast_bridged_channel(), AST_FLAG_NBRIDGE, ast_softhangup(), AST_SOFTHANGUP_UNBRIDGE, and ast_test_flag.

Referenced by launch_monitor_thread().

00184 {
00185    struct ast_channel *peer = NULL;
00186    int res = 0;
00187 
00188    if (!chan)
00189       return -1;
00190 
00191    ast_audiohook_attach(chan, audiohook);
00192 
00193    if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
00194       ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);  
00195 
00196    return res;
00197 }

static int stop_mixmonitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 477 of file app_mixmonitor.c.

References ast_audiohook_detach_source(), ast_channel_datastore_find(), ast_datastore::data, and mixmonitor_ds_close_fs().

Referenced by load_module().

00478 {
00479    struct ast_datastore *datastore = NULL;
00480 
00481    /* closing the filestream here guarantees the file is avaliable to the dialplan
00482     * after calling StopMixMonitor */
00483    if ((datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, NULL))) {
00484       mixmonitor_ds_close_fs(datastore->data);
00485    }
00486 
00487    ast_audiohook_detach_source(chan, mixmonitor_spy_type);
00488    return 0;
00489 }

static int unload_module ( void   )  [static]

Definition at line 531 of file app_mixmonitor.c.

References ast_cli_unregister_multiple(), and ast_unregister_application().

00532 {
00533    int res;
00534 
00535    ast_cli_unregister_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
00536    res = ast_unregister_application(stop_app);
00537    res |= ast_unregister_application(app);
00538    
00539    return res;
00540 }


Variable Documentation

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

Definition at line 553 of file app_mixmonitor.c.

const char* app = "MixMonitor" [static]

Definition at line 51 of file app_mixmonitor.c.

Definition at line 553 of file app_mixmonitor.c.

struct ast_cli_entry cli_mixmonitor[] [static]

Initial value:

 {
   AST_CLI_DEFINE(handle_cli_mixmonitor, "Execute a MixMonitor command")
}

Definition at line 527 of file app_mixmonitor.c.

const char* desc [static]

Definition at line 53 of file app_mixmonitor.c.

struct module_symbols* me

enum { ... } mixmonitor_args

Initial value:

 {
   .type = "mixmonitor",
   .destroy = mixmonitor_ds_destroy,
   .chan_fixup = mixmonitor_ds_chan_fixup,
}

Definition at line 177 of file app_mixmonitor.c.

enum { ... } mixmonitor_flags

struct ast_app_option mixmonitor_opts[128] = { [ 'a' ] = { .flag = MUXFLAG_APPEND }, [ 'b' ] = { .flag = MUXFLAG_BRIDGED }, [ 'v' ] = { .flag = MUXFLAG_READVOLUME , .arg_index = OPT_ARG_READVOLUME + 1 }, [ 'V' ] = { .flag = MUXFLAG_WRITEVOLUME , .arg_index = OPT_ARG_WRITEVOLUME + 1 }, [ 'W' ] = { .flag = MUXFLAG_VOLUME , .arg_index = OPT_ARG_VOLUME + 1 },} [static]

Definition at line 120 of file app_mixmonitor.c.

Referenced by mixmonitor_exec().

const char* mixmonitor_spy_type = "MixMonitor" [static]

Definition at line 88 of file app_mixmonitor.c.

Referenced by builtin_automixmonitor().

const char* stop_app = "StopMixMonitor" [static]

Definition at line 79 of file app_mixmonitor.c.

const char* stop_desc [static]

Initial value:

 ""
"  StopMixMonitor():\n"
"Stop recording a call through MixMonitor, and free the recording's file handle.\n"
""

Definition at line 81 of file app_mixmonitor.c.

const char* stop_synopsis = "Stop recording a call through MixMonitor" [static]

Definition at line 80 of file app_mixmonitor.c.

const char* synopsis = "Record a call and mix the audio during the recording" [static]

Definition at line 52 of file app_mixmonitor.c.


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