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 | AST_API_MODULE |
| #define | LOCK_IF_NEEDED(lock, needed) |
| #define | UNLOCK_IF_NEEDED(lock, needed) |
Enumerations | |
| enum | MONITOR_PAUSING_ACTION { MONITOR_ACTION_PAUSE, MONITOR_ACTION_UNPAUSE } |
Functions | |
| static void | __reg_module (void) |
| static void | __unreg_module (void) |
| int | ast_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 = "0901e4e500243c855563a2d78b0c03e4" , .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 AST_API_MODULE |
Definition at line 41 of file res_monitor.c.
| #define LOCK_IF_NEEDED | ( | lock, | |||
| needed | ) |
do { \ if (needed) \ ast_channel_lock(lock); \ } while(0)
Definition at line 50 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 55 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 722 of file res_monitor.c.
00723 { 00724 MONITOR_ACTION_PAUSE, 00725 MONITOR_ACTION_UNPAUSE 00726 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 813 of file res_monitor.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 813 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 415 of file res_monitor.c.
References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_debug, ast_log(), ast_mkdir(), ast_strlen_zero(), errno, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, LOCK_IF_NEEDED, LOG_ERROR, LOG_WARNING, ast_channel::monitor, name, ast_channel::name, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00416 { 00417 if (ast_strlen_zero(fname_base)) { 00418 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00419 return -1; 00420 } 00421 00422 LOCK_IF_NEEDED(chan, need_lock); 00423 00424 if (chan->monitor) { 00425 int directory = strchr(fname_base, '/') ? 1 : 0; 00426 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00427 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00428 int i, fd[2] = { -1, -1 }, doexit = 0; 00429 00430 /* before continuing, see if we're trying to rename the file to itself... */ 00431 snprintf(tmpstring, sizeof(tmpstring), "%s/%s", absolute, fname_base); 00432 00433 /*!\note We cannot just compare filenames, due to symlinks, relative 00434 * paths, and other possible filesystem issues. We could use 00435 * realpath(3), but its use is discouraged. However, if we try to 00436 * create the same file from two different paths, the second will 00437 * fail, and so we have our notification that the filenames point to 00438 * the same path. 00439 * 00440 * Remember, also, that we're using the basename of the file (i.e. 00441 * the file without the format suffix), so it does not already exist 00442 * and we aren't interfering with the recording itself. 00443 */ 00444 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00445 00446 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00447 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00448 if (fd[0] < 0) { 00449 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00450 } else { 00451 ast_debug(2, "No need to rename monitor filename to itself\n"); 00452 } 00453 doexit = 1; 00454 } 00455 00456 /* Cleanup temporary files */ 00457 for (i = 0; i < 2; i++) { 00458 if (fd[i] >= 0) { 00459 while (close(fd[i]) < 0 && errno == EINTR); 00460 } 00461 } 00462 unlink(tmpstring); 00463 unlink(chan->monitor->filename_base); 00464 00465 if (doexit) { 00466 UNLOCK_IF_NEEDED(chan, need_lock); 00467 return 0; 00468 } 00469 00470 /* try creating the directory just in case it doesn't exist */ 00471 if (directory) { 00472 char *name = ast_strdupa(fname_base); 00473 ast_mkdir(dirname(name), 0777); 00474 } 00475 00476 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00477 chan->monitor->filename_changed = 1; 00478 } else { 00479 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00480 } 00481 00482 UNLOCK_IF_NEEDED(chan, need_lock); 00483 00484 return 0; 00485 }
| int ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 384 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00385 { 00386 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00387 }
| 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 125 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().
00126 { 00127 LOCK_IF_NEEDED(chan, 1); 00128 if (!chan->monitor) { 00129 UNLOCK_IF_NEEDED(chan, 1); 00130 return -1; 00131 } 00132 chan->monitor->state = state; 00133 UNLOCK_IF_NEEDED(chan, 1); 00134 return 0; 00135 }
| void ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
| int | turnon | |||
| ) |
Definition at line 716 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 148 of file res_monitor.c.
References ast_calloc, ast_closestream(), ast_config_AST_MONITOR_DIR, ast_debug, 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_strlen_zero(), ast_writefile(), EVENT_FLAG_CALL, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, ast_channel_monitor::format, LOCK_IF_NEEDED, LOG_WARNING, manager_event, monitor, ast_channel::monitor, monitorlock, ast_channel::name, name, pbx_builtin_setvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, ast_channel_monitor::stop, ast_channel::uniqueid, 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().
00150 { 00151 int res = 0; 00152 00153 LOCK_IF_NEEDED(chan, need_lock); 00154 00155 if (!(chan->monitor)) { 00156 struct ast_channel_monitor *monitor; 00157 char *channel_name, *p; 00158 00159 /* Create monitoring directory if needed */ 00160 ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); 00161 00162 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { 00163 UNLOCK_IF_NEEDED(chan, need_lock); 00164 return -1; 00165 } 00166 00167 /* Determine file names */ 00168 if (!ast_strlen_zero(fname_base)) { 00169 int directory = strchr(fname_base, '/') ? 1 : 0; 00170 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR; 00171 00172 snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in", 00173 absolute, fname_base); 00174 snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out", 00175 absolute, fname_base); 00176 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%s", 00177 absolute, 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_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, 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, name, pbx_builtin_getvar_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 *name = chan->monitor->filename_base; 00334 int directory = strchr(name, '/') ? 1 : 0; 00335 const char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; 00336 const char *execute, *execute_args; 00337 const char *absolute = *name == '/' ? "" : "/"; 00338 00339 /* Set the execute application */ 00340 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00341 if (ast_strlen_zero(execute)) { 00342 #ifdef HAVE_SOXMIX 00343 execute = "nice -n 19 soxmix"; 00344 #else 00345 execute = "nice -n 19 sox -m"; 00346 #endif 00347 format = get_soxmix_format(format); 00348 delfiles = 1; 00349 } 00350 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00351 if (ast_strlen_zero(execute_args)) { 00352 execute_args = ""; 00353 } 00354 00355 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); 00356 if (delfiles) { 00357 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */ 00358 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00359 } 00360 ast_debug(1,"monitor executing %s\n",tmp); 00361 if (ast_safe_system(tmp) == -1) 00362 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00363 } 00364 00365 ast_free(chan->monitor->format); 00366 ast_free(chan->monitor); 00367 chan->monitor = NULL; 00368 00369 manager_event(EVENT_FLAG_CALL, "MonitorStop", 00370 "Channel: %s\r\n" 00371 "Uniqueid: %s\r\n", 00372 chan->name, 00373 chan->uniqueid 00374 ); 00375 } 00376 00377 UNLOCK_IF_NEEDED(chan, need_lock); 00378 00379 return 0; 00380 }
| int ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 390 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00391 { 00392 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00393 }
| 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 688 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().
00689 { 00690 struct ast_channel *c = NULL; 00691 const char *name = astman_get_header(m, "Channel"); 00692 const char *fname = astman_get_header(m, "File"); 00693 if (ast_strlen_zero(name)) { 00694 astman_send_error(s, m, "No channel specified"); 00695 return 0; 00696 } 00697 if (ast_strlen_zero(fname)) { 00698 astman_send_error(s, m, "No filename specified"); 00699 return 0; 00700 } 00701 c = ast_get_channel_by_name_locked(name); 00702 if (!c) { 00703 astman_send_error(s, m, "No such channel"); 00704 return 0; 00705 } 00706 if (ast_monitor_change_fname(c, fname, 1)) { 00707 astman_send_error(s, m, "Could not change monitored filename of channel"); 00708 ast_channel_unlock(c); 00709 return 0; 00710 } 00711 ast_channel_unlock(c); 00712 astman_send_ack(s, m, "Changed monitor filename"); 00713 return 0; 00714 }
| static int change_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper function.
Definition at line 585 of file res_monitor.c.
References ast_monitor_change_fname().
Referenced by load_module().
00586 { 00587 return ast_monitor_change_fname(chan, (const char*)data, 1); 00588 }
| static int do_pause_or_unpause | ( | struct mansession * | s, | |
| const struct message * | m, | |||
| int | action | |||
| ) | [static] |
Definition at line 728 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().
00729 { 00730 struct ast_channel *c = NULL; 00731 const char *name = astman_get_header(m, "Channel"); 00732 00733 if (ast_strlen_zero(name)) { 00734 astman_send_error(s, m, "No channel specified"); 00735 return -1; 00736 } 00737 00738 c = ast_get_channel_by_name_locked(name); 00739 if (!c) { 00740 astman_send_error(s, m, "No such channel"); 00741 return -1; 00742 } 00743 00744 if (action == MONITOR_ACTION_PAUSE) 00745 ast_monitor_pause(c); 00746 else 00747 ast_monitor_unpause(c); 00748 00749 ast_channel_unlock(c); 00750 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00751 return 0; 00752 }
| 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().
| static int load_module | ( | void | ) | [static] |
Definition at line 777 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().
00778 { 00779 ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip); 00780 ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip); 00781 ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip); 00782 ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip); 00783 ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip); 00784 ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help); 00785 ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help); 00786 ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help); 00787 ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help); 00788 ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help); 00789 00790 return AST_MODULE_LOAD_SUCCESS; 00791 }
| static int pause_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 760 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.
Referenced by load_module().
00761 { 00762 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00763 }
| static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 396 of file res_monitor.c.
References ast_monitor_pause().
Referenced by load_module().
00397 { 00398 return ast_monitor_pause(chan); 00399 }
| static int start_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Start monitoring a channel by manager connection.
Definition at line 605 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_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), format, ast_channel::name, name, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00606 { 00607 struct ast_channel *c = NULL; 00608 const char *name = astman_get_header(m, "Channel"); 00609 const char *fname = astman_get_header(m, "File"); 00610 const char *format = astman_get_header(m, "Format"); 00611 const char *mix = astman_get_header(m, "Mix"); 00612 char *d; 00613 00614 if (ast_strlen_zero(name)) { 00615 astman_send_error(s, m, "No channel specified"); 00616 return 0; 00617 } 00618 c = ast_get_channel_by_name_locked(name); 00619 if (!c) { 00620 astman_send_error(s, m, "No such channel"); 00621 return 0; 00622 } 00623 00624 if (ast_strlen_zero(fname)) { 00625 /* No filename base specified, default to channel name as per CLI */ 00626 fname = ast_strdupa(c->name); 00627 /* Channels have the format technology/channel_name - have to replace that / */ 00628 if ((d = strchr(fname, '/'))) 00629 *d = '-'; 00630 } 00631 00632 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00633 if (ast_monitor_change_fname(c, fname, 1)) { 00634 astman_send_error(s, m, "Could not start monitoring channel"); 00635 ast_channel_unlock(c); 00636 return 0; 00637 } 00638 } 00639 00640 if (ast_true(mix)) { 00641 ast_monitor_setjoinfiles(c, 1); 00642 } 00643 00644 ast_channel_unlock(c); 00645 astman_send_ack(s, m, "Started monitoring channel"); 00646 return 0; 00647 }
| 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 495 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_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().
00496 { 00497 char *arg = NULL; 00498 char *options = NULL; 00499 char *delay = NULL; 00500 char *urlprefix = NULL; 00501 char tmp[256]; 00502 int stream_action = X_REC_IN | X_REC_OUT; 00503 int joinfiles = 0; 00504 int waitforbridge = 0; 00505 int res = 0; 00506 char *parse; 00507 AST_DECLARE_APP_ARGS(args, 00508 AST_APP_ARG(format); 00509 AST_APP_ARG(fname_base); 00510 AST_APP_ARG(options); 00511 ); 00512 00513 /* Parse arguments. */ 00514 if (ast_strlen_zero((char*)data)) { 00515 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00516 return 0; 00517 } 00518 00519 parse = ast_strdupa((char*)data); 00520 AST_STANDARD_APP_ARGS(args, parse); 00521 00522 if (!ast_strlen_zero(args.options)) { 00523 if (strchr(args.options, 'm')) 00524 stream_action |= X_JOIN; 00525 if (strchr(args.options, 'b')) 00526 waitforbridge = 1; 00527 if (strchr(args.options, 'i')) 00528 stream_action &= ~X_REC_IN; 00529 if (strchr(args.options, 'o')) 00530 stream_action &= ~X_REC_OUT; 00531 } 00532 00533 arg = strchr(args.format, ':'); 00534 if (arg) { 00535 *arg++ = 0; 00536 urlprefix = arg; 00537 } 00538 00539 if (urlprefix) { 00540 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00541 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00542 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) 00543 return -1; 00544 ast_cdr_setuserfield(chan, tmp); 00545 } 00546 if (waitforbridge) { 00547 /* We must remove the "b" option if listed. In principle none of 00548 the following could give NULL results, but we check just to 00549 be pedantic. Reconstructing with checks for 'm' option does not 00550 work if we end up adding more options than 'm' in the future. */ 00551 delay = ast_strdupa(data); 00552 options = strrchr(delay, ','); 00553 if (options) { 00554 arg = strchr(options, 'b'); 00555 if (arg) { 00556 *arg = 'X'; 00557 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00558 } 00559 } 00560 return 0; 00561 } 00562 00563 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00564 if (res < 0) 00565 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00566 00567 if (stream_action & X_JOIN) { 00568 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00569 joinfiles = 1; 00570 else 00571 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00572 } 00573 ast_monitor_setjoinfiles(chan, joinfiles); 00574 00575 return res; 00576 }
| static int stop_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 655 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().
00656 { 00657 struct ast_channel *c = NULL; 00658 const char *name = astman_get_header(m, "Channel"); 00659 int res; 00660 if (ast_strlen_zero(name)) { 00661 astman_send_error(s, m, "No channel specified"); 00662 return 0; 00663 } 00664 c = ast_get_channel_by_name_locked(name); 00665 if (!c) { 00666 astman_send_error(s, m, "No such channel"); 00667 return 0; 00668 } 00669 res = ast_monitor_stop(c, 1); 00670 ast_channel_unlock(c); 00671 if (res) { 00672 astman_send_error(s, m, "Could not stop monitoring channel"); 00673 return 0; 00674 } 00675 astman_send_ack(s, m, "Stopped monitoring channel"); 00676 return 0; 00677 }
| static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper function.
Definition at line 579 of file res_monitor.c.
References ast_monitor_stop().
Referenced by load_module().
00580 { 00581 return ast_monitor_stop(chan, 1); 00582 }
| static int unload_module | ( | void | ) | [static] |
Definition at line 793 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00794 { 00795 ast_unregister_application("Monitor"); 00796 ast_unregister_application("StopMonitor"); 00797 ast_unregister_application("ChangeMonitor"); 00798 ast_unregister_application("PauseMonitor"); 00799 ast_unregister_application("UnpauseMonitor"); 00800 ast_manager_unregister("Monitor"); 00801 ast_manager_unregister("StopMonitor"); 00802 ast_manager_unregister("ChangeMonitor"); 00803 ast_manager_unregister("PauseMonitor"); 00804 ast_manager_unregister("UnpauseMonitor"); 00805 00806 return 0; 00807 }
| static int unpause_monitor_action | ( | struct mansession * | s, | |
| const struct message * | m | |||
| ) | [static] |
Definition at line 771 of file res_monitor.c.
References do_pause_or_unpause(), and MONITOR_ACTION_UNPAUSE.
Referenced by load_module().
00772 { 00773 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00774 }
| static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
| void * | data | |||
| ) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 402 of file res_monitor.c.
References ast_monitor_unpause().
Referenced by load_module().
00403 { 00404 return ast_monitor_unpause(chan); 00405 }
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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 813 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 813 of file res_monitor.c.
char change_monitor_action_help[] [static] |
Definition at line 679 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 103 of file res_monitor.c.
char* changemonitor_synopsis = "Change monitoring filename of a channel" [static] |
Definition at line 101 of file res_monitor.c.
char* monitor_descrip [static] |
Definition at line 64 of file res_monitor.c.
char* monitor_synopsis = "Monitor a channel" [static] |
Definition at line 62 of file res_monitor.c.
ast_mutex_t monitorlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
Definition at line 48 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 754 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 109 of file res_monitor.c.
char* pausemonitor_synopsis = "Pause monitoring of a channel" [static] |
Definition at line 107 of file res_monitor.c.
unsigned long seq = 0 [static] |
Definition at line 60 of file res_monitor.c.
char start_monitor_action_help[] [static] |
Definition at line 590 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 649 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 98 of file res_monitor.c.
char* stopmonitor_synopsis = "Stop monitoring a channel" [static] |
Definition at line 96 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 765 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 114 of file res_monitor.c.
char* unpausemonitor_synopsis = "Unpause monitoring of a channel" [static] |
Definition at line 112 of file res_monitor.c.
1.6.2