PBX channel monitoring. More...
#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" |
PBX channel monitoring.
Definition in file res_monitor.c.
| #define LOCK_IF_NEEDED | ( | lock, | |||
| needed | ) |
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 | ) |
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 721 of file res_monitor.c.
00722 { 00723 MONITOR_ACTION_PAUSE, 00724 MONITOR_ACTION_UNPAUSE 00725 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 812 of file res_monitor.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 812 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. |
Remember, also, that we're using the basename of the file (i.e. the file without the format suffix), so it does not already exist and we aren't interfering with the recording itself.
Definition at line 414 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, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00415 { 00416 if (ast_strlen_zero(fname_base)) { 00417 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00418 return -1; 00419 } 00420 00421 LOCK_IF_NEEDED(chan, need_lock); 00422 00423 if (chan->monitor) { 00424 int directory = strchr(fname_base, '/') ? 1 : 0; 00425 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00426 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00427 int i, fd[2] = { -1, -1 }, doexit = 0; 00428 00429 /* before continuing, see if we're trying to rename the file to itself... */ 00430 snprintf(tmpstring, sizeof(tmpstring), "%s/%s", absolute, fname_base); 00431 00432 /*!\note We cannot just compare filenames, due to symlinks, relative 00433 * paths, and other possible filesystem issues. We could use 00434 * realpath(3), but its use is discouraged. However, if we try to 00435 * create the same file from two different paths, the second will 00436 * fail, and so we have our notification that the filenames point to 00437 * the same path. 00438 * 00439 * Remember, also, that we're using the basename of the file (i.e. 00440 * the file without the format suffix), so it does not already exist 00441 * and we aren't interfering with the recording itself. 00442 */ 00443 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00444 00445 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00446 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00447 if (fd[0] < 0) { 00448 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00449 } else { 00450 ast_debug(2, "No need to rename monitor filename to itself\n"); 00451 } 00452 doexit = 1; 00453 } 00454 00455 /* Cleanup temporary files */ 00456 for (i = 0; i < 2; i++) { 00457 if (fd[i] >= 0) { 00458 while (close(fd[i]) < 0 && errno == EINTR); 00459 } 00460 } 00461 unlink(tmpstring); 00462 unlink(chan->monitor->filename_base); 00463 00464 if (doexit) { 00465 UNLOCK_IF_NEEDED(chan, need_lock); 00466 return 0; 00467 } 00468 00469 /* try creating the directory just in case it doesn't exist */ 00470 if (directory) { 00471 char *name = ast_strdupa(fname_base); 00472 ast_mkdir(dirname(name), 0777); 00473 } 00474 00475 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00476 chan->monitor->filename_changed = 1; 00477 } else { 00478 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00479 } 00480 00481 UNLOCK_IF_NEEDED(chan, need_lock); 00482 00483 return 0; 00484 }
| int ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 383 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00384 { 00385 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00386 }
| static int ast_monitor_set_state | ( | struct ast_channel * | chan, | |
| int | state | |||
| ) | [static] |
Change state of monitored channel.
| 0 | on success. | |
| -1 | on failure. |
Definition at line 124 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().
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 715 of file res_monitor.c.
References ast_channel_monitor::joinfiles, and ast_channel::monitor.
Referenced by __agent_start_monitoring(), start_monitor_action(), start_monitor_exec(), and try_calling().
| int ast_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(), EVENT_FLAG_CALL, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, ast_channel_monitor::format, LOCK_IF_NEEDED, LOG_WARNING, manager_event, monitor, ast_channel::monitor, monitorlock, name, pbx_builtin_setvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, ast_channel_monitor::stop, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, ast_channel_monitor::write_stream, X_REC_IN, and X_REC_OUT.
Referenced by __agent_start_monitoring(), start_monitor_action(), start_monitor_exec(), and try_calling().
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 00171 snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in", 00172 absolute, fname_base); 00173 snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out", 00174 absolute, fname_base); 00175 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%s", 00176 absolute, fname_base); 00177 00178 /* try creating the directory just in case it doesn't exist */ 00179 if (directory) { 00180 char *name = ast_strdupa(monitor->filename_base); 00181 ast_mkdir(dirname(name), 0777); 00182 } 00183 } else { 00184 ast_mutex_lock(&monitorlock); 00185 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00186 ast_config_AST_MONITOR_DIR, seq); 00187 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00188 ast_config_AST_MONITOR_DIR, seq); 00189 seq++; 00190 ast_mutex_unlock(&monitorlock); 00191 00192 channel_name = ast_strdupa(chan->name); 00193 while ((p = strchr(channel_name, '/'))) { 00194 *p = '-'; 00195 } 00196 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00197 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00198 monitor->filename_changed = 1; 00199 } 00200 00201 monitor->stop = ast_monitor_stop; 00202 00203 /* Determine file format */ 00204 if (!ast_strlen_zero(format_spec)) { 00205 monitor->format = ast_strdup(format_spec); 00206 } else { 00207 monitor->format = ast_strdup("wav"); 00208 } 00209 00210 /* open files */ 00211 if (stream_action & X_REC_IN) { 00212 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) 00213 ast_filedelete(monitor->read_filename, NULL); 00214 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00215 monitor->format, NULL, 00216 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00217 ast_log(LOG_WARNING, "Could not create file %s\n", 00218 monitor->read_filename); 00219 ast_free(monitor); 00220 UNLOCK_IF_NEEDED(chan, need_lock); 00221 return -1; 00222 } 00223 } else 00224 monitor->read_stream = NULL; 00225 00226 if (stream_action & X_REC_OUT) { 00227 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00228 ast_filedelete(monitor->write_filename, NULL); 00229 } 00230 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00231 monitor->format, NULL, 00232 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00233 ast_log(LOG_WARNING, "Could not create file %s\n", 00234 monitor->write_filename); 00235 ast_closestream(monitor->read_stream); 00236 ast_free(monitor); 00237 UNLOCK_IF_NEEDED(chan, need_lock); 00238 return -1; 00239 } 00240 } else 00241 monitor->write_stream = NULL; 00242 00243 chan->monitor = monitor; 00244 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00245 /* so we know this call has been monitored in case we need to bill for it or something */ 00246 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00247 00248 manager_event(EVENT_FLAG_CALL, "MonitorStart", 00249 "Channel: %s\r\n" 00250 "Uniqueid: %s\r\n", 00251 chan->name, 00252 chan->uniqueid 00253 ); 00254 } else { 00255 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name); 00256 res = -1; 00257 } 00258 00259 UNLOCK_IF_NEEDED(chan, need_lock); 00260 00261 return res; 00262 }
| 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 290 of file res_monitor.c.
References ast_closestream(), ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, ast_filedelete(), ast_fileexists(), ast_filerename(), ast_free, ast_log(), ast_safe_system(), ast_strlen_zero(), dir, EVENT_FLAG_CALL, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, format, ast_channel_monitor::format, get_soxmix_format(), ast_channel_monitor::joinfiles, LOCK_IF_NEEDED, LOG_WARNING, manager_event, ast_channel::monitor, name, pbx_builtin_getvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, 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().
00291 { 00292 int delfiles = 0; 00293 00294 LOCK_IF_NEEDED(chan, need_lock); 00295 00296 if (chan->monitor) { 00297 char filename[ FILENAME_MAX ]; 00298 00299 if (chan->monitor->read_stream) { 00300 ast_closestream(chan->monitor->read_stream); 00301 } 00302 if (chan->monitor->write_stream) { 00303 ast_closestream(chan->monitor->write_stream); 00304 } 00305 00306 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00307 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00308 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00309 if (ast_fileexists(filename, NULL, NULL) > 0) { 00310 ast_filedelete(filename, NULL); 00311 } 00312 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00313 } else { 00314 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00315 } 00316 00317 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00318 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00319 if (ast_fileexists(filename, NULL, NULL) > 0) { 00320 ast_filedelete(filename, NULL); 00321 } 00322 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00323 } else { 00324 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00325 } 00326 } 00327 00328 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00329 char tmp[1024]; 00330 char tmp2[1024]; 00331 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00332 char *name = chan->monitor->filename_base; 00333 int directory = strchr(name, '/') ? 1 : 0; 00334 const char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; 00335 const char *execute, *execute_args; 00336 const char *absolute = *name == '/' ? "" : "/"; 00337 00338 /* Set the execute application */ 00339 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00340 if (ast_strlen_zero(execute)) { 00341 #ifdef HAVE_SOXMIX 00342 execute = "nice -n 19 soxmix"; 00343 #else 00344 execute = "nice -n 19 sox -m"; 00345 #endif 00346 format = get_soxmix_format(format); 00347 delfiles = 1; 00348 } 00349 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00350 if (ast_strlen_zero(execute_args)) { 00351 execute_args = ""; 00352 } 00353 00354 snprintf(tmp, sizeof(tmp), "%s \"%s%s%s-in.%s\" \"%s%s%s-out.%s\" \"%s%s%s.%s\" %s &", execute, dir, absolute, name, format, dir, absolute, name, format, dir, absolute, name, format,execute_args); 00355 if (delfiles) { 00356 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* 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 } 00375 00376 UNLOCK_IF_NEEDED(chan, need_lock); 00377 00378 return 0; 00379 }
| int ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 389 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00390 { 00391 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00392 }
| 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 687 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(), and name.
Referenced by load_module().
00688 { 00689 struct ast_channel *c = NULL; 00690 const char *name = astman_get_header(m, "Channel"); 00691 const char *fname = astman_get_header(m, "File"); 00692 if (ast_strlen_zero(name)) { 00693 astman_send_error(s, m, "No channel specified"); 00694 return 0; 00695 } 00696 if (ast_strlen_zero(fname)) { 00697 astman_send_error(s, m, "No filename specified"); 00698 return 0; 00699 } 00700 c = ast_get_channel_by_name_locked(name); 00701 if (!c) { 00702 astman_send_error(s, m, "No such channel"); 00703 return 0; 00704 } 00705 if (ast_monitor_change_fname(c, fname, 1)) { 00706 astman_send_error(s, m, "Could not change monitored filename of channel"); 00707 ast_channel_unlock(c); 00708 return 0; 00709 } 00710 ast_channel_unlock(c); 00711 astman_send_ack(s, m, "Changed monitor filename"); 00712 return 0; 00713 }
| static int change_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper function.
Definition at line 584 of file res_monitor.c.
References ast_monitor_change_fname().
Referenced by load_module().
00585 { 00586 return ast_monitor_change_fname(chan, (const char*)data, 1); 00587 }
| static int do_pause_or_unpause | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | action | |||
| ) | [static] |
Definition at line 727 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, and name.
Referenced by pause_monitor_action(), and unpause_monitor_action().
00728 { 00729 struct ast_channel *c = NULL; 00730 const char *name = astman_get_header(m, "Channel"); 00731 00732 if (ast_strlen_zero(name)) { 00733 astman_send_error(s, m, "No channel specified"); 00734 return -1; 00735 } 00736 00737 c = ast_get_channel_by_name_locked(name); 00738 if (!c) { 00739 astman_send_error(s, m, "No such channel"); 00740 return -1; 00741 } 00742 00743 if (action == MONITOR_ACTION_PAUSE) 00744 ast_monitor_pause(c); 00745 else 00746 ast_monitor_unpause(c); 00747 00748 ast_channel_unlock(c); 00749 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00750 return 0; 00751 }
| 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 271 of file res_monitor.c.
Referenced by ast_monitor_stop().
| static int load_module | ( | void | ) | [static] |
Definition at line 776 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().
00777 { 00778 ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip); 00779 ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip); 00780 ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip); 00781 ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip); 00782 ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip); 00783 ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help); 00784 ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help); 00785 ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help); 00786 ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help); 00787 ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help); 00788 00789 return AST_MODULE_LOAD_SUCCESS; 00790 }
| static int pause_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 759 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.
Referenced by load_module().
00760 { 00761 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00762 }
| static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 395 of file res_monitor.c.
References ast_monitor_pause().
Referenced by load_module().
00396 { 00397 return ast_monitor_pause(chan); 00398 }
| static int start_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Start monitoring a channel by manager connection.
Definition at line 604 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, name, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00605 { 00606 struct ast_channel *c = NULL; 00607 const char *name = astman_get_header(m, "Channel"); 00608 const char *fname = astman_get_header(m, "File"); 00609 const char *format = astman_get_header(m, "Format"); 00610 const char *mix = astman_get_header(m, "Mix"); 00611 char *d; 00612 00613 if (ast_strlen_zero(name)) { 00614 astman_send_error(s, m, "No channel specified"); 00615 return 0; 00616 } 00617 c = ast_get_channel_by_name_locked(name); 00618 if (!c) { 00619 astman_send_error(s, m, "No such channel"); 00620 return 0; 00621 } 00622 00623 if (ast_strlen_zero(fname)) { 00624 /* No filename base specified, default to channel name as per CLI */ 00625 fname = ast_strdupa(c->name); 00626 /* Channels have the format technology/channel_name - have to replace that / */ 00627 if ((d = strchr(fname, '/'))) 00628 *d = '-'; 00629 } 00630 00631 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00632 if (ast_monitor_change_fname(c, fname, 1)) { 00633 astman_send_error(s, m, "Could not start monitoring channel"); 00634 ast_channel_unlock(c); 00635 return 0; 00636 } 00637 } 00638 00639 if (ast_true(mix)) { 00640 ast_monitor_setjoinfiles(c, 1); 00641 } 00642 00643 ast_channel_unlock(c); 00644 astman_send_ack(s, m, "Started monitoring channel"); 00645 return 0; 00646 }
| 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 494 of file res_monitor.c.
References AST_APP_ARG, ast_cdr_alloc(), ast_cdr_setuserfield(), AST_DECLARE_APP_ARGS, ast_log(), ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::cdr, format, 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().
00495 { 00496 char *arg = NULL; 00497 char *options = NULL; 00498 char *delay = NULL; 00499 char *urlprefix = NULL; 00500 char tmp[256]; 00501 int stream_action = X_REC_IN | X_REC_OUT; 00502 int joinfiles = 0; 00503 int waitforbridge = 0; 00504 int res = 0; 00505 char *parse; 00506 AST_DECLARE_APP_ARGS(args, 00507 AST_APP_ARG(format); 00508 AST_APP_ARG(fname_base); 00509 AST_APP_ARG(options); 00510 ); 00511 00512 /* Parse arguments. */ 00513 if (ast_strlen_zero((char*)data)) { 00514 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00515 return 0; 00516 } 00517 00518 parse = ast_strdupa((char*)data); 00519 AST_STANDARD_APP_ARGS(args, parse); 00520 00521 if (!ast_strlen_zero(args.options)) { 00522 if (strchr(args.options, 'm')) 00523 stream_action |= X_JOIN; 00524 if (strchr(args.options, 'b')) 00525 waitforbridge = 1; 00526 if (strchr(args.options, 'i')) 00527 stream_action &= ~X_REC_IN; 00528 if (strchr(args.options, 'o')) 00529 stream_action &= ~X_REC_OUT; 00530 } 00531 00532 arg = strchr(args.format, ':'); 00533 if (arg) { 00534 *arg++ = 0; 00535 urlprefix = arg; 00536 } 00537 00538 if (urlprefix) { 00539 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00540 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00541 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) 00542 return -1; 00543 ast_cdr_setuserfield(chan, tmp); 00544 } 00545 if (waitforbridge) { 00546 /* We must remove the "b" option if listed. In principle none of 00547 the following could give NULL results, but we check just to 00548 be pedantic. Reconstructing with checks for 'm' option does not 00549 work if we end up adding more options than 'm' in the future. */ 00550 delay = ast_strdupa(data); 00551 options = strrchr(delay, ','); 00552 if (options) { 00553 arg = strchr(options, 'b'); 00554 if (arg) { 00555 *arg = 'X'; 00556 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00557 } 00558 } 00559 return 0; 00560 } 00561 00562 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00563 if (res < 0) 00564 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00565 00566 if (stream_action & X_JOIN) { 00567 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00568 joinfiles = 1; 00569 else 00570 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00571 } 00572 ast_monitor_setjoinfiles(chan, joinfiles); 00573 00574 return res; 00575 }
| static int stop_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 654 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(), and name.
Referenced by load_module().
00655 { 00656 struct ast_channel *c = NULL; 00657 const char *name = astman_get_header(m, "Channel"); 00658 int res; 00659 if (ast_strlen_zero(name)) { 00660 astman_send_error(s, m, "No channel specified"); 00661 return 0; 00662 } 00663 c = ast_get_channel_by_name_locked(name); 00664 if (!c) { 00665 astman_send_error(s, m, "No such channel"); 00666 return 0; 00667 } 00668 res = ast_monitor_stop(c, 1); 00669 ast_channel_unlock(c); 00670 if (res) { 00671 astman_send_error(s, m, "Could not stop monitoring channel"); 00672 return 0; 00673 } 00674 astman_send_ack(s, m, "Stopped monitoring channel"); 00675 return 0; 00676 }
| static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper function.
Definition at line 578 of file res_monitor.c.
References ast_monitor_stop().
Referenced by load_module().
00579 { 00580 return ast_monitor_stop(chan, 1); 00581 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 792 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00793 { 00794 ast_unregister_application("Monitor"); 00795 ast_unregister_application("StopMonitor"); 00796 ast_unregister_application("ChangeMonitor"); 00797 ast_unregister_application("PauseMonitor"); 00798 ast_unregister_application("UnpauseMonitor"); 00799 ast_manager_unregister("Monitor"); 00800 ast_manager_unregister("StopMonitor"); 00801 ast_manager_unregister("ChangeMonitor"); 00802 ast_manager_unregister("PauseMonitor"); 00803 ast_manager_unregister("UnpauseMonitor"); 00804 00805 return 0; 00806 }
| static int unpause_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 770 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_UNPAUSE.
Referenced by load_module().
00771 { 00772 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00773 }
| static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 401 of file res_monitor.c.
References ast_monitor_unpause().
Referenced by load_module().
00402 { 00403 return ast_monitor_unpause(chan); 00404 }
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 812 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 812 of file res_monitor.c.
char change_monitor_action_help[] [static] |
Definition at line 678 of file res_monitor.c.
char* changemonitor_descrip [static] |
" 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] |
Definition at line 47 of file res_monitor.c.
Referenced by ast_monitor_start().
char pause_monitor_action_help[] [static] |
"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 753 of file res_monitor.c.
char* pausemonitor_descrip [static] |
" 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 589 of file res_monitor.c.
char stop_monitor_action_help[] [static] |
"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 648 of file res_monitor.c.
char* stopmonitor_descrip [static] |
" 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] |
"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 764 of file res_monitor.c.
char* unpausemonitor_descrip [static] |
" 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.
1.6.1