Thu May 14 14:49:17 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/audiohook.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/lock.h"
#include "asterisk/cli.h"
#include "asterisk/options.h"
#include "asterisk/app.h"
#include "asterisk/linkedlists.h"
#include "asterisk/utils.h"

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 * complete_mixmonitor_cli (const char *line, const char *word, int pos, int state)
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 int mixmonitor_cli (int fd, int argc, char **argv)
static void mixmonitor_ds_chan_fixup (void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
static void mixmonitor_ds_destroy (void *data)
static int mixmonitor_exec (struct ast_channel *chan, void *data)
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 | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, }
static const char * app = "MixMonitor"
static const struct ast_module_infoast_module_info = &__mod_info
static struct ast_cli_entry cli_mixmonitor []
static const char * desc
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 58 of file app_mixmonitor.c.

Referenced by mixmonitor_exec().

#define SAMPLES_PER_FRAME   160

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

00104      {
00105    MUXFLAG_APPEND = (1 << 1),
00106    MUXFLAG_BRIDGED = (1 << 2),
00107    MUXFLAG_VOLUME = (1 << 3),
00108    MUXFLAG_READVOLUME = (1 << 4),
00109    MUXFLAG_WRITEVOLUME = (1 << 5),
00110 } mixmonitor_flags;

anonymous enum

Enumerator:
OPT_ARG_READVOLUME 
OPT_ARG_WRITEVOLUME 
OPT_ARG_VOLUME 
OPT_ARG_ARRAY_SIZE 

Definition at line 112 of file app_mixmonitor.c.


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 531 of file app_mixmonitor.c.

static void __unreg_module ( void   )  [static]

Definition at line 531 of file app_mixmonitor.c.

static char* complete_mixmonitor_cli ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 493 of file app_mixmonitor.c.

References ast_complete_channels().

00494 {
00495    return ast_complete_channels(line, word, pos, state, 2);
00496 }

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 301 of file app_mixmonitor.c.

References ast_audiohook_destroy(), ast_audiohook_init(), AST_AUDIOHOOK_TRIGGER_SYNC, AST_AUDIOHOOK_TYPE_SPY, ast_log(), ast_pthread_create_background, ast_set_flag, ast_strdupa, ast_strlen_zero(), calloc, mixmonitor::flags, free, len(), LOG_WARNING, mixmonitor_thread(), mixmonitor::name, ast_channel::name, pbx_substitute_variables_helper(), setup_mixmonitor_ds(), startmon(), and thread.

Referenced by mixmonitor_exec().

00303 {
00304    pthread_attr_t attr;
00305    pthread_t thread;
00306    struct mixmonitor *mixmonitor;
00307    char postprocess2[1024] = "";
00308    size_t len;
00309 
00310    len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2;
00311 
00312    /* If a post process system command is given attach it to the structure */
00313    if (!ast_strlen_zero(post_process)) {
00314       char *p1, *p2;
00315 
00316       p1 = ast_strdupa(post_process);
00317       for (p2 = p1; *p2 ; p2++) {
00318          if (*p2 == '^' && *(p2+1) == '{') {
00319             *p2 = '$';
00320          }
00321       }
00322 
00323       pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
00324       if (!ast_strlen_zero(postprocess2))
00325          len += strlen(postprocess2) + 1;
00326    }
00327 
00328    /* Pre-allocate mixmonitor structure and spy */
00329    if (!(mixmonitor = calloc(1, len))) {
00330       return;
00331    }
00332 
00333    /* Copy over flags and channel name */
00334    mixmonitor->flags = flags;
00335    if (setup_mixmonitor_ds(mixmonitor, chan)) {
00336       return;
00337    }
00338    mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor);
00339    strcpy(mixmonitor->name, chan->name);
00340    if (!ast_strlen_zero(postprocess2)) {
00341       mixmonitor->post_process = mixmonitor->name + strlen(mixmonitor->name) + strlen(filename) + 2;
00342       strcpy(mixmonitor->post_process, postprocess2);
00343    }
00344 
00345    mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1;
00346    strcpy(mixmonitor->filename, filename);
00347 
00348    /* Setup the actual spy before creating our thread */
00349    if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) {
00350       free(mixmonitor);
00351       return;
00352    }
00353    
00354    ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
00355    
00356    if (readvol)
00357       mixmonitor->audiohook.options.read_volume = readvol;
00358    if (writevol)
00359       mixmonitor->audiohook.options.write_volume = writevol;
00360 
00361    if (startmon(chan, &mixmonitor->audiohook)) {
00362       ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
00363          mixmonitor_spy_type, chan->name);
00364       /* Since we couldn't add ourselves - bail out! */
00365       ast_audiohook_destroy(&mixmonitor->audiohook);
00366       free(mixmonitor);
00367       return;
00368    }
00369 
00370    pthread_attr_init(&attr);
00371    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
00372    ast_pthread_create_background(&thread, &attr, mixmonitor_thread, mixmonitor);
00373    pthread_attr_destroy(&attr);
00374 }

