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"
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 void | destroy_monitor_audiohook (struct mixmonitor *mixmonitor) |
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 __MODULE_INFO_SECTION | __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mixed Audio Monitoring Application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } |
static const char * | app = "MixMonitor" |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_cli_entry | cli_mixmonitor [] |
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" |
MixMonitor() - Record a call and mix the audio during the recording.
Definition in file app_mixmonitor.c.
#define get_volfactor | ( | x | ) | x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0 |
Definition at line 129 of file app_mixmonitor.c.
Referenced by mixmonitor_exec().
#define SAMPLES_PER_FRAME 160 |
Definition at line 266 of file app_mixmonitor.c.
Referenced by mixmonitor_thread().
anonymous enum |
Definition at line 148 of file app_mixmonitor.c.
{ MUXFLAG_APPEND = (1 << 1), MUXFLAG_BRIDGED = (1 << 2), MUXFLAG_VOLUME = (1 << 3), MUXFLAG_READVOLUME = (1 << 4), MUXFLAG_WRITEVOLUME = (1 << 5), } mixmonitor_flags;
anonymous enum |
Definition at line 156 of file app_mixmonitor.c.
static void __reg_module | ( | void | ) | [static] |
Definition at line 650 of file app_mixmonitor.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 650 of file app_mixmonitor.c.
static void destroy_monitor_audiohook | ( | struct mixmonitor * | mixmonitor | ) | [static] |
Definition at line 236 of file app_mixmonitor.c.
References ast_audiohook_destroy(), ast_audiohook_detach(), ast_audiohook_lock, ast_audiohook_unlock, ast_mutex_lock(), ast_mutex_unlock(), mixmonitor::audiohook, mixmonitor_ds::audiohook, mixmonitor_ds::lock, and mixmonitor::mixmonitor_ds.
Referenced by mixmonitor_thread().
{ if (mixmonitor->mixmonitor_ds) { ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); mixmonitor->mixmonitor_ds->audiohook = NULL; ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); } /* kill the audiohook.*/ ast_audiohook_lock(&mixmonitor->audiohook); ast_audiohook_detach(&mixmonitor->audiohook); ast_audiohook_unlock(&mixmonitor->audiohook); ast_audiohook_destroy(&mixmonitor->audiohook); }
static char* handle_cli_mixmonitor | ( | struct ast_cli_entry * | e, |
int | cmd, | ||
struct ast_cli_args * | a | ||
) | [static] |
Definition at line 588 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.
{ struct ast_channel *chan; switch (cmd) { case CLI_INIT: e->command = "mixmonitor {start|stop}"; e->usage = "Usage: mixmonitor <start|stop> <chan_name> [args]\n" " The optional arguments are passed to the MixMonitor\n" " application when the 'start' command is used.\n"; return NULL; case CLI_GENERATE: return ast_complete_channels(a->line, a->word, a->pos, a->n, 2); } if (a->argc < 3) return CLI_SHOWUSAGE; if (!(chan = ast_get_channel_by_name_prefix_locked(a->argv[2], strlen(a->argv[2])))) { ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]); /* Technically this is a failure, but we don't want 2 errors printing out */ return CLI_SUCCESS; } if (!strcasecmp(a->argv[1], "start")) { mixmonitor_exec(chan, a->argv[3]); ast_channel_unlock(chan); } else { ast_channel_unlock(chan); ast_audiohook_detach_source(chan, mixmonitor_spy_type); } return CLI_SUCCESS; }
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 399 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().
{ pthread_t thread; struct mixmonitor *mixmonitor; char postprocess2[1024] = ""; size_t len; len = sizeof(*mixmonitor) + strlen(chan->name) + strlen(filename) + 2; postprocess2[0] = 0; /* If a post process system command is given attach it to the structure */ if (!ast_strlen_zero(post_process)) { char *p1, *p2; p1 = ast_strdupa(post_process); for (p2 = p1; *p2 ; p2++) { if (*p2 == '^' && *(p2+1) == '{') { *p2 = '$'; } } pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1); if (!ast_strlen_zero(postprocess2)) len += strlen(postprocess2) + 1; } /* Pre-allocate mixmonitor structure and spy */ if (!(mixmonitor = ast_calloc(1, len))) { return; } /* Setup the actual spy before creating our thread */ if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type)) { mixmonitor_free(mixmonitor); return; } /* Copy over flags and channel name */ mixmonitor->flags = flags; if (setup_mixmonitor_ds(mixmonitor, chan)) { mixmonitor_free(mixmonitor); return; } mixmonitor->name = (char *) mixmonitor + sizeof(*mixmonitor); strcpy(mixmonitor->name, chan->name); if (!ast_strlen_zero(postprocess2)) { mixmonitor->post_process = mixmonitor->name + strlen(mixmonitor->name) + strlen(filename) + 2; strcpy(mixmonitor->post_process, postprocess2); } mixmonitor->filename = (char *) mixmonitor + sizeof(*mixmonitor) + strlen(chan->name) + 1; strcpy(mixmonitor->filename, filename); ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC); if (readvol) mixmonitor->audiohook.options.read_volume = readvol; if (writevol) mixmonitor->audiohook.options.write_volume = writevol; if (startmon(chan, &mixmonitor->audiohook)) { ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n", mixmonitor_spy_type, chan->name); ast_audiohook_destroy(&mixmonitor->audiohook); mixmonitor_free(mixmonitor); return; } ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor); }
static int load_module | ( | void | ) | [static] |
Definition at line 639 of file app_mixmonitor.c.
References ARRAY_LEN, ast_cli_register_multiple(), ast_register_application_xml, mixmonitor_exec(), and stop_mixmonitor_exec().
{ int res; ast_cli_register_multiple(cli_mixmonitor, ARRAY_LEN(cli_mixmonitor)); res = ast_register_application_xml(app, mixmonitor_exec); res |= ast_register_application_xml(stop_app, stop_mixmonitor_exec); return res; }
static void mixmonitor_ds_chan_fixup | ( | void * | data, |
struct ast_channel * | old_chan, | ||
struct ast_channel * | new_chan | ||
) | [static] |
Definition at line 221 of file app_mixmonitor.c.
References ast_mutex_lock(), ast_mutex_unlock(), mixmonitor_ds::chan, and mixmonitor_ds::lock.
{ struct mixmonitor_ds *mixmonitor_ds = data; ast_mutex_lock(&mixmonitor_ds->lock); mixmonitor_ds->chan = new_chan; ast_mutex_unlock(&mixmonitor_ds->lock); }
static void mixmonitor_ds_close_fs | ( | struct mixmonitor_ds * | mixmonitor_ds | ) | [static] |
Definition at line 199 of file app_mixmonitor.c.
References ast_closestream(), ast_verb, mixmonitor_ds::fs, and mixmonitor_ds::fs_quit.
Referenced by mixmonitor_thread(), and stop_mixmonitor_exec().
static void mixmonitor_ds_destroy | ( | void * | data | ) | [static] |
Definition at line 209 of file app_mixmonitor.c.
References ast_cond_signal(), ast_mutex_lock(), ast_mutex_unlock(), mixmonitor_ds::audiohook, mixmonitor_ds::chan, mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, and mixmonitor_ds::lock.
{ struct mixmonitor_ds *mixmonitor_ds = data; ast_mutex_lock(&mixmonitor_ds->lock); mixmonitor_ds->chan = NULL; mixmonitor_ds->audiohook = NULL; mixmonitor_ds->destruction_ok = 1; ast_cond_signal(&mixmonitor_ds->destruction_condition); ast_mutex_unlock(&mixmonitor_ds->lock); }
static int mixmonitor_exec | ( | struct ast_channel * | chan, |
void * | data | ||
) | [static] |
Definition at line 470 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().
{ int x, readvol = 0, writevol = 0; struct ast_flags flags = {0}; char *parse, *tmp, *slash; AST_DECLARE_APP_ARGS(args, AST_APP_ARG(filename); AST_APP_ARG(options); AST_APP_ARG(post_process); ); if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n"); return -1; } parse = ast_strdupa(data); AST_STANDARD_APP_ARGS(args, parse); if (ast_strlen_zero(args.filename)) { ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n"); return -1; } if (args.options) { char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, }; ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options); if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) { if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) { ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n"); } else if ((sscanf(opts[OPT_ARG_READVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) { ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]); } else { readvol = get_volfactor(x); } } if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) { if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) { ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n"); } else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) { ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]); } else { writevol = get_volfactor(x); } } if (ast_test_flag(&flags, MUXFLAG_VOLUME)) { if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) { ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n"); } else if ((sscanf(opts[OPT_ARG_VOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) { ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]); } else { readvol = writevol = get_volfactor(x); } } } /* if not provided an absolute path, use the system-configured monitoring directory */ if (args.filename[0] != '/') { char *build; build = alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(args.filename) + 3); sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, args.filename); args.filename = build; } tmp = ast_strdupa(args.filename); if ((slash = strrchr(tmp, '/'))) *slash = '\0'; ast_mkdir(tmp, 0777); pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename); launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process); return 0; }
static void mixmonitor_free | ( | struct mixmonitor * | mixmonitor | ) | [static] |
Definition at line 268 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().
{ if (mixmonitor) { if (mixmonitor->mixmonitor_ds) { ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor->mixmonitor_ds->destruction_condition); ast_free(mixmonitor->mixmonitor_ds); } ast_free(mixmonitor); } }
static void* mixmonitor_thread | ( | void * | obj | ) | [static] |
Definition at line 280 of file app_mixmonitor.c.
References 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, destroy_monitor_audiohook(), mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, ext, mixmonitor::filename, 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().
{ struct mixmonitor *mixmonitor = obj; struct ast_filestream **fs = NULL; unsigned int oflags; char *ext; int errflag = 0; ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name); fs = &mixmonitor->mixmonitor_ds->fs; /* The audiohook must enter and exit the loop locked */ ast_audiohook_lock(&mixmonitor->audiohook); while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) { struct ast_frame *fr = NULL; if (!(fr = ast_audiohook_read_frame(&mixmonitor->audiohook, SAMPLES_PER_FRAME, AST_AUDIOHOOK_DIRECTION_BOTH, AST_FORMAT_SLINEAR))) { ast_audiohook_trigger_wait(&mixmonitor->audiohook); if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) { break; } continue; } /* audiohook lock is not required for the next block. * Unlock it, but remember to lock it before looping or exiting */ ast_audiohook_unlock(&mixmonitor->audiohook); ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED) || (mixmonitor->mixmonitor_ds->chan && ast_bridged_channel(mixmonitor->mixmonitor_ds->chan))) { /* Initialize the file if not already done so */ if (!*fs && !errflag && !mixmonitor->mixmonitor_ds->fs_quit) { oflags = O_CREAT | O_WRONLY; oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC; if ((ext = strrchr(mixmonitor->filename, '.'))) *(ext++) = '\0'; else ext = "raw"; if (!(*fs = ast_writefile(mixmonitor->filename, ext, NULL, oflags, 0, 0666))) { ast_log(LOG_ERROR, "Cannot open %s.%s\n", mixmonitor->filename, ext); errflag = 1; } } /* Write out the frame(s) */ if (*fs) { struct ast_frame *cur; for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) { ast_writestream(*fs, cur); } } } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* All done! free it. */ ast_frame_free(fr, 0); ast_audiohook_lock(&mixmonitor->audiohook); } ast_audiohook_unlock(&mixmonitor->audiohook); /* Datastore cleanup. close the filestream and wait for ds destruction */ ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock); mixmonitor_ds_close_fs(mixmonitor->mixmonitor_ds); if (!mixmonitor->mixmonitor_ds->destruction_ok) { ast_cond_wait(&mixmonitor->mixmonitor_ds->destruction_condition, &mixmonitor->mixmonitor_ds->lock); } ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock); /* kill the audiohook */ destroy_monitor_audiohook(mixmonitor); if (mixmonitor->post_process) { ast_verb(2, "Executing [%s]\n", mixmonitor->post_process); ast_safe_system(mixmonitor->post_process); } ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name); mixmonitor_free(mixmonitor); return NULL; }
static int setup_mixmonitor_ds | ( | struct mixmonitor * | mixmonitor, |
struct ast_channel * | chan | ||
) | [static] |
Definition at line 367 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::audiohook, mixmonitor_ds::audiohook, chan, mixmonitor_ds::chan, ast_datastore::data, mixmonitor_ds::destruction_condition, mixmonitor_ds::lock, and mixmonitor::mixmonitor_ds.
Referenced by launch_monitor_thread().
{ struct ast_datastore *datastore = NULL; struct mixmonitor_ds *mixmonitor_ds; if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) { return -1; } ast_mutex_init(&mixmonitor_ds->lock); ast_cond_init(&mixmonitor_ds->destruction_condition, NULL); if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, NULL))) { ast_mutex_destroy(&mixmonitor_ds->lock); ast_cond_destroy(&mixmonitor_ds->destruction_condition); ast_free(mixmonitor_ds); return -1; } /* No need to lock mixmonitor_ds since this is still operating in the channel's thread */ mixmonitor_ds->chan = chan; mixmonitor_ds->audiohook = &mixmonitor->audiohook; datastore->data = mixmonitor_ds; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); mixmonitor->mixmonitor_ds = mixmonitor_ds; return 0; }
static int startmon | ( | struct ast_channel * | chan, |
struct ast_audiohook * | audiohook | ||
) | [static] |
Definition at line 250 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().
{ struct ast_channel *peer = NULL; int res = 0; if (!chan) return -1; ast_audiohook_attach(chan, audiohook); if (!res && ast_test_flag(chan, AST_FLAG_NBRIDGE) && (peer = ast_bridged_channel(chan))) ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE); return res; }
static int stop_mixmonitor_exec | ( | struct ast_channel * | chan, |
void * | data | ||
) | [static] |
Definition at line 551 of file app_mixmonitor.c.
References ast_audiohook_detach_source(), ast_audiohook_lock, ast_audiohook_unlock, ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_cond_signal(), ast_datastore_free(), ast_mutex_lock(), ast_mutex_unlock(), mixmonitor_ds::audiohook, ast_datastore::data, mixmonitor_ds::lock, mixmonitor_ds_close_fs(), and ast_audiohook::trigger.
Referenced by load_module().
{ struct ast_datastore *datastore = NULL; ast_channel_lock(chan); ast_audiohook_detach_source(chan, mixmonitor_spy_type); if ((datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, NULL))) { struct mixmonitor_ds *mixmonitor_ds = datastore->data; ast_mutex_lock(&mixmonitor_ds->lock); /* closing the filestream here guarantees the file is avaliable to the dialplan * after calling StopMixMonitor */ mixmonitor_ds_close_fs(mixmonitor_ds); /* The mixmonitor thread may be waiting on the audiohook trigger. * In order to exit from the mixmonitor loop before waiting on channel * destruction, poke the audiohook trigger. */ if (mixmonitor_ds->audiohook) { ast_audiohook_lock(mixmonitor_ds->audiohook); ast_cond_signal(&mixmonitor_ds->audiohook->trigger); ast_audiohook_unlock(mixmonitor_ds->audiohook); mixmonitor_ds->audiohook = NULL; } ast_mutex_unlock(&mixmonitor_ds->lock); /* Remove the datastore so the monitor thread can exit */ if (!ast_channel_datastore_remove(chan, datastore)) { ast_datastore_free(datastore); } } ast_channel_unlock(chan); return 0; }
static int unload_module | ( | void | ) | [static] |
Definition at line 628 of file app_mixmonitor.c.
References ARRAY_LEN, ast_cli_unregister_multiple(), and ast_unregister_application().
{ int res; ast_cli_unregister_multiple(cli_mixmonitor, ARRAY_LEN(cli_mixmonitor)); res = ast_unregister_application(stop_app); res |= ast_unregister_application(app); return res; }
struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mixed Audio Monitoring Application" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static] |
Definition at line 650 of file app_mixmonitor.c.
const char* app = "MixMonitor" [static] |
Definition at line 131 of file app_mixmonitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 650 of file app_mixmonitor.c.
struct ast_cli_entry cli_mixmonitor[] [static] |
{ AST_CLI_DEFINE(handle_cli_mixmonitor, "Execute a MixMonitor command") }
Definition at line 624 of file app_mixmonitor.c.
struct module_symbols* me |
Definition at line 135 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] |
{ .type = "mixmonitor", .destroy = mixmonitor_ds_destroy, .chan_fixup = mixmonitor_ds_chan_fixup, }
Definition at line 230 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 169 of file app_mixmonitor.c.
Referenced by mixmonitor_exec().
const char* mixmonitor_spy_type = "MixMonitor" [static] |
Definition at line 137 of file app_mixmonitor.c.
Referenced by builtin_automixmonitor().
const char* stop_app = "StopMixMonitor" [static] |
Definition at line 133 of file app_mixmonitor.c.