#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_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 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 |
Definition at line 112 of file app_mixmonitor.c.
00112 { 00113 OPT_ARG_READVOLUME = 0, 00114 OPT_ARG_WRITEVOLUME, 00115 OPT_ARG_VOLUME, 00116 OPT_ARG_ARRAY_SIZE, 00117 } mixmonitor_args;
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 }
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] |
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] |
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.