static int load_module ( void   )  [static]

Definition at line 520 of file app_mixmonitor.c.

References ast_cli_register_multiple(), ast_register_application(), cli_mixmonitor, mixmonitor_exec(), and stop_mixmonitor_exec().

00521 {
00522    int res;
00523 
00524    ast_cli_register_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
00525    res = ast_register_application(app, mixmonitor_exec, synopsis, desc);
00526    res |= ast_register_application(stop_app, stop_mixmonitor_exec, stop_synopsis, stop_desc);
00527 
00528    return res;
00529 }

static int mixmonitor_cli ( int  fd,
int  argc,
char **  argv 
) [static]

Definition at line 471 of file app_mixmonitor.c.

References ast_audiohook_detach_source(), ast_channel_unlock, ast_cli(), ast_get_channel_by_name_prefix_locked(), mixmonitor_exec(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00472 {
00473    struct ast_channel *chan;
00474 
00475    if (argc < 3)
00476       return RESULT_SHOWUSAGE;
00477 
00478    if (!(chan = ast_get_channel_by_name_prefix_locked(argv[2], strlen(argv[2])))) {
00479       ast_cli(fd, "No channel matching '%s' found.\n", argv[2]);
00480       return RESULT_SUCCESS;
00481    }
00482 
00483    if (!strcasecmp(argv[1], "start"))
00484       mixmonitor_exec(chan, argv[3]);
00485    else if (!strcasecmp(argv[1], "stop"))
00486       ast_audiohook_detach_source(chan, mixmonitor_spy_type);
00487 
00488    ast_channel_unlock(chan);
00489 
00490    return RESULT_SUCCESS;
00491 }

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

Definition at line 156 of file app_mixmonitor.c.

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

00157 {
00158    struct mixmonitor_ds *mixmonitor_ds = data;
00159 
00160    ast_mutex_lock(&mixmonitor_ds->lock);
00161    mixmonitor_ds->chan = new_chan;
00162    ast_mutex_unlock(&mixmonitor_ds->lock);
00163 }

static void mixmonitor_ds_destroy ( void *  data  )  [static]

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

00146 {
00147    struct mixmonitor_ds *mixmonitor_ds = data;
00148 
00149    ast_mutex_lock(&mixmonitor_ds->lock);
00150    mixmonitor_ds->chan = NULL;
00151    mixmonitor_ds->destruction_ok = 1;
00152    ast_cond_signal(&mixmonitor_ds->destruction_condition);
00153    ast_mutex_unlock(&mixmonitor_ds->lock);
00154 }

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

Definition at line 376 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_module_user_add, ast_module_user_remove, 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 load_module(), and mixmonitor_cli().

00377 {
00378    int x, readvol = 0, writevol = 0;
00379    struct ast_module_user *u;
00380    struct ast_flags flags = {0};
00381    char *parse;
00382    AST_DECLARE_APP_ARGS(args,
00383       AST_APP_ARG(filename);
00384       AST_APP_ARG(options);
00385       AST_APP_ARG(post_process);
00386    );
00387    
00388    if (ast_strlen_zero(data)) {
00389       ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
00390       return -1;
00391    }
00392 
00393    u = ast_module_user_add(chan);
00394 
00395    parse = ast_strdupa(data);
00396 
00397    AST_STANDARD_APP_ARGS(args, parse);
00398    
00399    if (ast_strlen_zero(args.filename)) {
00400       ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
00401       ast_module_user_remove(u);
00402       return -1;
00403    }
00404 
00405    if (args.options) {
00406       char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
00407 
00408       ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options);
00409 
00410       if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
00411          if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
00412             ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
00413          } else if ((sscanf(opts[OPT_ARG_READVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
00414             ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
00415          } else {
00416             readvol = get_volfactor(x);
00417          }
00418       }
00419       
00420       if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
00421          if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
00422             ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
00423          } else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
00424             ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
00425          } else {
00426             writevol = get_volfactor(x);
00427          }
00428       }
00429       
00430       if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
00431          if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
00432             ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
00433          } else if ((sscanf(opts[OPT_ARG_VOLUME], "%d", &x) != 1) || (x < -4) || (x > 4)) {
00434             ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
00435          } else {
00436             readvol = writevol = get_volfactor(x);
00437          }
00438       }
00439    }
00440 
00441    /* if not provided an absolute path, use the system-configured monitoring directory */
00442    if (args.filename[0] != '/') {
00443       char *build;
00444 
00445       build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(args.filename) + 3);
00446       sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, args.filename);
00447       args.filename = build;
00448    }
00449 
00450    pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
00451    launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process);
00452 
00453    ast_module_user_remove(u);
00454 
00455    return 0;
00456 }

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

