#include "asterisk.h"
#include <sys/stat.h>
#include <libgen.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/manager.h"
#include "asterisk/cli.h"
#include "asterisk/monitor.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/options.h"

Go to the source code of this file.
Defines | |
| #define | AST_API_MODULE |
| #define | LOCK_IF_NEEDED(lock, needed) |
| #define | UNLOCK_IF_NEEDED(lock, needed) |
Enumerations | |
| enum | MONITOR_PAUSING_ACTION { MONITOR_ACTION_PAUSE, MONITOR_ACTION_UNPAUSE } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| int AST_OPTIONAL_API_NAME() | ast_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock) |
| Change monitored filename of channel. | |
| int AST_OPTIONAL_API_NAME() | ast_monitor_pause (struct ast_channel *chan) |
| Pause monitoring of channel. | |
| static int | ast_monitor_set_state (struct ast_channel *chan, int state) |
| Change state of monitored channel. | |
| void AST_OPTIONAL_API_NAME() | ast_monitor_setjoinfiles (struct ast_channel *chan, int turnon) |
| int AST_OPTIONAL_API_NAME() | ast_monitor_start (struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action) |
| Start monitoring a channel. | |
| int AST_OPTIONAL_API_NAME() | ast_monitor_stop (struct ast_channel *chan, int need_lock) |
| Stop monitoring channel. | |
| int AST_OPTIONAL_API_NAME() | ast_monitor_unpause (struct ast_channel *chan) |
| Unpause monitoring of channel. | |
| static int | change_monitor_action (struct mansession *s, const struct message *m) |
| Change filename of a monitored channel by manager connection. | |
| static int | change_monitor_exec (struct ast_channel *chan, const char *data) |
| Wrapper function. | |
| static int | do_pause_or_unpause (struct mansession *s, const struct message *m, int action) |
| static const char * | get_soxmix_format (const char *format) |
| Get audio format. | |
| static int | load_module (void) |
| static int | pause_monitor_action (struct mansession *s, const struct message *m) |
| static int | pause_monitor_exec (struct ast_channel *chan, const char *data) |
| Wrapper for ast_monitor_pause. | |
| static int | start_monitor_action (struct mansession *s, const struct message *m) |
| Start monitoring a channel by manager connection. | |
| static int | start_monitor_exec (struct ast_channel *chan, const char *data) |
| Start monitor. | |
| static int | stop_monitor_action (struct mansession *s, const struct message *m) |
| Stop monitoring a channel by manager connection. | |
| static int | stop_monitor_exec (struct ast_channel *chan, const char *data) |
| Wrapper function. | |
| static int | unload_module (void) |
| static int | unpause_monitor_action (struct mansession *s, const struct message *m) |
| static int | unpause_monitor_exec (struct ast_channel *chan, const char *data) |
| Wrapper for ast_monitor_unpause. | |
Variables | |
| static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Call Monitoring Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } |
| static struct ast_module_info * | ast_module_info = &__mod_info |
| static ast_mutex_t | monitorlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) |
| static unsigned long | seq = 0 |
Definition in file res_monitor.c.
| #define AST_API_MODULE |
Definition at line 41 of file res_monitor.c.
| #define LOCK_IF_NEEDED | ( | lock, | |||
| needed | ) |
Value:
do { \ if (needed) \ ast_channel_lock(lock); \ } while(0)
Definition at line 244 of file res_monitor.c.
Referenced by ast_monitor_change_fname(), ast_monitor_set_state(), ast_monitor_start(), and ast_monitor_stop().
| #define UNLOCK_IF_NEEDED | ( | lock, | |||
| needed | ) |
Value:
do { \ if (needed) \ ast_channel_unlock(lock); \ } while (0)
Definition at line 249 of file res_monitor.c.
Referenced by ast_monitor_change_fname(), ast_monitor_set_state(), ast_monitor_start(), and ast_monitor_stop().
Definition at line 817 of file res_monitor.c.
00818 { 00819 MONITOR_ACTION_PAUSE, 00820 MONITOR_ACTION_UNPAUSE 00821 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 898 of file res_monitor.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 898 of file res_monitor.c.
| int AST_OPTIONAL_API_NAME() ast_monitor_change_fname | ( | struct ast_channel * | chan, | |
| const char * | fname_base, | |||
| int | need_lock | |||
| ) |
Change monitored filename of channel.
| chan | ||
| fname_base | new filename | |
| need_lock |
| 0 | on success. | |
| -1 | on failure. |
Definition at line 550 of file res_monitor.c.
References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_log(), ast_mkdir(), ast_strdupa, ast_strlen_zero(), ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, ast_channel::monitor, name, ast_channel::name, option_debug, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00551 { 00552 if (ast_strlen_zero(fname_base)) { 00553 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00554 return -1; 00555 } 00556 00557 LOCK_IF_NEEDED(chan, need_lock); 00558 00559 if (chan->monitor) { 00560 int directory = strchr(fname_base, '/') ? 1 : 0; 00561 const char *absolute = *fname_base == '/' ? "" : "/"; 00562 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00563 00564 /* before continuing, see if we're trying to rename the file to itself... */ 00565 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00566 if (!strcmp(tmpstring, chan->monitor->filename_base)) { 00567 if (option_debug > 2) 00568 ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n"); 00569 UNLOCK_IF_NEEDED(chan, need_lock); 00570 return 0; 00571 } 00572 00573 /* try creating the directory just in case it doesn't exist */ 00574 if (directory) { 00575 char *name = ast_strdupa(fname_base); 00576 ast_mkdir(dirname(name), 0777); 00577 } 00578 00579 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00580 chan->monitor->filename_changed = 1; 00581 } else { 00582 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00583 } 00584 00585 UNLOCK_IF_NEEDED(chan, need_lock); 00586 00587 return 0; 00588 }
| int AST_OPTIONAL_API_NAME() ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 519 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00520 { 00521 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00522 }
| static int ast_monitor_set_state | ( | struct ast_channel * | chan, | |
| int | state | |||
| ) | [static] |
Change state of monitored channel.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 263 of file res_monitor.c.
References LOCK_IF_NEEDED, ast_channel::monitor, ast_channel_monitor::state, and UNLOCK_IF_NEEDED.
Referenced by ast_monitor_pause(), ast_monitor_start(), and ast_monitor_unpause().
00264 { 00265 LOCK_IF_NEEDED(chan, 1); 00266 if (!chan->monitor) { 00267 UNLOCK_IF_NEEDED(chan, 1); 00268 return -1; 00269 } 00270 chan->monitor->state = state; 00271 UNLOCK_IF_NEEDED(chan, 1); 00272 return 0; 00273 }
| void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
| int | turnon | |||
| ) |
Definition at line 811 of file res_monitor.c.
References ast_channel_monitor::joinfiles, and ast_channel::monitor.
Referenced by __agent_start_monitoring(), start_monitor_action(), start_monitor_exec(), and try_calling().
| int AST_OPTIONAL_API_NAME() ast_monitor_start | ( | struct ast_channel * | chan, | |
| const char * | format_spec, | |||
| const char * | fname_base, | |||
| int | need_lock, | |||
| int | stream_action | |||
| ) |
Start monitoring a channel.
| chan | ast_channel struct to record | |
| format_spec | file format to use for recording | |
| fname_base | filename base to record to | |
| need_lock | whether to lock the channel mutex | |
| stream_action | whether to record the input and/or output streams. X_REC_IN | X_REC_OUT is most often used Creates the file to record, if no format is specified it assumes WAV It also sets channel variable __MONITORED=yes |
| 0 | on success | |
| -1 | on failure |
Definition at line 286 of file res_monitor.c.
References ast_calloc, ast_closestream(), ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, AST_FILE_MODE, ast_filedelete(), ast_fileexists(), ast_free, ast_log(), ast_mkdir(), AST_MONITOR_RUNNING, ast_monitor_set_state(), ast_monitor_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_writefile(), EVENT_FLAG_CALL, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, ast_channel_monitor::format, LOCK_IF_NEEDED, LOG_WARNING, manager_event, monitor, ast_channel::monitor, monitorlock, ast_channel::name, name, pbx_builtin_setvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, ast_channel_monitor::stop, ast_channel::uniqueid, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, ast_channel_monitor::write_stream, X_REC_IN, and X_REC_OUT.
Referenced by __agent_start_monitoring(), start_monitor_action(), start_monitor_exec(), and try_calling().
00288 { 00289 int res = 0; 00290 00291 LOCK_IF_NEEDED(chan, need_lock); 00292 00293 if (!(chan->monitor)) { 00294 struct ast_channel_monitor *monitor; 00295 char *channel_name, *p; 00296 00297 /* Create monitoring directory if needed */ 00298 ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); 00299 00300 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { 00301 UNLOCK_IF_NEEDED(chan, need_lock); 00302 return -1; 00303 } 00304 00305 /* Determine file names */ 00306 if (!ast_strlen_zero(fname_base)) { 00307 int directory = strchr(fname_base, '/') ? 1 : 0; 00308 const char *absolute = *fname_base == '/' ? "" : "/"; 00309 /* try creating the directory just in case it doesn't exist */ 00310 if (directory) { 00311 char *name = ast_strdupa(fname_base); 00312 ast_mkdir(dirname(name), 0777); 00313 } 00314 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", 00315 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00316 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", 00317 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00318 ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base)); 00319 } else { 00320 ast_mutex_lock(&monitorlock); 00321 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00322 ast_config_AST_MONITOR_DIR, seq); 00323 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00324 ast_config_AST_MONITOR_DIR, seq); 00325 seq++; 00326 ast_mutex_unlock(&monitorlock); 00327 00328 channel_name = ast_strdupa(chan->name); 00329 while ((p = strchr(channel_name, '/'))) { 00330 *p = '-'; 00331 } 00332 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00333 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00334 monitor->filename_changed = 1; 00335 } 00336 00337 monitor->stop = ast_monitor_stop; 00338 00339 /* Determine file format */ 00340 if (!ast_strlen_zero(format_spec)) { 00341 monitor->format = ast_strdup(format_spec); 00342 } else { 00343 monitor->format = ast_strdup("wav"); 00344 } 00345 00346 /* open files */ 00347 if (stream_action & X_REC_IN) { 00348 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) 00349 ast_filedelete(monitor->read_filename, NULL); 00350 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00351 monitor->format, NULL, 00352 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00353 ast_log(LOG_WARNING, "Could not create file %s\n", 00354 monitor->read_filename); 00355 ast_free(monitor); 00356 UNLOCK_IF_NEEDED(chan, need_lock); 00357 return -1; 00358 } 00359 } else 00360 monitor->read_stream = NULL; 00361 00362 if (stream_action & X_REC_OUT) { 00363 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00364 ast_filedelete(monitor->write_filename, NULL); 00365 } 00366 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00367 monitor->format, NULL, 00368 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00369 ast_log(LOG_WARNING, "Could not create file %s\n", 00370 monitor->write_filename); 00371 ast_closestream(monitor->read_stream); 00372 ast_free(monitor); 00373 UNLOCK_IF_NEEDED(chan, need_lock); 00374 return -1; 00375 } 00376 } else 00377 monitor->write_stream = NULL; 00378 00379 chan->monitor = monitor; 00380 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00381 /* so we know this call has been monitored in case we need to bill for it or something */ 00382 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00383 00384 manager_event(EVENT_FLAG_CALL, "MonitorStart", 00385 "Channel: %s\r\n" 00386 "Uniqueid: %s\r\n", 00387 chan->name, 00388 chan->uniqueid 00389 ); 00390 } else { 00391 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name); 00392 res = -1; 00393 } 00394 00395 UNLOCK_IF_NEEDED(chan, need_lock); 00396 00397 return res; 00398 }
| int AST_OPTIONAL_API_NAME() ast_monitor_stop | ( | struct ast_channel * | chan, | |
| int | need_lock | |||
| ) |
Stop monitoring channel.
| chan | ||
| need_lock | Stop the recording, close any open streams, mix in/out channels if required |
Definition at line 426 of file res_monitor.c.
References ast_closestream(), ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), ast_safe_system(), ast_strlen_zero(), dir, EVENT_FLAG_CALL, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, format, ast_channel_monitor::format, get_soxmix_format(), ast_channel_monitor::joinfiles, LOCK_IF_NEEDED, LOG_WARNING, manager_event, ast_channel::monitor, ast_channel::name, name, pbx_builtin_getvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, ast_channel::uniqueid, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, and ast_channel_monitor::write_stream.
Referenced by ast_monitor_start(), stop_monitor_action(), and stop_monitor_exec().
00427 { 00428 int delfiles = 0; 00429 00430 LOCK_IF_NEEDED(chan, need_lock); 00431 00432 if (chan->monitor) { 00433 char filename[ FILENAME_MAX ]; 00434 00435 if (chan->monitor->read_stream) { 00436 ast_closestream(chan->monitor->read_stream); 00437 } 00438 if (chan->monitor->write_stream) { 00439 ast_closestream(chan->monitor->write_stream); 00440 } 00441 00442 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00443 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00444 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00445 if (ast_fileexists(filename, NULL, NULL) > 0) { 00446 ast_filedelete(filename, NULL); 00447 } 00448 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00449 } else { 00450 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00451 } 00452 00453 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00454 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00455 if (ast_fileexists(filename, NULL, NULL) > 0) { 00456 ast_filedelete(filename, NULL); 00457 } 00458 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00459 } else { 00460 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00461 } 00462 } 00463 00464 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00465 char tmp[1024]; 00466 char tmp2[1024]; 00467 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00468 char *name = chan->monitor->filename_base; 00469 int directory = strchr(name, '/') ? 1 : 0; 00470 const char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; 00471 const char *execute, *execute_args; 00472 const char *absolute = *name == '/' ? "" : "/"; 00473 00474 /* Set the execute application */ 00475 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00476 if (ast_strlen_zero(execute)) { 00477 #ifdef HAVE_SOXMIX 00478 execute = "nice -n 19 soxmix"; 00479 #else 00480 execute = "nice -n 19 sox -m"; 00481 #endif 00482 format = get_soxmix_format(format); 00483 delfiles = 1; 00484 } 00485 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00486 if (ast_strlen_zero(execute_args)) { 00487 execute_args = ""; 00488 } 00489 00490 snprintf(tmp, sizeof(tmp), "%s \"%s%s%s-in.%s\" \"%s%s%s-out.%s\" \"%s%s%s.%s\" %s &", execute, dir, absolute, name, format, dir, absolute, name, format, dir, absolute, name, format,execute_args); 00491 if (delfiles) { 00492 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */ 00493 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00494 } 00495 ast_debug(1,"monitor executing %s\n",tmp); 00496 if (ast_safe_system(tmp) == -1) 00497 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00498 } 00499 00500 ast_free(chan->monitor->format); 00501 ast_free(chan->monitor); 00502 chan->monitor = NULL; 00503 00504 manager_event(EVENT_FLAG_CALL, "MonitorStop", 00505 "Channel: %s\r\n" 00506 "Uniqueid: %s\r\n", 00507 chan->name, 00508 chan->uniqueid 00509 ); 00510 } 00511 00512 UNLOCK_IF_NEEDED(chan, need_lock); 00513 00514 return 0; 00515 }
| int AST_OPTIONAL_API_NAME() ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 525 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00526 { 00527 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00528 }
| static int change_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Change filename of a monitored channel by manager connection.
Definition at line 777 of file res_monitor.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_monitor_change_fname(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.
Referenced by load_module().
00778 { 00779 struct ast_channel *c = NULL; 00780 const char *name = astman_get_header(m, "Channel"); 00781 const char *fname = astman_get_header(m, "File"); 00782 00783 if (ast_strlen_zero(name)) { 00784 astman_send_error(s, m, "No channel specified"); 00785 return 0; 00786 } 00787 00788 if (ast_strlen_zero(fname)) { 00789 astman_send_error(s, m, "No filename specified"); 00790 return 0; 00791 } 00792 00793 if (!(c = ast_channel_get_by_name(name))) { 00794 astman_send_error(s, m, "No such channel"); 00795 return 0; 00796 } 00797 00798 if (ast_monitor_change_fname(c, fname, 1)) { 00799 c = ast_channel_unref(c); 00800 astman_send_error(s, m, "Could not change monitored filename of channel"); 00801 return 0; 00802 } 00803 00804 c = ast_channel_unref(c); 00805 00806 astman_send_ack(s, m, "Changed monitor filename"); 00807 00808 return 0; 00809 }
| static int change_monitor_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Wrapper function.
Definition at line 688 of file res_monitor.c.
References ast_monitor_change_fname().
Referenced by load_module().
00689 { 00690 return ast_monitor_change_fname(chan, data, 1); 00691 }
| static int do_pause_or_unpause | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | action | |||
| ) | [static] |
Definition at line 823 of file res_monitor.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_monitor_pause(), ast_monitor_unpause(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), MONITOR_ACTION_PAUSE, and name.
Referenced by pause_monitor_action(), and unpause_monitor_action().
00824 { 00825 struct ast_channel *c = NULL; 00826 const char *name = astman_get_header(m, "Channel"); 00827 00828 if (ast_strlen_zero(name)) { 00829 astman_send_error(s, m, "No channel specified"); 00830 return -1; 00831 } 00832 00833 if (!(c = ast_channel_get_by_name(name))) { 00834 astman_send_error(s, m, "No such channel"); 00835 return -1; 00836 } 00837 00838 if (action == MONITOR_ACTION_PAUSE) { 00839 ast_monitor_pause(c); 00840 } else { 00841 ast_monitor_unpause(c); 00842 } 00843 00844 c = ast_channel_unref(c); 00845 00846 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00847 00848 return 0; 00849 }
| static const char* get_soxmix_format | ( | const char * | format | ) | [static] |
Get audio format.
| format | recording format. The file format extensions that Asterisk uses are not all the same as that which soxmix expects. This function ensures that the format used as the extension on the filename is something soxmix will understand. |
Definition at line 407 of file res_monitor.c.
Referenced by ast_monitor_stop().
00408 { 00409 const char *res = format; 00410 00411 if (!strcasecmp(format,"ulaw")) 00412 res = "ul"; 00413 if (!strcasecmp(format,"alaw")) 00414 res = "al"; 00415 00416 return res; 00417 }
| static int load_module | ( | void | ) | [static] |
Definition at line 862 of file res_monitor.c.
References ast_manager_register_xml, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, change_monitor_action(), change_monitor_exec(), EVENT_FLAG_CALL, pause_monitor_action(), pause_monitor_exec(), start_monitor_action(), start_monitor_exec(), stop_monitor_action(), stop_monitor_exec(), unpause_monitor_action(), and unpause_monitor_exec().
00863 { 00864 ast_register_application_xml("Monitor", start_monitor_exec); 00865 ast_register_application_xml("StopMonitor", stop_monitor_exec); 00866 ast_register_application_xml("ChangeMonitor", change_monitor_exec); 00867 ast_register_application_xml("PauseMonitor", pause_monitor_exec); 00868 ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec); 00869 ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action); 00870 ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action); 00871 ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action); 00872 ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action); 00873 ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action); 00874 00875 return AST_MODULE_LOAD_SUCCESS; 00876 }
| static int pause_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 851 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.
Referenced by load_module().
00852 { 00853 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00854 }
| static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 531 of file res_monitor.c.
References ast_monitor_pause().
Referenced by load_module().
00532 { 00533 return ast_monitor_pause(chan); 00534 }
| static int start_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Start monitoring a channel by manager connection.
Definition at line 694 of file res_monitor.c.
References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), ast_strdupa, ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), format, ast_channel::name, name, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00695 { 00696 struct ast_channel *c = NULL; 00697 const char *name = astman_get_header(m, "Channel"); 00698 const char *fname = astman_get_header(m, "File"); 00699 const char *format = astman_get_header(m, "Format"); 00700 const char *mix = astman_get_header(m, "Mix"); 00701 char *d; 00702 00703 if (ast_strlen_zero(name)) { 00704 astman_send_error(s, m, "No channel specified"); 00705 return 0; 00706 } 00707 00708 if (!(c = ast_channel_get_by_name(name))) { 00709 astman_send_error(s, m, "No such channel"); 00710 return 0; 00711 } 00712 00713 if (ast_strlen_zero(fname)) { 00714 /* No filename base specified, default to channel name as per CLI */ 00715 ast_channel_lock(c); 00716 fname = ast_strdupa(c->name); 00717 ast_channel_unlock(c); 00718 /* Channels have the format technology/channel_name - have to replace that / */ 00719 if ((d = strchr(fname, '/'))) { 00720 *d = '-'; 00721 } 00722 } 00723 00724 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00725 if (ast_monitor_change_fname(c, fname, 1)) { 00726 astman_send_error(s, m, "Could not start monitoring channel"); 00727 c = ast_channel_unref(c); 00728 return 0; 00729 } 00730 } 00731 00732 if (ast_true(mix)) { 00733 ast_channel_lock(c); 00734 ast_monitor_setjoinfiles(c, 1); 00735 ast_channel_unlock(c); 00736 } 00737 00738 c = ast_channel_unref(c); 00739 00740 astman_send_ack(s, m, "Started monitoring channel"); 00741 00742 return 0; 00743 }
| static int start_monitor_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Start monitor.
| chan | ||
| data | arguments passed fname|options |
| 0 | on success. | |
| -1 | on failure. |
Definition at line 598 of file res_monitor.c.
References AST_APP_ARG, ast_cdr_alloc(), ast_cdr_setuserfield(), AST_DECLARE_APP_ARGS, ast_log(), ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::cdr, format, LOG_ERROR, LOG_WARNING, parse(), pbx_builtin_setvar_helper(), urlprefix, X_JOIN, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00599 { 00600 char *arg = NULL; 00601 char *options = NULL; 00602 char *delay = NULL; 00603 char *urlprefix = NULL; 00604 char tmp[256]; 00605 int stream_action = X_REC_IN | X_REC_OUT; 00606 int joinfiles = 0; 00607 int waitforbridge = 0; 00608 int res = 0; 00609 char *parse; 00610 AST_DECLARE_APP_ARGS(args, 00611 AST_APP_ARG(format); 00612 AST_APP_ARG(fname_base); 00613 AST_APP_ARG(options); 00614 ); 00615 00616 /* Parse arguments. */ 00617 if (ast_strlen_zero(data)) { 00618 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00619 return 0; 00620 } 00621 00622 parse = ast_strdupa(data); 00623 AST_STANDARD_APP_ARGS(args, parse); 00624 00625 if (!ast_strlen_zero(args.options)) { 00626 if (strchr(args.options, 'm')) 00627 stream_action |= X_JOIN; 00628 if (strchr(args.options, 'b')) 00629 waitforbridge = 1; 00630 if (strchr(args.options, 'i')) 00631 stream_action &= ~X_REC_IN; 00632 if (strchr(args.options, 'o')) 00633 stream_action &= ~X_REC_OUT; 00634 } 00635 00636 arg = strchr(args.format, ':'); 00637 if (arg) { 00638 *arg++ = 0; 00639 urlprefix = arg; 00640 } 00641 00642 if (urlprefix) { 00643 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00644 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00645 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) 00646 return -1; 00647 ast_cdr_setuserfield(chan, tmp); 00648 } 00649 if (waitforbridge) { 00650 /* We must remove the "b" option if listed. In principle none of 00651 the following could give NULL results, but we check just to 00652 be pedantic. Reconstructing with checks for 'm' option does not 00653 work if we end up adding more options than 'm' in the future. */ 00654 delay = ast_strdupa(data); 00655 options = strrchr(delay, ','); 00656 if (options) { 00657 arg = strchr(options, 'b'); 00658 if (arg) { 00659 *arg = 'X'; 00660 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00661 } 00662 } 00663 return 0; 00664 } 00665 00666 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00667 if (res < 0) 00668 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00669 00670 if (stream_action & X_JOIN) { 00671 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00672 joinfiles = 1; 00673 else 00674 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00675 } 00676 ast_monitor_setjoinfiles(chan, joinfiles); 00677 00678 return res; 00679 }
| static int stop_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 746 of file res_monitor.c.
References ast_channel_get_by_name(), ast_channel_unref, ast_monitor_stop(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.
Referenced by load_module().
00747 { 00748 struct ast_channel *c = NULL; 00749 const char *name = astman_get_header(m, "Channel"); 00750 int res; 00751 00752 if (ast_strlen_zero(name)) { 00753 astman_send_error(s, m, "No channel specified"); 00754 return 0; 00755 } 00756 00757 if (!(c = ast_channel_get_by_name(name))) { 00758 astman_send_error(s, m, "No such channel"); 00759 return 0; 00760 } 00761 00762 res = ast_monitor_stop(c, 1); 00763 00764 c = ast_channel_unref(c); 00765 00766 if (res) { 00767 astman_send_error(s, m, "Could not stop monitoring channel"); 00768 return 0; 00769 } 00770 00771 astman_send_ack(s, m, "Stopped monitoring channel"); 00772 00773 return 0; 00774 }
| static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Wrapper function.
Definition at line 682 of file res_monitor.c.
References ast_monitor_stop().
Referenced by load_module().
00683 { 00684 return ast_monitor_stop(chan, 1); 00685 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 878 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00879 { 00880 ast_unregister_application("Monitor"); 00881 ast_unregister_application("StopMonitor"); 00882 ast_unregister_application("ChangeMonitor"); 00883 ast_unregister_application("PauseMonitor"); 00884 ast_unregister_application("UnpauseMonitor"); 00885 ast_manager_unregister("Monitor"); 00886 ast_manager_unregister("StopMonitor"); 00887 ast_manager_unregister("ChangeMonitor"); 00888 ast_manager_unregister("PauseMonitor"); 00889 ast_manager_unregister("UnpauseMonitor"); 00890 00891 return 0; 00892 }
| static int unpause_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 856 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_UNPAUSE.
Referenced by load_module().
00857 { 00858 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00859 }
| static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
| const char * | data | |||
| ) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 537 of file res_monitor.c.
References ast_monitor_unpause().
Referenced by load_module().
00538 { 00539 return ast_monitor_unpause(chan); 00540 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Call Monitoring Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static] |
Definition at line 898 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 898 of file res_monitor.c.
ast_mutex_t monitorlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static] |
unsigned long seq = 0 [static] |
Definition at line 254 of file res_monitor.c.
1.5.6