#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 = "ac1f6a56484a8820659555499174e588" , .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 45 of file res_monitor.c.
#define LOCK_IF_NEEDED | ( | lock, | |||
needed | ) |
Value:
do { \ if (needed) \ ast_channel_lock(lock); \ } while(0)
Definition at line 248 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 253 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 869 of file res_monitor.c.
00870 { 00871 MONITOR_ACTION_PAUSE, 00872 MONITOR_ACTION_UNPAUSE 00873 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 950 of file res_monitor.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 950 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 562 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().
00563 { 00564 if (ast_strlen_zero(fname_base)) { 00565 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00566 return -1; 00567 } 00568 00569 LOCK_IF_NEEDED(chan, need_lock); 00570 00571 if (chan->monitor) { 00572 int directory = strchr(fname_base, '/') ? 1 : 0; 00573 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00574 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00575 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00576 int i, fd[2] = { -1, -1 }, doexit = 0; 00577 00578 /* before continuing, see if we're trying to rename the file to itself... */ 00579 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base); 00580 00581 /* try creating the directory just in case it doesn't exist */ 00582 if (directory) { 00583 char *name = ast_strdupa(tmpstring); 00584 ast_mkdir(dirname(name), 0777); 00585 } 00586 00587 /*! 00588 * \note We cannot just compare filenames, due to symlinks, relative 00589 * paths, and other possible filesystem issues. We could use 00590 * realpath(3), but its use is discouraged. However, if we try to 00591 * create the same file from two different paths, the second will 00592 * fail, and so we have our notification that the filenames point to 00593 * the same path. 00594 * 00595 * Remember, also, that we're using the basename of the file (i.e. 00596 * the file without the format suffix), so it does not already exist 00597 * and we aren't interfering with the recording itself. 00598 */ 00599 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00600 00601 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00602 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00603 if (fd[0] < 0) { 00604 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00605 } else { 00606 ast_debug(2, "No need to rename monitor filename to itself\n"); 00607 } 00608 doexit = 1; 00609 } 00610 00611 /* Cleanup temporary files */ 00612 for (i = 0; i < 2; i++) { 00613 if (fd[i] >= 0) { 00614 while (close(fd[i]) < 0 && errno == EINTR); 00615 } 00616 } 00617 unlink(tmpstring); 00618 /* if previous monitor file existed in a subdirectory, the directory will not be removed */ 00619 unlink(chan->monitor->filename_base); 00620 00621 if (doexit) { 00622 UNLOCK_IF_NEEDED(chan, need_lock); 00623 return 0; 00624 } 00625 00626 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00627 chan->monitor->filename_changed = 1; 00628 } else { 00629 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00630 } 00631 00632 UNLOCK_IF_NEEDED(chan, need_lock); 00633 00634 return 0; 00635 }
int AST_OPTIONAL_API_NAME() ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 531 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00532 { 00533 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00534 }
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 267 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().
00268 { 00269 LOCK_IF_NEEDED(chan, 1); 00270 if (!chan->monitor) { 00271 UNLOCK_IF_NEEDED(chan, 1); 00272 return -1; 00273 } 00274 chan->monitor->state = state; 00275 UNLOCK_IF_NEEDED(chan, 1); 00276 return 0; 00277 }
void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
int | turnon | |||
) |
Definition at line 863 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 290 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().
00292 { 00293 int res = 0; 00294 00295 LOCK_IF_NEEDED(chan, need_lock); 00296 00297 if (!(chan->monitor)) { 00298 struct ast_channel_monitor *monitor; 00299 char *channel_name, *p; 00300 00301 /* Create monitoring directory if needed */ 00302 ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); 00303 00304 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { 00305 UNLOCK_IF_NEEDED(chan, need_lock); 00306 return -1; 00307 } 00308 00309 /* Determine file names */ 00310 if (!ast_strlen_zero(fname_base)) { 00311 int directory = strchr(fname_base, '/') ? 1 : 0; 00312 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00313 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00314 00315 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", 00316 absolute, absolute_suffix, fname_base); 00317 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", 00318 absolute, absolute_suffix, fname_base); 00319 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", 00320 absolute, absolute_suffix, fname_base); 00321 00322 /* try creating the directory just in case it doesn't exist */ 00323 if (directory) { 00324 char *name = ast_strdupa(monitor->filename_base); 00325 ast_mkdir(dirname(name), 0777); 00326 } 00327 } else { 00328 ast_mutex_lock(&monitorlock); 00329 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00330 ast_config_AST_MONITOR_DIR, seq); 00331 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00332 ast_config_AST_MONITOR_DIR, seq); 00333 seq++; 00334 ast_mutex_unlock(&monitorlock); 00335 00336 /* Replace all '/' chars from the channel name with '-' chars. */ 00337 channel_name = ast_strdupa(chan->name); 00338 for (p = channel_name; (p = strchr(p, '/')); ) { 00339 *p = '-'; 00340 } 00341 00342 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00343 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00344 monitor->filename_changed = 1; 00345 } 00346 00347 monitor->stop = ast_monitor_stop; 00348 00349 /* Determine file format */ 00350 if (!ast_strlen_zero(format_spec)) { 00351 monitor->format = ast_strdup(format_spec); 00352 } else { 00353 monitor->format = ast_strdup("wav"); 00354 } 00355 00356 /* open files */ 00357 if (stream_action & X_REC_IN) { 00358 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) 00359 ast_filedelete(monitor->read_filename, NULL); 00360 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00361 monitor->format, NULL, 00362 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00363 ast_log(LOG_WARNING, "Could not create file %s\n", 00364 monitor->read_filename); 00365 ast_free(monitor); 00366 UNLOCK_IF_NEEDED(chan, need_lock); 00367 return -1; 00368 } 00369 } else 00370 monitor->read_stream = NULL; 00371 00372 if (stream_action & X_REC_OUT) { 00373 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00374 ast_filedelete(monitor->write_filename, NULL); 00375 } 00376 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00377 monitor->format, NULL, 00378 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00379 ast_log(LOG_WARNING, "Could not create file %s\n", 00380 monitor->write_filename); 00381 if (monitor->read_stream) { 00382 ast_closestream(monitor->read_stream); 00383 } 00384 ast_free(monitor); 00385 UNLOCK_IF_NEEDED(chan, need_lock); 00386 return -1; 00387 } 00388 } else 00389 monitor->write_stream = NULL; 00390 00391 chan->monitor = monitor; 00392 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00393 /* so we know this call has been monitored in case we need to bill for it or something */ 00394 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00395 00396 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStart", 00397 "Channel: %s\r\n" 00398 "Uniqueid: %s\r\n", 00399 chan->name, 00400 chan->uniqueid); 00401 } else { 00402 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name); 00403 res = -1; 00404 } 00405 00406 UNLOCK_IF_NEEDED(chan, need_lock); 00407 00408 return res; 00409 }
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 437 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().
00438 { 00439 int delfiles = 0; 00440 00441 LOCK_IF_NEEDED(chan, need_lock); 00442 00443 if (chan->monitor) { 00444 char filename[ FILENAME_MAX ]; 00445 00446 if (chan->monitor->read_stream) { 00447 ast_closestream(chan->monitor->read_stream); 00448 } 00449 if (chan->monitor->write_stream) { 00450 ast_closestream(chan->monitor->write_stream); 00451 } 00452 00453 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00454 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00455 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00456 if (ast_fileexists(filename, NULL, NULL) > 0) { 00457 ast_filedelete(filename, NULL); 00458 } 00459 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00460 } else { 00461 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00462 } 00463 00464 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00465 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00466 if (ast_fileexists(filename, NULL, NULL) > 0) { 00467 ast_filedelete(filename, NULL); 00468 } 00469 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00470 } else { 00471 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00472 } 00473 } 00474 00475 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00476 char tmp[1024]; 00477 char tmp2[1024]; 00478 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00479 char *fname_base = chan->monitor->filename_base; 00480 const char *execute, *execute_args; 00481 /* at this point, fname_base really is the full path */ 00482 00483 /* Set the execute application */ 00484 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00485 if (ast_strlen_zero(execute)) { 00486 #ifdef HAVE_SOXMIX 00487 execute = "nice -n 19 soxmix"; 00488 #else 00489 execute = "nice -n 19 sox -m"; 00490 #endif 00491 format = get_soxmix_format(format); 00492 delfiles = 1; 00493 } 00494 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00495 if (ast_strlen_zero(execute_args)) { 00496 execute_args = ""; 00497 } 00498 00499 snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &", 00500 execute, fname_base, format, fname_base, format, fname_base, format,execute_args); 00501 if (delfiles) { 00502 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */ 00503 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00504 } 00505 ast_debug(1,"monitor executing %s\n",tmp); 00506 if (ast_safe_system(tmp) == -1) 00507 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00508 } 00509 00510 ast_free(chan->monitor->format); 00511 ast_free(chan->monitor); 00512 chan->monitor = NULL; 00513 00514 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop", 00515 "Channel: %s\r\n" 00516 "Uniqueid: %s\r\n", 00517 chan->name, 00518 chan->uniqueid 00519 ); 00520 pbx_builtin_setvar_helper(chan, "MONITORED", NULL); 00521 } 00522 pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL); 00523 00524 UNLOCK_IF_NEEDED(chan, need_lock); 00525 00526 return 0; 00527 }
int AST_OPTIONAL_API_NAME() ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 537 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00538 { 00539 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00540 }
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 829 of file res_monitor.c.
References AMI_SUCCESS, 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().
00830 { 00831 struct ast_channel *c = NULL; 00832 const char *name = astman_get_header(m, "Channel"); 00833 const char *fname = astman_get_header(m, "File"); 00834 00835 if (ast_strlen_zero(name)) { 00836 astman_send_error(s, m, "No channel specified"); 00837 return AMI_SUCCESS; 00838 } 00839 00840 if (ast_strlen_zero(fname)) { 00841 astman_send_error(s, m, "No filename specified"); 00842 return AMI_SUCCESS; 00843 } 00844 00845 if (!(c = ast_channel_get_by_name(name))) { 00846 astman_send_error(s, m, "No such channel"); 00847 return AMI_SUCCESS; 00848 } 00849 00850 if (ast_monitor_change_fname(c, fname, 1)) { 00851 c = ast_channel_unref(c); 00852 astman_send_error(s, m, "Could not change monitored filename of channel"); 00853 return AMI_SUCCESS; 00854 } 00855 00856 c = ast_channel_unref(c); 00857 00858 astman_send_ack(s, m, "Changed monitor filename"); 00859 00860 return AMI_SUCCESS; 00861 }
static int change_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper function.
Definition at line 739 of file res_monitor.c.
References ast_monitor_change_fname().
Referenced by load_module().
00740 { 00741 return ast_monitor_change_fname(chan, data, 1); 00742 }
static int do_pause_or_unpause | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | action | |||
) | [static] |
Definition at line 875 of file res_monitor.c.
References AMI_SUCCESS, 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().
00876 { 00877 struct ast_channel *c = NULL; 00878 const char *name = astman_get_header(m, "Channel"); 00879 00880 if (ast_strlen_zero(name)) { 00881 astman_send_error(s, m, "No channel specified"); 00882 return AMI_SUCCESS; 00883 } 00884 00885 if (!(c = ast_channel_get_by_name(name))) { 00886 astman_send_error(s, m, "No such channel"); 00887 return AMI_SUCCESS; 00888 } 00889 00890 if (action == MONITOR_ACTION_PAUSE) { 00891 ast_monitor_pause(c); 00892 } else { 00893 ast_monitor_unpause(c); 00894 } 00895 00896 c = ast_channel_unref(c); 00897 00898 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00899 00900 return AMI_SUCCESS; 00901 }
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 418 of file res_monitor.c.
Referenced by ast_monitor_stop().
00419 { 00420 const char *res = format; 00421 00422 if (!strcasecmp(format,"ulaw")) 00423 res = "ul"; 00424 if (!strcasecmp(format,"alaw")) 00425 res = "al"; 00426 00427 return res; 00428 }
static int load_module | ( | void | ) | [static] |
Definition at line 913 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().
00914 { 00915 ast_register_application_xml("Monitor", start_monitor_exec); 00916 ast_register_application_xml("StopMonitor", stop_monitor_exec); 00917 ast_register_application_xml("ChangeMonitor", change_monitor_exec); 00918 ast_register_application_xml("PauseMonitor", pause_monitor_exec); 00919 ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec); 00920 ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action); 00921 ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action); 00922 ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action); 00923 ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action); 00924 ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action); 00925 00926 return AST_MODULE_LOAD_SUCCESS; 00927 }
static int pause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 903 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.
Referenced by load_module().
00904 { 00905 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00906 }
static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 543 of file res_monitor.c.
References ast_monitor_pause().
Referenced by load_module().
00544 { 00545 return ast_monitor_pause(chan); 00546 }
static int start_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Start monitoring a channel by manager connection.
Definition at line 745 of file res_monitor.c.
References AMI_SUCCESS, 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().
00746 { 00747 struct ast_channel *c = NULL; 00748 const char *name = astman_get_header(m, "Channel"); 00749 const char *fname = astman_get_header(m, "File"); 00750 const char *format = astman_get_header(m, "Format"); 00751 const char *mix = astman_get_header(m, "Mix"); 00752 char *d; 00753 00754 if (ast_strlen_zero(name)) { 00755 astman_send_error(s, m, "No channel specified"); 00756 return AMI_SUCCESS; 00757 } 00758 00759 if (!(c = ast_channel_get_by_name(name))) { 00760 astman_send_error(s, m, "No such channel"); 00761 return AMI_SUCCESS; 00762 } 00763 00764 if (ast_strlen_zero(fname)) { 00765 /* No filename specified, default to the channel name. */ 00766 ast_channel_lock(c); 00767 fname = ast_strdupa(c->name); 00768 ast_channel_unlock(c); 00769 00770 /* Replace all '/' chars from the channel name with '-' chars. */ 00771 for (d = (char *) fname; (d = strchr(d, '/')); ) { 00772 *d = '-'; 00773 } 00774 } 00775 00776 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00777 if (ast_monitor_change_fname(c, fname, 1)) { 00778 astman_send_error(s, m, "Could not start monitoring channel"); 00779 c = ast_channel_unref(c); 00780 return AMI_SUCCESS; 00781 } 00782 } 00783 00784 if (ast_true(mix)) { 00785 ast_channel_lock(c); 00786 ast_monitor_setjoinfiles(c, 1); 00787 ast_channel_unlock(c); 00788 } 00789 00790 c = ast_channel_unref(c); 00791 00792 astman_send_ack(s, m, "Started monitoring channel"); 00793 00794 return AMI_SUCCESS; 00795 }
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 645 of file res_monitor.c.
References args, AST_APP_ARG, ast_cdr_alloc(), ast_cdr_setuserfield(), ast_channel_lock, ast_channel_unlock, 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().
00646 { 00647 char *arg; 00648 char *options; 00649 char *delay; 00650 char *urlprefix = NULL; 00651 char tmp[256]; 00652 int stream_action = X_REC_IN | X_REC_OUT; 00653 int joinfiles = 0; 00654 int waitforbridge = 0; 00655 int res = 0; 00656 char *parse; 00657 AST_DECLARE_APP_ARGS(args, 00658 AST_APP_ARG(format); 00659 AST_APP_ARG(fname_base); 00660 AST_APP_ARG(options); 00661 ); 00662 00663 /* Parse arguments. */ 00664 if (ast_strlen_zero(data)) { 00665 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00666 return 0; 00667 } 00668 00669 parse = ast_strdupa(data); 00670 AST_STANDARD_APP_ARGS(args, parse); 00671 00672 if (!ast_strlen_zero(args.options)) { 00673 if (strchr(args.options, 'm')) 00674 stream_action |= X_JOIN; 00675 if (strchr(args.options, 'b')) 00676 waitforbridge = 1; 00677 if (strchr(args.options, 'i')) 00678 stream_action &= ~X_REC_IN; 00679 if (strchr(args.options, 'o')) 00680 stream_action &= ~X_REC_OUT; 00681 } 00682 00683 arg = strchr(args.format, ':'); 00684 if (arg) { 00685 *arg++ = 0; 00686 urlprefix = arg; 00687 } 00688 00689 if (!ast_strlen_zero(urlprefix) && !ast_strlen_zero(args.fname_base)) { 00690 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00691 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00692 ast_channel_lock(chan); 00693 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) { 00694 ast_channel_unlock(chan); 00695 return -1; 00696 } 00697 ast_cdr_setuserfield(chan, tmp); 00698 ast_channel_unlock(chan); 00699 } 00700 if (waitforbridge) { 00701 /* We must remove the "b" option if listed. In principle none of 00702 the following could give NULL results, but we check just to 00703 be pedantic. Reconstructing with checks for 'm' option does not 00704 work if we end up adding more options than 'm' in the future. */ 00705 delay = ast_strdupa(data); 00706 options = strrchr(delay, ','); 00707 if (options) { 00708 arg = strchr(options, 'b'); 00709 if (arg) { 00710 *arg = 'X'; 00711 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00712 } 00713 } 00714 return 0; 00715 } 00716 00717 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00718 if (res < 0) 00719 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00720 00721 if (stream_action & X_JOIN) { 00722 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00723 joinfiles = 1; 00724 else 00725 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00726 } 00727 ast_monitor_setjoinfiles(chan, joinfiles); 00728 00729 return res; 00730 }
static int stop_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 798 of file res_monitor.c.
References AMI_SUCCESS, 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().
00799 { 00800 struct ast_channel *c = NULL; 00801 const char *name = astman_get_header(m, "Channel"); 00802 int res; 00803 00804 if (ast_strlen_zero(name)) { 00805 astman_send_error(s, m, "No channel specified"); 00806 return AMI_SUCCESS; 00807 } 00808 00809 if (!(c = ast_channel_get_by_name(name))) { 00810 astman_send_error(s, m, "No such channel"); 00811 return AMI_SUCCESS; 00812 } 00813 00814 res = ast_monitor_stop(c, 1); 00815 00816 c = ast_channel_unref(c); 00817 00818 if (res) { 00819 astman_send_error(s, m, "Could not stop monitoring channel"); 00820 return AMI_SUCCESS; 00821 } 00822 00823 astman_send_ack(s, m, "Stopped monitoring channel"); 00824 00825 return AMI_SUCCESS; 00826 }
static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper function.
Definition at line 733 of file res_monitor.c.
References ast_monitor_stop().
Referenced by load_module().
00734 { 00735 return ast_monitor_stop(chan, 1); 00736 }
static int unload_module | ( | void | ) | [static] |
Definition at line 929 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00930 { 00931 ast_unregister_application("Monitor"); 00932 ast_unregister_application("StopMonitor"); 00933 ast_unregister_application("ChangeMonitor"); 00934 ast_unregister_application("PauseMonitor"); 00935 ast_unregister_application("UnpauseMonitor"); 00936 ast_manager_unregister("Monitor"); 00937 ast_manager_unregister("StopMonitor"); 00938 ast_manager_unregister("ChangeMonitor"); 00939 ast_manager_unregister("PauseMonitor"); 00940 ast_manager_unregister("UnpauseMonitor"); 00941 00942 return 0; 00943 }
static int unpause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 908 of file res_monitor.c.
References do_pause_or_unpause().
Referenced by load_module().
00909 { 00910 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00911 }
static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
const char * | data | |||
) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 549 of file res_monitor.c.
References ast_monitor_unpause().
Referenced by load_module().
00550 { 00551 return ast_monitor_unpause(chan); 00552 }
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 = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 950 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 950 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 258 of file res_monitor.c.