Definition at line 189 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_closestream(), ast_cond_destroy(), ast_cond_wait(), AST_FORMAT_SLINEAR, ast_frame_free(), ast_free, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_safe_system(), ast_test_flag, ast_verbose(), ast_writefile(), ast_writestream(), mixmonitor::audiohook, mixmonitor_ds::chan, mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, ext, mixmonitor::filename, free, mixmonitor_ds::lock, LOG_ERROR, mixmonitor::mixmonitor_ds, MUXFLAG_APPEND, MUXFLAG_BRIDGED, mixmonitor::name, option_verbose, mixmonitor::post_process, SAMPLES_PER_FRAME, ast_audiohook::status, and VERBOSE_PREFIX_2.

Referenced by launch_monitor_thread().

00190 {
00191    struct mixmonitor *mixmonitor = obj;
00192    struct ast_filestream *fs = NULL;
00193    unsigned int oflags;
00194    char *ext;
00195    int errflag = 0;
00196 
00197    if (option_verbose > 1)
00198       ast_verbose(VERBOSE_PREFIX_2 "Begin MixMonitor Recording %s\n", mixmonitor->name);
00199    
00200    ast_audiohook_lock(&mixmonitor->audiohook);
00201 
00202    while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING) {
00203       struct ast_frame *fr = NULL;
00204       
00205       ast_audiohook_trigger_wait(&mixmonitor->audiohook);
00206       
00207       if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING)
00208          break;
00209       
00210       if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR)))
00211          continue;
00212 
00213       ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
00214       if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) {
00215          ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
00216          /* Initialize the file if not already done so */
00217          if (!fs && !errflag) {
00218             oflags = O_CREAT | O_WRONLY;
00219             oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
00220             
00221             if ((ext = strrchr(mixmonitor->filename, '.')))
00222                *(ext++) = '\0';
00223             else
00224                ext = "raw";
00225             
00226             if (!(fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0644))) {
00227                ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext);
00228                errflag = 1;
00229             }
00230          }
00231 
00232          /* Write out the frame */
00233          if (fs)
00234             ast_writestream(fs, fr);
00235       } else {
00236          ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
00237       }
00238 
00239       /* All done! free it. */
00240       ast_frame_free(fr, 0);
00241    }
00242 
00243    ast_audiohook_detach(&mixmonitor->audiohook);
00244    ast_audiohook_unlock(&mixmonitor->audiohook);
00245    ast_audiohook_destroy(&mixmonitor->audiohook);
00246    
00247    if (option_verbose > 1)
00248       ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name);
00249 
00250    if (fs)
00251       ast_closestream(fs);
00252 
00253    if (mixmonitor->post_process) {
00254       if (option_verbose > 2)
00255          ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process);
00256       ast_safe_system(mixmonitor->post_process);
00257    }
00258 
00259    ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
00260    if (!mixmonitor->mixmonitor_ds->destruction_ok) {
00261       ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock);
00262    }
00263    ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
00264    ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
00265    ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition);
00266    ast_free(mixmonitor->mixmonitor_ds);
00267    free(mixmonitor);
00268 
00269    return NULL;
00270 }

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

