#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"
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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, } |
static const char * | app = "MixMonitor" |
static const struct ast_module_info * | ast_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" |
Kevin P. Fleming <kpfleming@digium.com>
Definition in file app_mixmonitor.c.
#define get_volfactor | ( | x | ) | x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0 |
#define SAMPLES_PER_FRAME 160 |
anonymous enum |
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 |
Definition at line 107 of file app_mixmonitor.c.
00107 { 00108 OPT_ARG_READVOLUME = 0, 00109 OPT_ARG_WRITEVOLUME, 00110 OPT_ARG_VOLUME, 00111 OPT_ARG_ARRAY_SIZE, 00112 } mixmonitor_args;
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_free, ast_log(), ast_pthread_create_detached_background, ast_set_flag, ast_strdupa, ast_strlen_zero(), chan, mixmonitor::flags, len(), LOG_WARNING, mixmonitor_free(), mixmonitor_thread(), mixmonitor::name, ast_channel::name, pbx_substitute_variables_helper(), setup_mixmonitor_ds(), startmon(), and thread.
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 ast_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 ast_free(mixmonitor); 00390 return; 00391 } 00392 00393 ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor); 00394 }
static int load_module | ( | void | ) | [static] |
Definition at line 542 of file app_mixmonitor.c.
References ast_cli_register_multiple(), ast_register_application, cli_mixmonitor, mixmonitor_exec(), and stop_mixmonitor_exec().
00543 { 00544 int res; 00545 00546 ast_cli_register_multiple(cli_mixmonitor, sizeof(cli_mixmonitor) / sizeof(struct ast_cli_entry)); 00547 res = ast_register_application(app, mixmonitor_exec, synopsis, desc); 00548 res |= ast_register_application(stop_app, stop_mixmonitor_exec, stop_synopsis, stop_desc); 00549 00550 return res; 00551 }
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, chan, 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], "%d", &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], "%d", &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], "%d", &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, 0644))) { 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 00272 ast_audiohook_detach(&mixmonitor->audiohook); 00273 ast_audiohook_unlock(&mixmonitor->audiohook); 00274 ast_audiohook_destroy(&mixmonitor->audiohook); 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_datastore_alloc(), ast_channel_lock, ast_channel_unlock, ast_cond_destroy(), ast_cond_init(), ast_free, ast_mutex_destroy(), ast_mutex_init(), chan, ast_datastore::data, mixmonitor::mixmonitor_ds, and mixmonitor_ds_info.
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_channel_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, ast_test_flag, and chan.
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(), chan, ast_datastore::data, mixmonitor_ds_close_fs(), and mixmonitor_ds_info.
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(), ast_unregister_application(), and cli_mixmonitor.
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 }
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 = "068e67f60f50dd9ee86464c05884a49d" , .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.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 553 of file app_mixmonitor.c.
struct ast_cli_entry cli_mixmonitor[] [static] |
Initial value:
{ { .handler = handle_cli_mixmonitor , .summary = "Execute a MixMonitor command" ,__VA_ARGS__ } }
Definition at line 527 of file app_mixmonitor.c.
Referenced by load_module(), and unload_module().
const char* desc [static] |
Definition at line 53 of file app_mixmonitor.c.
struct module_symbols* me |
Definition at line 86 of file app_mixmonitor.c.
Referenced by _sip_tcp_helper_thread(), handle_mgcp_audit_endpoint(), and handle_mgcp_show_endpoints().
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 177 of file app_mixmonitor.c.
Referenced by setup_mixmonitor_ds(), and stop_mixmonitor_exec().
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] |
const char* mixmonitor_spy_type = "MixMonitor" [static] |
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.