#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 | AST_MODFLAG_LOAD_ORDER , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static ast_mutex_t | monitorlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } |
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 855 of file res_monitor.c.
00856 { 00857 MONITOR_ACTION_PAUSE, 00858 MONITOR_ACTION_UNPAUSE 00859 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 937 of file res_monitor.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 937 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 554 of file res_monitor.c.
References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, ast_log(), ast_mkdir(), ast_strdupa, ast_strlen_zero(), errno, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, LOCK_IF_NEEDED, LOG_ERROR, LOG_WARNING, ast_channel::monitor, name, ast_channel::name, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00555 { 00556 if (ast_strlen_zero(fname_base)) { 00557 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00558 return -1; 00559 } 00560 00561 LOCK_IF_NEEDED(chan, need_lock); 00562 00563 if (chan->monitor) { 00564 int directory = strchr(fname_base, '/') ? 1 : 0; 00565 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00566 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00567 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00568 int i, fd[2] = { -1, -1 }, doexit = 0; 00569 00570 /* before continuing, see if we're trying to rename the file to itself... */ 00571 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base); 00572 00573 /* try creating the directory just in case it doesn't exist */ 00574 if (directory) { 00575 char *name = ast_strdupa(tmpstring); 00576 ast_mkdir(dirname(name), 0777); 00577 } 00578 00579 /*!\note We cannot just compare filenames, due to symlinks, relative 00580 * paths, and other possible filesystem issues. We could use 00581 * realpath(3), but its use is discouraged. However, if we try to 00582 * create the same file from two different paths, the second will 00583 * fail, and so we have our notification that the filenames point to 00584 * the same path. 00585 * 00586 * Remember, also, that we're using the basename of the file (i.e. 00587 * the file without the format suffix), so it does not already exist 00588 * and we aren't interfering with the recording itself. 00589 */ 00590 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00591 00592 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00593 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00594 if (fd[0] < 0) { 00595 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00596 } else { 00597 ast_debug(2, "No need to rename monitor filename to itself\n"); 00598 } 00599 doexit = 1; 00600 } 00601 00602 /* Cleanup temporary files */ 00603 for (i = 0; i < 2; i++) { 00604 if (fd[i] >= 0) { 00605 while (close(fd[i]) < 0 && errno == EINTR); 00606 } 00607 } 00608 unlink(tmpstring); 00609 /* if previous monitor file existed in a subdirectory, the directory will not be removed */ 00610 unlink(chan->monitor->filename_base); 00611 00612 if (doexit) { 00613 UNLOCK_IF_NEEDED(chan, need_lock); 00614 return 0; 00615 } 00616 00617 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00618 chan->monitor->filename_changed = 1; 00619 } else { 00620 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00621 } 00622 00623 UNLOCK_IF_NEEDED(chan, need_lock); 00624 00625 return 0; 00626 }
int AST_OPTIONAL_API_NAME() ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 523 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00524 { 00525 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00526 }
static int ast_monitor_set_state | ( | struct ast_channel * | chan, | |
int | state | |||
) | [static] |
Change state of monitored channel.
chan | ||
state | monitor state |
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 849 of file res_monitor.c.
References ast_channel_monitor::joinfiles, and ast_channel::monitor.
Referenced by __agent_start_monitoring(), start_monitor_action(), and start_monitor_exec().
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_debug, AST_FILE_MODE, ast_filedelete(), ast_fileexists(), ast_free, ast_log(), ast_manager_event, 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, FILENAME_MAX, LOCK_IF_NEEDED, LOG_WARNING, monitor, ast_channel::monitor, monitorlock, ast_channel::name, name, pbx_builtin_setvar_helper(), ast_channel::uniqueid, UNLOCK_IF_NEEDED, X_REC_IN, and X_REC_OUT.
Referenced by __agent_start_monitoring(), start_monitor_action(), and start_monitor_exec().
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 == '/' ? "" : ast_config_AST_MONITOR_DIR; 00309 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00310 00311 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", 00312 absolute, absolute_suffix, fname_base); 00313 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", 00314 absolute, absolute_suffix, fname_base); 00315 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", 00316 absolute, absolute_suffix, fname_base); 00317 00318 /* try creating the directory just in case it doesn't exist */ 00319 if (directory) { 00320 char *name = ast_strdupa(monitor->filename_base); 00321 ast_mkdir(dirname(name), 0777); 00322 } 00323 } else { 00324 ast_mutex_lock(&monitorlock); 00325 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00326 ast_config_AST_MONITOR_DIR, seq); 00327 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00328 ast_config_AST_MONITOR_DIR, seq); 00329 seq++; 00330 ast_mutex_unlock(&monitorlock); 00331 00332 channel_name = ast_strdupa(chan->name); 00333 while ((p = strchr(channel_name, '/'))) { 00334 *p = '-'; 00335 } 00336 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00337 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00338 monitor->filename_changed = 1; 00339 } 00340 00341 monitor->stop = ast_monitor_stop; 00342 00343 /* Determine file format */ 00344 if (!ast_strlen_zero(format_spec)) { 00345 monitor->format = ast_strdup(format_spec); 00346 } else { 00347 monitor->format = ast_strdup("wav"); 00348 } 00349 00350 /* open files */ 00351 if (stream_action & X_REC_IN) { 00352 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) 00353 ast_filedelete(monitor->read_filename, NULL); 00354 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00355 monitor->format, NULL, 00356 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00357 ast_log(LOG_WARNING, "Could not create file %s\n", 00358 monitor->read_filename); 00359 ast_free(monitor); 00360 UNLOCK_IF_NEEDED(chan, need_lock); 00361 return -1; 00362 } 00363 } else 00364 monitor->read_stream = NULL; 00365 00366 if (stream_action & X_REC_OUT) { 00367 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00368 ast_filedelete(monitor->write_filename, NULL); 00369 } 00370 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00371 monitor->format, NULL, 00372 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00373 ast_log(LOG_WARNING, "Could not create file %s\n", 00374 monitor->write_filename); 00375 ast_closestream(monitor->read_stream); 00376 ast_free(monitor); 00377 UNLOCK_IF_NEEDED(chan, need_lock); 00378 return -1; 00379 } 00380 } else 00381 monitor->write_stream = NULL; 00382 00383 chan->monitor = monitor; 00384 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00385 /* so we know this call has been monitored in case we need to bill for it or something */ 00386 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00387 00388 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStart", 00389 "Channel: %s\r\n" 00390 "Uniqueid: %s\r\n", 00391 chan->name, 00392 chan->uniqueid); 00393 } else { 00394 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name); 00395 res = -1; 00396 } 00397 00398 UNLOCK_IF_NEEDED(chan, need_lock); 00399 00400 return res; 00401 }
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 429 of file res_monitor.c.
References ast_closestream(), ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), ast_manager_event, ast_safe_system(), ast_strlen_zero(), 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, ast_channel::monitor, ast_channel::name, pbx_builtin_getvar_helper(), pbx_builtin_setvar_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().
00430 { 00431 int delfiles = 0; 00432 00433 LOCK_IF_NEEDED(chan, need_lock); 00434 00435 if (chan->monitor) { 00436 char filename[ FILENAME_MAX ]; 00437 00438 if (chan->monitor->read_stream) { 00439 ast_closestream(chan->monitor->read_stream); 00440 } 00441 if (chan->monitor->write_stream) { 00442 ast_closestream(chan->monitor->write_stream); 00443 } 00444 00445 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00446 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00447 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00448 if (ast_fileexists(filename, NULL, NULL) > 0) { 00449 ast_filedelete(filename, NULL); 00450 } 00451 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00452 } else { 00453 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00454 } 00455 00456 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00457 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00458 if (ast_fileexists(filename, NULL, NULL) > 0) { 00459 ast_filedelete(filename, NULL); 00460 } 00461 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00462 } else { 00463 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00464 } 00465 } 00466 00467 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00468 char tmp[1024]; 00469 char tmp2[1024]; 00470 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00471 char *fname_base = chan->monitor->filename_base; 00472 const char *execute, *execute_args; 00473 /* at this point, fname_base really is the full path */ 00474 00475 /* Set the execute application */ 00476 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00477 if (ast_strlen_zero(execute)) { 00478 #ifdef HAVE_SOXMIX 00479 execute = "nice -n 19 soxmix"; 00480 #else 00481 execute = "nice -n 19 sox -m"; 00482 #endif 00483 format = get_soxmix_format(format); 00484 delfiles = 1; 00485 } 00486 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00487 if (ast_strlen_zero(execute_args)) { 00488 execute_args = ""; 00489 } 00490 00491 snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &", 00492 execute, fname_base, format, fname_base, format, fname_base, format,execute_args); 00493 if (delfiles) { 00494 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */ 00495 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00496 } 00497 ast_debug(1,"monitor executing %s\n",tmp); 00498 if (ast_safe_system(tmp) == -1) 00499 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00500 } 00501 00502 ast_free(chan->monitor->format); 00503 ast_free(chan->monitor); 00504 chan->monitor = NULL; 00505 00506 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop", 00507 "Channel: %s\r\n" 00508 "Uniqueid: %s\r\n", 00509 chan->name, 00510 chan->uniqueid 00511 ); 00512 pbx_builtin_setvar_helper(chan, "MONITORED", NULL); 00513 } 00514 pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL); 00515 00516 UNLOCK_IF_NEEDED(chan, need_lock); 00517 00518 return 0; 00519 }
int AST_OPTIONAL_API_NAME() ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 529 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00530 { 00531 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00532 }
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 815 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().
00816 { 00817 struct ast_channel *c = NULL; 00818 const char *name = astman_get_header(m, "Channel"); 00819 const char *fname = astman_get_header(m, "File"); 00820 00821 if (ast_strlen_zero(name)) { 00822 astman_send_error(s, m, "No channel specified"); 00823 return 0; 00824 } 00825 00826 if (ast_strlen_zero(fname)) { 00827 astman_send_error(s, m, "No filename specified"); 00828 return 0; 00829 } 00830 00831 if (!(c = ast_channel_get_by_name(name))) { 00832 astman_send_error(s, m, "No such channel"); 00833 return 0; 00834 } 00835 00836 if (ast_monitor_change_fname(c, fname, 1)) { 00837 c = ast_channel_unref(c); 00838 astman_send_error(s, m, "Could not change monitored filename of channel"); 00839 return 0; 00840 } 00841 00842 c = ast_channel_unref(c); 00843 00844 astman_send_ack(s, m, "Changed monitor filename"); 00845 00846 return 0; 00847 }
static int change_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper function.
Definition at line 726 of file res_monitor.c.
References ast_monitor_change_fname().
Referenced by load_module().
00727 { 00728 return ast_monitor_change_fname(chan, data, 1); 00729 }
static int do_pause_or_unpause | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | action | |||
) | [static] |
Definition at line 861 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().
00862 { 00863 struct ast_channel *c = NULL; 00864 const char *name = astman_get_header(m, "Channel"); 00865 00866 if (ast_strlen_zero(name)) { 00867 astman_send_error(s, m, "No channel specified"); 00868 return -1; 00869 } 00870 00871 if (!(c = ast_channel_get_by_name(name))) { 00872 astman_send_error(s, m, "No such channel"); 00873 return -1; 00874 } 00875 00876 if (action == MONITOR_ACTION_PAUSE) { 00877 ast_monitor_pause(c); 00878 } else { 00879 ast_monitor_unpause(c); 00880 } 00881 00882 c = ast_channel_unref(c); 00883 00884 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00885 00886 return 0; 00887 }
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 410 of file res_monitor.c.
Referenced by ast_monitor_stop().
00411 { 00412 const char *res = format; 00413 00414 if (!strcasecmp(format,"ulaw")) 00415 res = "ul"; 00416 if (!strcasecmp(format,"alaw")) 00417 res = "al"; 00418 00419 return res; 00420 }
static int load_module | ( | void | ) | [static] |
Definition at line 900 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().
00901 { 00902 ast_register_application_xml("Monitor", start_monitor_exec); 00903 ast_register_application_xml("StopMonitor", stop_monitor_exec); 00904 ast_register_application_xml("ChangeMonitor", change_monitor_exec); 00905 ast_register_application_xml("PauseMonitor", pause_monitor_exec); 00906 ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec); 00907 ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action); 00908 ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action); 00909 ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action); 00910 ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action); 00911 ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action); 00912 00913 return AST_MODULE_LOAD_SUCCESS; 00914 }
static int pause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 889 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.
Referenced by load_module().
00890 { 00891 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00892 }
static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 535 of file res_monitor.c.
References ast_monitor_pause().
Referenced by load_module().
00536 { 00537 return ast_monitor_pause(chan); 00538 }
static int start_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Start monitoring a channel by manager connection.
Definition at line 732 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, name, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00733 { 00734 struct ast_channel *c = NULL; 00735 const char *name = astman_get_header(m, "Channel"); 00736 const char *fname = astman_get_header(m, "File"); 00737 const char *format = astman_get_header(m, "Format"); 00738 const char *mix = astman_get_header(m, "Mix"); 00739 char *d; 00740 00741 if (ast_strlen_zero(name)) { 00742 astman_send_error(s, m, "No channel specified"); 00743 return 0; 00744 } 00745 00746 if (!(c = ast_channel_get_by_name(name))) { 00747 astman_send_error(s, m, "No such channel"); 00748 return 0; 00749 } 00750 00751 if (ast_strlen_zero(fname)) { 00752 /* No filename base specified, default to channel name as per CLI */ 00753 ast_channel_lock(c); 00754 fname = ast_strdupa(c->name); 00755 ast_channel_unlock(c); 00756 /* Channels have the format technology/channel_name - have to replace that / */ 00757 if ((d = strchr(fname, '/'))) { 00758 *d = '-'; 00759 } 00760 } 00761 00762 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00763 if (ast_monitor_change_fname(c, fname, 1)) { 00764 astman_send_error(s, m, "Could not start monitoring channel"); 00765 c = ast_channel_unref(c); 00766 return 0; 00767 } 00768 } 00769 00770 if (ast_true(mix)) { 00771 ast_channel_lock(c); 00772 ast_monitor_setjoinfiles(c, 1); 00773 ast_channel_unlock(c); 00774 } 00775 00776 c = ast_channel_unref(c); 00777 00778 astman_send_ack(s, m, "Started monitoring channel"); 00779 00780 return 0; 00781 }
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 636 of file res_monitor.c.
References args, 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().
00637 { 00638 char *arg = NULL; 00639 char *options = NULL; 00640 char *delay = NULL; 00641 char *urlprefix = NULL; 00642 char tmp[256]; 00643 int stream_action = X_REC_IN | X_REC_OUT; 00644 int joinfiles = 0; 00645 int waitforbridge = 0; 00646 int res = 0; 00647 char *parse; 00648 AST_DECLARE_APP_ARGS(args, 00649 AST_APP_ARG(format); 00650 AST_APP_ARG(fname_base); 00651 AST_APP_ARG(options); 00652 ); 00653 00654 /* Parse arguments. */ 00655 if (ast_strlen_zero(data)) { 00656 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00657 return 0; 00658 } 00659 00660 parse = ast_strdupa(data); 00661 AST_STANDARD_APP_ARGS(args, parse); 00662 00663 if (!ast_strlen_zero(args.options)) { 00664 if (strchr(args.options, 'm')) 00665 stream_action |= X_JOIN; 00666 if (strchr(args.options, 'b')) 00667 waitforbridge = 1; 00668 if (strchr(args.options, 'i')) 00669 stream_action &= ~X_REC_IN; 00670 if (strchr(args.options, 'o')) 00671 stream_action &= ~X_REC_OUT; 00672 } 00673 00674 arg = strchr(args.format, ':'); 00675 if (arg) { 00676 *arg++ = 0; 00677 urlprefix = arg; 00678 } 00679 00680 if (urlprefix) { 00681 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00682 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00683 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) 00684 return -1; 00685 ast_cdr_setuserfield(chan, tmp); 00686 } 00687 if (waitforbridge) { 00688 /* We must remove the "b" option if listed. In principle none of 00689 the following could give NULL results, but we check just to 00690 be pedantic. Reconstructing with checks for 'm' option does not 00691 work if we end up adding more options than 'm' in the future. */ 00692 delay = ast_strdupa(data); 00693 options = strrchr(delay, ','); 00694 if (options) { 00695 arg = strchr(options, 'b'); 00696 if (arg) { 00697 *arg = 'X'; 00698 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00699 } 00700 } 00701 return 0; 00702 } 00703 00704 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00705 if (res < 0) 00706 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00707 00708 if (stream_action & X_JOIN) { 00709 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00710 joinfiles = 1; 00711 else 00712 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00713 } 00714 ast_monitor_setjoinfiles(chan, joinfiles); 00715 00716 return res; 00717 }
static int stop_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 784 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().
00785 { 00786 struct ast_channel *c = NULL; 00787 const char *name = astman_get_header(m, "Channel"); 00788 int res; 00789 00790 if (ast_strlen_zero(name)) { 00791 astman_send_error(s, m, "No channel specified"); 00792 return 0; 00793 } 00794 00795 if (!(c = ast_channel_get_by_name(name))) { 00796 astman_send_error(s, m, "No such channel"); 00797 return 0; 00798 } 00799 00800 res = ast_monitor_stop(c, 1); 00801 00802 c = ast_channel_unref(c); 00803 00804 if (res) { 00805 astman_send_error(s, m, "Could not stop monitoring channel"); 00806 return 0; 00807 } 00808 00809 astman_send_ack(s, m, "Stopped monitoring channel"); 00810 00811 return 0; 00812 }
static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper function.
Definition at line 720 of file res_monitor.c.
References ast_monitor_stop().
Referenced by load_module().
00721 { 00722 return ast_monitor_stop(chan, 1); 00723 }
static int unload_module | ( | void | ) | [static] |
Definition at line 916 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00917 { 00918 ast_unregister_application("Monitor"); 00919 ast_unregister_application("StopMonitor"); 00920 ast_unregister_application("ChangeMonitor"); 00921 ast_unregister_application("PauseMonitor"); 00922 ast_unregister_application("UnpauseMonitor"); 00923 ast_manager_unregister("Monitor"); 00924 ast_manager_unregister("StopMonitor"); 00925 ast_manager_unregister("ChangeMonitor"); 00926 ast_manager_unregister("PauseMonitor"); 00927 ast_manager_unregister("UnpauseMonitor"); 00928 00929 return 0; 00930 }
static int unpause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 894 of file res_monitor.c.
References do_pause_or_unpause().
Referenced by load_module().
00895 { 00896 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00897 }
static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 541 of file res_monitor.c.
References ast_monitor_unpause().
Referenced by load_module().
00542 { 00543 return ast_monitor_unpause(chan); 00544 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER , .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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 937 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 937 of file res_monitor.c.
ast_mutex_t monitorlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static] |
unsigned long seq = 0 [static] |
Definition at line 254 of file res_monitor.c.