Definition at line 272 of file app_mixmonitor.c.

References ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_alloc(), ast_channel_lock, ast_channel_unlock, ast_cond_init(), ast_free, ast_mutex_init(), mixmonitor_ds::chan, ast_datastore::data, mixmonitor::mixmonitor_ds, and mixmonitor_ds_info.

Referenced by launch_monitor_thread().

00273 {
00274    struct ast_datastore *datastore = NULL;
00275    struct mixmonitor_ds *mixmonitor_ds;
00276 
00277    if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
00278       return -1;
00279    }
00280    
00281    ast_mutex_init(&mixmonitor_ds->lock);
00282    ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
00283 
00284    if (!(datastore = ast_channel_datastore_alloc(&mixmonitor_ds_info, NULL))) {
00285       ast_free(mixmonitor_ds);
00286       return -1;
00287    }
00288 
00289    /* No need to lock mixmonitor_ds since this is still operating in the channel's thread */
00290    mixmonitor_ds->chan = chan;
00291    datastore->data = mixmonitor_ds;
00292 
00293    ast_channel_lock(chan);
00294    ast_channel_datastore_add(chan, datastore);
00295    ast_channel_unlock(chan);
00296 
00297    mixmonitor->mixmonitor_ds = mixmonitor_ds;
00298    return 0;
00299 }

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

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

00172 {
00173    struct ast_channel *peer;
00174    int res;
00175 
00176    if (!chan)
00177       return -1;
00178 
00179    res = ast_audiohook_attach(chan, audiohook);
00180 
00181    if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan)))
00182       ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);  
00183 
00184    return res;
00185 }

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

Definition at line 458 of file app_mixmonitor.c.

References ast_audiohook_detach_source(), ast_module_user_add, ast_module_user_remove, and ast_module_user::chan.

Referenced by load_module().

00459 {
00460    struct ast_module_user *u;
00461 
00462    u = ast_module_user_add(chan);
00463 
00464    ast_audiohook_detach_source(chan, mixmonitor_spy_type);
00465 
00466    ast_module_user_remove(u);
00467 
00468    return 0;
00469 }

static int unload_module ( void   )  [static]

Definition at line 507 of file app_mixmonitor.c.

References ast_cli_unregister_multiple(), ast_module_user_hangup_all, ast_unregister_application(), and cli_mixmonitor.

00508 {
00509    int res;
00510 
00511    ast_cli_unregister_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry));
00512    res = ast_unregister_application(stop_app);
00513    res |= ast_unregister_application(app);
00514    
00515    ast_module_user_hangup_all();
00516 
00517    return res;
00518 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static]

Definition at line 531 of file app_mixmonitor.c.

const char* app = "MixMonitor" [static]

Definition at line 60 of file app_mixmonitor.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 531 of file app_mixmonitor.c.

struct ast_cli_entry cli_mixmonitor[] [static]

Definition at line 498 of file app_mixmonitor.c.

Referenced by load_module(), and unload_module().

const char* desc [static]

Definition at line 62 of file app_mixmonitor.c.

struct module_symbols* me

Definition at line 91 of file app_mixmonitor.c.

enum { ... } mixmonitor_args

struct ast_datastore_info mixmonitor_ds_info [static]

Initial value:

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

Definition at line 165 of file app_mixmonitor.c.

Referenced by setup_mixmonitor_ds().

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 125 of file app_mixmonitor.c.

Referenced by mixmonitor_exec().

const char* mixmonitor_spy_type = "MixMonitor" [static]

Definition at line 93 of file app_mixmonitor.c.

const char* stop_app = "StopMixMonitor" [static]

Definition at line 83 of file app_mixmonitor.c.

const char* stop_desc [static]

Initial value:

 ""
"  StopMixMonitor()\n\n"
"Stops the audio recording that was started with a call to MixMonitor()\n"
"on the current channel.\n"
""

Definition at line 85 of file app_mixmonitor.c.

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

Definition at line 84 of file app_mixmonitor.c.

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

Definition at line 61 of file app_mixmonitor.c.


Generated on Thu May 14 14:49:17 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7