#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 | 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_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock) |
Change monitored filename of channel. | |
int | 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_monitor_setjoinfiles (struct ast_channel *chan, int turnon) |
int | 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_monitor_stop (struct ast_channel *chan, int need_lock) |
Stop monitoring channel. | |
int | 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, void *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, void *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, void *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, void *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, void *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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static char | change_monitor_action_help [] |
static char * | changemonitor_descrip |
static char * | changemonitor_synopsis = "Change monitoring filename of a channel" |
static char * | monitor_descrip |
static char * | monitor_synopsis = "Monitor a channel" |
static ast_mutex_t | monitorlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static char | pause_monitor_action_help [] |
static char * | pausemonitor_descrip |
static char * | pausemonitor_synopsis = "Pause monitoring of a channel" |
static unsigned long | seq = 0 |
static char | start_monitor_action_help [] |
static char | stop_monitor_action_help [] |
static char * | stopmonitor_descrip |
static char * | stopmonitor_synopsis = "Stop monitoring a channel" |
static char | unpause_monitor_action_help [] |
static char * | unpausemonitor_descrip |
static char * | unpausemonitor_synopsis = "Unpause monitoring of a channel" |
Definition in file res_monitor.c.
#define LOCK_IF_NEEDED | ( | lock, | |||
needed | ) |
Value:
do { \ if (needed) \ ast_channel_lock(lock); \ } while(0)
Definition at line 49 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 54 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 725 of file res_monitor.c.
00726 { 00727 MONITOR_ACTION_PAUSE, 00728 MONITOR_ACTION_UNPAUSE 00729 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 816 of file res_monitor.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 816 of file res_monitor.c.
int 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 416 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(), chan, 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().
00417 { 00418 if (ast_strlen_zero(fname_base)) { 00419 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00420 return -1; 00421 } 00422 00423 LOCK_IF_NEEDED(chan, need_lock); 00424 00425 if (chan->monitor) { 00426 int directory = strchr(fname_base, '/') ? 1 : 0; 00427 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00428 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00429 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00430 int i, fd[2] = { -1, -1 }, doexit = 0; 00431 00432 /* before continuing, see if we're trying to rename the file to itself... */ 00433 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base); 00434 00435 /* try creating the directory just in case it doesn't exist */ 00436 if (directory) { 00437 char *name = ast_strdupa(tmpstring); 00438 ast_mkdir(dirname(name), 0777); 00439 } 00440 00441 /*!\note We cannot just compare filenames, due to symlinks, relative 00442 * paths, and other possible filesystem issues. We could use 00443 * realpath(3), but its use is discouraged. However, if we try to 00444 * create the same file from two different paths, the second will 00445 * fail, and so we have our notification that the filenames point to 00446 * the same path. 00447 * 00448 * Remember, also, that we're using the basename of the file (i.e. 00449 * the file without the format suffix), so it does not already exist 00450 * and we aren't interfering with the recording itself. 00451 */ 00452 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00453 00454 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00455 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00456 if (fd[0] < 0) { 00457 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00458 } else { 00459 ast_debug(2, "No need to rename monitor filename to itself\n"); 00460 } 00461 doexit = 1; 00462 } 00463 00464 /* Cleanup temporary files */ 00465 for (i = 0; i < 2; i++) { 00466 if (fd[i] >= 0) { 00467 while (close(fd[i]) < 0 && errno == EINTR); 00468 } 00469 } 00470 unlink(tmpstring); 00471 /* if previous monitor file existed in a subdirectory, the directory will not be removed */ 00472 unlink(chan->monitor->filename_base); 00473 00474 if (doexit) { 00475 UNLOCK_IF_NEEDED(chan, need_lock); 00476 return 0; 00477 } 00478 00479 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00480 chan->monitor->filename_changed = 1; 00481 } else { 00482 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00483 } 00484 00485 UNLOCK_IF_NEEDED(chan, need_lock); 00486 00487 return 0; 00488 }
int ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 385 of file res_monitor.c.
References AST_MONITOR_PAUSED, ast_monitor_set_state(), and chan.
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00386 { 00387 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00388 }
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 124 of file res_monitor.c.
References chan, 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().
00125 { 00126 LOCK_IF_NEEDED(chan, 1); 00127 if (!chan->monitor) { 00128 UNLOCK_IF_NEEDED(chan, 1); 00129 return -1; 00130 } 00131 chan->monitor->state = state; 00132 UNLOCK_IF_NEEDED(chan, 1); 00133 return 0; 00134 }
void ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
int | turnon | |||
) |
Definition at line 719 of file res_monitor.c.
References chan, ast_channel_monitor::joinfiles, and ast_channel::monitor.
Referenced by __agent_start_monitoring(), start_monitor_action(), and start_monitor_exec().
int 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 147 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_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(), chan, EVENT_FLAG_CALL, FILENAME_MAX, LOCK_IF_NEEDED, LOG_WARNING, manager_event, 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().
00149 { 00150 int res = 0; 00151 00152 LOCK_IF_NEEDED(chan, need_lock); 00153 00154 if (!(chan->monitor)) { 00155 struct ast_channel_monitor *monitor; 00156 char *channel_name, *p; 00157 00158 /* Create monitoring directory if needed */ 00159 ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); 00160 00161 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { 00162 UNLOCK_IF_NEEDED(chan, need_lock); 00163 return -1; 00164 } 00165 00166 /* Determine file names */ 00167 if (!ast_strlen_zero(fname_base)) { 00168 int directory = strchr(fname_base, '/') ? 1 : 0; 00169 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00170 const char *absolute_suffix = *fname_base == '/' ? "" : "/"; 00171 00172 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", 00173 absolute, absolute_suffix, fname_base); 00174 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", 00175 absolute, absolute_suffix, fname_base); 00176 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", 00177 absolute, absolute_suffix, fname_base); 00178 00179 /* try creating the directory just in case it doesn't exist */ 00180 if (directory) { 00181 char *name = ast_strdupa(monitor->filename_base); 00182 ast_mkdir(dirname(name), 0777); 00183 } 00184 } else { 00185 ast_mutex_lock(&monitorlock); 00186 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00187 ast_config_AST_MONITOR_DIR, seq); 00188 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00189 ast_config_AST_MONITOR_DIR, seq); 00190 seq++; 00191 ast_mutex_unlock(&monitorlock); 00192 00193 channel_name = ast_strdupa(chan->name); 00194 while ((p = strchr(channel_name, '/'))) { 00195 *p = '-'; 00196 } 00197 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00198 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00199 monitor->filename_changed = 1; 00200 } 00201 00202 monitor->stop = ast_monitor_stop; 00203 00204 /* Determine file format */ 00205 if (!ast_strlen_zero(format_spec)) { 00206 monitor->format = ast_strdup(format_spec); 00207 } else { 00208 monitor->format = ast_strdup("wav"); 00209 } 00210 00211 /* open files */ 00212 if (stream_action & X_REC_IN) { 00213 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) 00214 ast_filedelete(monitor->read_filename, NULL); 00215 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00216 monitor->format, NULL, 00217 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00218 ast_log(LOG_WARNING, "Could not create file %s\n", 00219 monitor->read_filename); 00220 ast_free(monitor); 00221 UNLOCK_IF_NEEDED(chan, need_lock); 00222 return -1; 00223 } 00224 } else 00225 monitor->read_stream = NULL; 00226 00227 if (stream_action & X_REC_OUT) { 00228 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00229 ast_filedelete(monitor->write_filename, NULL); 00230 } 00231 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00232 monitor->format, NULL, 00233 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00234 ast_log(LOG_WARNING, "Could not create file %s\n", 00235 monitor->write_filename); 00236 ast_closestream(monitor->read_stream); 00237 ast_free(monitor); 00238 UNLOCK_IF_NEEDED(chan, need_lock); 00239 return -1; 00240 } 00241 } else 00242 monitor->write_stream = NULL; 00243 00244 chan->monitor = monitor; 00245 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00246 /* so we know this call has been monitored in case we need to bill for it or something */ 00247 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00248 00249 manager_event(EVENT_FLAG_CALL, "MonitorStart", 00250 "Channel: %s\r\n" 00251 "Uniqueid: %s\r\n", 00252 chan->name, 00253 chan->uniqueid 00254 ); 00255 } else { 00256 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name); 00257 res = -1; 00258 } 00259 00260 UNLOCK_IF_NEEDED(chan, need_lock); 00261 00262 return res; 00263 }
int 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 291 of file res_monitor.c.
References ast_closestream(), ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), ast_safe_system(), ast_strlen_zero(), chan, 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, 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().
00292 { 00293 int delfiles = 0; 00294 00295 LOCK_IF_NEEDED(chan, need_lock); 00296 00297 if (chan->monitor) { 00298 char filename[ FILENAME_MAX ]; 00299 00300 if (chan->monitor->read_stream) { 00301 ast_closestream(chan->monitor->read_stream); 00302 } 00303 if (chan->monitor->write_stream) { 00304 ast_closestream(chan->monitor->write_stream); 00305 } 00306 00307 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00308 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00309 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00310 if (ast_fileexists(filename, NULL, NULL) > 0) { 00311 ast_filedelete(filename, NULL); 00312 } 00313 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00314 } else { 00315 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00316 } 00317 00318 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00319 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00320 if (ast_fileexists(filename, NULL, NULL) > 0) { 00321 ast_filedelete(filename, NULL); 00322 } 00323 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00324 } else { 00325 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00326 } 00327 } 00328 00329 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00330 char tmp[1024]; 00331 char tmp2[1024]; 00332 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00333 char *fname_base = chan->monitor->filename_base; 00334 const char *execute, *execute_args; 00335 /* at this point, fname_base really is the full path */ 00336 00337 /* Set the execute application */ 00338 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00339 if (ast_strlen_zero(execute)) { 00340 #ifdef HAVE_SOXMIX 00341 execute = "nice -n 19 soxmix"; 00342 #else 00343 execute = "nice -n 19 sox -m"; 00344 #endif 00345 format = get_soxmix_format(format); 00346 delfiles = 1; 00347 } 00348 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00349 if (ast_strlen_zero(execute_args)) { 00350 execute_args = ""; 00351 } 00352 00353 snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &", 00354 execute, fname_base, format, fname_base, format, fname_base, format,execute_args); 00355 if (delfiles) { 00356 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */ 00357 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00358 } 00359 ast_debug(1,"monitor executing %s\n",tmp); 00360 if (ast_safe_system(tmp) == -1) 00361 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00362 } 00363 00364 ast_free(chan->monitor->format); 00365 ast_free(chan->monitor); 00366 chan->monitor = NULL; 00367 00368 manager_event(EVENT_FLAG_CALL, "MonitorStop", 00369 "Channel: %s\r\n" 00370 "Uniqueid: %s\r\n", 00371 chan->name, 00372 chan->uniqueid 00373 ); 00374 pbx_builtin_setvar_helper(chan, "MONITORED", NULL); 00375 } 00376 pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL); 00377 00378 UNLOCK_IF_NEEDED(chan, need_lock); 00379 00380 return 0; 00381 }
int ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 391 of file res_monitor.c.
References AST_MONITOR_RUNNING, ast_monitor_set_state(), and chan.
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00392 { 00393 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00394 }
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 691 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_change_fname(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, and s.
Referenced by load_module().
00692 { 00693 struct ast_channel *c = NULL; 00694 const char *name = astman_get_header(m, "Channel"); 00695 const char *fname = astman_get_header(m, "File"); 00696 if (ast_strlen_zero(name)) { 00697 astman_send_error(s, m, "No channel specified"); 00698 return 0; 00699 } 00700 if (ast_strlen_zero(fname)) { 00701 astman_send_error(s, m, "No filename specified"); 00702 return 0; 00703 } 00704 c = ast_get_channel_by_name_locked(name); 00705 if (!c) { 00706 astman_send_error(s, m, "No such channel"); 00707 return 0; 00708 } 00709 if (ast_monitor_change_fname(c, fname, 1)) { 00710 astman_send_error(s, m, "Could not change monitored filename of channel"); 00711 ast_channel_unlock(c); 00712 return 0; 00713 } 00714 ast_channel_unlock(c); 00715 astman_send_ack(s, m, "Changed monitor filename"); 00716 return 0; 00717 }
static int change_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper function.
Definition at line 588 of file res_monitor.c.
References ast_monitor_change_fname(), and chan.
Referenced by load_module().
00589 { 00590 return ast_monitor_change_fname(chan, (const char*)data, 1); 00591 }
static int do_pause_or_unpause | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | action | |||
) | [static] |
Definition at line 731 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_pause(), ast_monitor_unpause(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), MONITOR_ACTION_PAUSE, name, and s.
Referenced by pause_monitor_action(), and unpause_monitor_action().
00732 { 00733 struct ast_channel *c = NULL; 00734 const char *name = astman_get_header(m, "Channel"); 00735 00736 if (ast_strlen_zero(name)) { 00737 astman_send_error(s, m, "No channel specified"); 00738 return -1; 00739 } 00740 00741 c = ast_get_channel_by_name_locked(name); 00742 if (!c) { 00743 astman_send_error(s, m, "No such channel"); 00744 return -1; 00745 } 00746 00747 if (action == MONITOR_ACTION_PAUSE) 00748 ast_monitor_pause(c); 00749 else 00750 ast_monitor_unpause(c); 00751 00752 ast_channel_unlock(c); 00753 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00754 return 0; 00755 }
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 272 of file res_monitor.c.
Referenced by ast_monitor_stop().
00273 { 00274 const char *res = format; 00275 00276 if (!strcasecmp(format,"ulaw")) 00277 res = "ul"; 00278 if (!strcasecmp(format,"alaw")) 00279 res = "al"; 00280 00281 return res; 00282 }
static int load_module | ( | void | ) | [static] |
Definition at line 780 of file res_monitor.c.
References ast_manager_register2(), AST_MODULE_LOAD_SUCCESS, ast_register_application, 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().
00781 { 00782 ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip); 00783 ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip); 00784 ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip); 00785 ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip); 00786 ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip); 00787 ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help); 00788 ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help); 00789 ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help); 00790 ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help); 00791 ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help); 00792 00793 return AST_MODULE_LOAD_SUCCESS; 00794 }
static int pause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 763 of file res_monitor.c.
References do_pause_or_unpause(), MONITOR_ACTION_PAUSE, and s.
Referenced by load_module().
00764 { 00765 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00766 }
static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 397 of file res_monitor.c.
References ast_monitor_pause(), and chan.
Referenced by load_module().
00398 { 00399 return ast_monitor_pause(chan); 00400 }
static int start_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Start monitoring a channel by manager connection.
Definition at line 608 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), 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, s, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00609 { 00610 struct ast_channel *c = NULL; 00611 const char *name = astman_get_header(m, "Channel"); 00612 const char *fname = astman_get_header(m, "File"); 00613 const char *format = astman_get_header(m, "Format"); 00614 const char *mix = astman_get_header(m, "Mix"); 00615 char *d; 00616 00617 if (ast_strlen_zero(name)) { 00618 astman_send_error(s, m, "No channel specified"); 00619 return 0; 00620 } 00621 c = ast_get_channel_by_name_locked(name); 00622 if (!c) { 00623 astman_send_error(s, m, "No such channel"); 00624 return 0; 00625 } 00626 00627 if (ast_strlen_zero(fname)) { 00628 /* No filename base specified, default to channel name as per CLI */ 00629 fname = ast_strdupa(c->name); 00630 /* Channels have the format technology/channel_name - have to replace that / */ 00631 if ((d = strchr(fname, '/'))) 00632 *d = '-'; 00633 } 00634 00635 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00636 if (ast_monitor_change_fname(c, fname, 1)) { 00637 astman_send_error(s, m, "Could not start monitoring channel"); 00638 ast_channel_unlock(c); 00639 return 0; 00640 } 00641 } 00642 00643 if (ast_true(mix)) { 00644 ast_monitor_setjoinfiles(c, 1); 00645 } 00646 00647 ast_channel_unlock(c); 00648 astman_send_ack(s, m, "Started monitoring channel"); 00649 return 0; 00650 }
static int start_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Start monitor.
chan | ||
data | arguments passed fname|options |
0 | on success. | |
-1 | on failure. |
Definition at line 498 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, chan, format, ast_channel_monitor::joinfiles, LOG_ERROR, LOG_WARNING, parse(), pbx_builtin_setvar_helper(), urlprefix, X_JOIN, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00499 { 00500 char *arg = NULL; 00501 char *options = NULL; 00502 char *delay = NULL; 00503 char *urlprefix = NULL; 00504 char tmp[256]; 00505 int stream_action = X_REC_IN | X_REC_OUT; 00506 int joinfiles = 0; 00507 int waitforbridge = 0; 00508 int res = 0; 00509 char *parse; 00510 AST_DECLARE_APP_ARGS(args, 00511 AST_APP_ARG(format); 00512 AST_APP_ARG(fname_base); 00513 AST_APP_ARG(options); 00514 ); 00515 00516 /* Parse arguments. */ 00517 if (ast_strlen_zero((char*)data)) { 00518 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00519 return 0; 00520 } 00521 00522 parse = ast_strdupa((char*)data); 00523 AST_STANDARD_APP_ARGS(args, parse); 00524 00525 if (!ast_strlen_zero(args.options)) { 00526 if (strchr(args.options, 'm')) 00527 stream_action |= X_JOIN; 00528 if (strchr(args.options, 'b')) 00529 waitforbridge = 1; 00530 if (strchr(args.options, 'i')) 00531 stream_action &= ~X_REC_IN; 00532 if (strchr(args.options, 'o')) 00533 stream_action &= ~X_REC_OUT; 00534 } 00535 00536 arg = strchr(args.format, ':'); 00537 if (arg) { 00538 *arg++ = 0; 00539 urlprefix = arg; 00540 } 00541 00542 if (urlprefix) { 00543 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00544 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00545 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) 00546 return -1; 00547 ast_cdr_setuserfield(chan, tmp); 00548 } 00549 if (waitforbridge) { 00550 /* We must remove the "b" option if listed. In principle none of 00551 the following could give NULL results, but we check just to 00552 be pedantic. Reconstructing with checks for 'm' option does not 00553 work if we end up adding more options than 'm' in the future. */ 00554 delay = ast_strdupa(data); 00555 options = strrchr(delay, ','); 00556 if (options) { 00557 arg = strchr(options, 'b'); 00558 if (arg) { 00559 *arg = 'X'; 00560 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00561 } 00562 } 00563 return 0; 00564 } 00565 00566 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00567 if (res < 0) 00568 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00569 00570 if (stream_action & X_JOIN) { 00571 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00572 joinfiles = 1; 00573 else 00574 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00575 } 00576 ast_monitor_setjoinfiles(chan, joinfiles); 00577 00578 return res; 00579 }
static int stop_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 658 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_stop(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, and s.
Referenced by load_module().
00659 { 00660 struct ast_channel *c = NULL; 00661 const char *name = astman_get_header(m, "Channel"); 00662 int res; 00663 if (ast_strlen_zero(name)) { 00664 astman_send_error(s, m, "No channel specified"); 00665 return 0; 00666 } 00667 c = ast_get_channel_by_name_locked(name); 00668 if (!c) { 00669 astman_send_error(s, m, "No such channel"); 00670 return 0; 00671 } 00672 res = ast_monitor_stop(c, 1); 00673 ast_channel_unlock(c); 00674 if (res) { 00675 astman_send_error(s, m, "Could not stop monitoring channel"); 00676 return 0; 00677 } 00678 astman_send_ack(s, m, "Stopped monitoring channel"); 00679 return 0; 00680 }
static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper function.
Definition at line 582 of file res_monitor.c.
References ast_monitor_stop(), and chan.
Referenced by load_module().
00583 { 00584 return ast_monitor_stop(chan, 1); 00585 }
static int unload_module | ( | void | ) | [static] |
Definition at line 796 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00797 { 00798 ast_unregister_application("Monitor"); 00799 ast_unregister_application("StopMonitor"); 00800 ast_unregister_application("ChangeMonitor"); 00801 ast_unregister_application("PauseMonitor"); 00802 ast_unregister_application("UnpauseMonitor"); 00803 ast_manager_unregister("Monitor"); 00804 ast_manager_unregister("StopMonitor"); 00805 ast_manager_unregister("ChangeMonitor"); 00806 ast_manager_unregister("PauseMonitor"); 00807 ast_manager_unregister("UnpauseMonitor"); 00808 00809 return 0; 00810 }
static int unpause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 774 of file res_monitor.c.
References do_pause_or_unpause(), and s.
Referenced by load_module().
00775 { 00776 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00777 }
static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 403 of file res_monitor.c.
References ast_monitor_unpause(), and chan.
Referenced by load_module().
00404 { 00405 return ast_monitor_unpause(chan); 00406 }
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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 816 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 816 of file res_monitor.c.
char change_monitor_action_help[] [static] |
Definition at line 682 of file res_monitor.c.
char* changemonitor_descrip [static] |
Initial value:
" ChangeMonitor(filename_base):\n" "Changes monitoring filename of a channel. Has no effect if the channel is not monitored.\n" "The argument is the new filename base to use for monitoring this channel.\n"
Definition at line 102 of file res_monitor.c.
char* changemonitor_synopsis = "Change monitoring filename of a channel" [static] |
Definition at line 100 of file res_monitor.c.
char* monitor_descrip [static] |
Definition at line 63 of file res_monitor.c.
char* monitor_synopsis = "Monitor a channel" [static] |
Definition at line 61 of file res_monitor.c.
ast_mutex_t monitorlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
char pause_monitor_action_help[] [static] |
Initial value:
"Description: The 'PauseMonitor' action may be used to temporarily stop the\n" " recording of a channel. The following parameters may\n" " be used to control this:\n" " Channel - Required. Used to specify the channel to record.\n"
Definition at line 757 of file res_monitor.c.
char* pausemonitor_descrip [static] |
Initial value:
" PauseMonitor():\n" "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n"
Definition at line 108 of file res_monitor.c.
char* pausemonitor_synopsis = "Pause monitoring of a channel" [static] |
Definition at line 106 of file res_monitor.c.
unsigned long seq = 0 [static] |
Definition at line 59 of file res_monitor.c.
char start_monitor_action_help[] [static] |
Definition at line 593 of file res_monitor.c.
char stop_monitor_action_help[] [static] |
Initial value:
"Description: The 'StopMonitor' action may be used to end a previously\n" " started 'Monitor' action. The only parameter is 'Channel', the name\n" " of the channel monitored.\n"
Definition at line 652 of file res_monitor.c.
char* stopmonitor_descrip [static] |
Initial value:
" StopMonitor():\n" "Stops monitoring a channel. Has no effect if the channel is not monitored\n"
Definition at line 97 of file res_monitor.c.
char* stopmonitor_synopsis = "Stop monitoring a channel" [static] |
Definition at line 95 of file res_monitor.c.
char unpause_monitor_action_help[] [static] |
Initial value:
"Description: The 'UnpauseMonitor' action may be used to re-enable recording\n" " of a channel after calling PauseMonitor. The following parameters may\n" " be used to control this:\n" " Channel - Required. Used to specify the channel to record.\n"
Definition at line 768 of file res_monitor.c.
char* unpausemonitor_descrip [static] |
Initial value:
" UnpauseMonitor():\n" "Unpauses monitoring of a channel on which monitoring had\n" "previously been paused with PauseMonitor.\n"
Definition at line 113 of file res_monitor.c.
char* unpausemonitor_synopsis = "Unpause monitoring of a channel" [static] |
Definition at line 111 of file res_monitor.c.