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