#include "asterisk.h"
#include <sys/stat.h>
#include <libgen.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/manager.h"
#include "asterisk/cli.h"
#include "asterisk/monitor.h"
#include "asterisk/app.h"
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
Go to the source code of this file.
Defines | |
#define | LOCK_IF_NEEDED(lock, needed) |
#define | UNLOCK_IF_NEEDED(lock, needed) |
Enumerations | |
enum | MONITOR_PAUSING_ACTION { MONITOR_ACTION_PAUSE, MONITOR_ACTION_UNPAUSE } |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
int | ast_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock) |
Change monitored filename of channel. | |
int | ast_monitor_pause (struct ast_channel *chan) |
Pause monitoring of channel. | |
static int | ast_monitor_set_state (struct ast_channel *chan, int state) |
Change state of monitored channel. | |
void | ast_monitor_setjoinfiles (struct ast_channel *chan, int turnon) |
int | ast_monitor_start (struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action) |
Start monitoring a channel. | |
int | ast_monitor_stop (struct ast_channel *chan, int need_lock) |
Stop monitoring channel. | |
int | ast_monitor_unpause (struct ast_channel *chan) |
Unpause monitoring of channel. | |
static int | change_monitor_action (struct mansession *s, const struct message *m) |
Change filename of a monitored channel by manager connection. | |
static int | change_monitor_exec (struct ast_channel *chan, void *data) |
Wrapper function. | |
static int | do_pause_or_unpause (struct mansession *s, const struct message *m, int action) |
static const char * | get_soxmix_format (const char *format) |
Get audio format. | |
static int | load_module (void) |
static int | pause_monitor_action (struct mansession *s, const struct message *m) |
static int | pause_monitor_exec (struct ast_channel *chan, void *data) |
Wrapper for ast_monitor_pause. | |
static int | start_monitor_action (struct mansession *s, const struct message *m) |
Start monitoring a channel by manager connection. | |
static int | start_monitor_exec (struct ast_channel *chan, void *data) |
Start monitor. | |
static int | stop_monitor_action (struct mansession *s, const struct message *m) |
Stop monitoring a channel by manager connection. | |
static int | stop_monitor_exec (struct ast_channel *chan, void *data) |
Wrapper function. | |
static int | unload_module (void) |
static int | unpause_monitor_action (struct mansession *s, const struct message *m) |
static int | unpause_monitor_exec (struct ast_channel *chan, void *data) |
Wrapper for ast_monitor_unpause. | |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS , .description = "Call Monitoring Resource" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static char | change_monitor_action_help [] |
static char * | changemonitor_descrip |
static char * | changemonitor_synopsis = "Change monitoring filename of a channel" |
static char * | monitor_descrip |
static char * | monitor_synopsis = "Monitor a channel" |
static ast_mutex_t | monitorlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
static char | pause_monitor_action_help [] |
static char * | pausemonitor_descrip |
static char * | pausemonitor_synopsis = "Pause monitoring of a channel" |
static unsigned long | seq = 0 |
static char | start_monitor_action_help [] |
static char | stop_monitor_action_help [] |
static char * | stopmonitor_descrip |
static char * | stopmonitor_synopsis = "Stop monitoring a channel" |
static char | unpause_monitor_action_help [] |
static char * | unpausemonitor_descrip |
static char * | unpausemonitor_synopsis = "Unpause monitoring of a channel" |
Definition in file res_monitor.c.
#define LOCK_IF_NEEDED | ( | lock, | |||
needed | ) |
Value:
do { \ if (needed) \ ast_channel_lock(lock); \ } while(0)
Definition at line 49 of file res_monitor.c.
Referenced by ast_monitor_change_fname(), ast_monitor_set_state(), ast_monitor_start(), and ast_monitor_stop().
#define UNLOCK_IF_NEEDED | ( | lock, | |||
needed | ) |
Value:
do { \ if (needed) \ ast_channel_unlock(lock); \ } while (0)
Definition at line 54 of file res_monitor.c.
Referenced by ast_monitor_change_fname(), ast_monitor_set_state(), ast_monitor_start(), and ast_monitor_stop().
Definition at line 686 of file res_monitor.c.
00687 { 00688 MONITOR_ACTION_PAUSE, 00689 MONITOR_ACTION_UNPAUSE 00690 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 777 of file res_monitor.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 777 of file res_monitor.c.
int ast_monitor_change_fname | ( | struct ast_channel * | chan, | |
const char * | fname_base, | |||
int | need_lock | |||
) |
Change monitored filename of channel.
chan | ||
fname_base | new filename | |
need_lock |
0 | on success. | |
-1 | on failure. |
Definition at line 411 of file res_monitor.c.
References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_log(), ast_mkdir(), ast_strdupa, ast_strlen_zero(), chan, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, ast_channel::monitor, name, ast_channel::name, option_debug, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00412 { 00413 if (ast_strlen_zero(fname_base)) { 00414 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00415 return -1; 00416 } 00417 00418 LOCK_IF_NEEDED(chan, need_lock); 00419 00420 if (chan->monitor) { 00421 int directory = strchr(fname_base, '/') ? 1 : 0; 00422 const char *absolute = *fname_base == '/' ? "" : "/"; 00423 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00424 00425 /* before continuing, see if we're trying to rename the file to itself... */ 00426 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00427 if (!strcmp(tmpstring, chan->monitor->filename_base)) { 00428 if (option_debug > 2) 00429 ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n"); 00430 UNLOCK_IF_NEEDED(chan, need_lock); 00431 return 0; 00432 } 00433 00434 /* try creating the directory just in case it doesn't exist */ 00435 if (directory) { 00436 char *name = ast_strdupa(fname_base); 00437 ast_mkdir(dirname(name), 0777); 00438 } 00439 00440 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00441 chan->monitor->filename_changed = 1; 00442 } else { 00443 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00444 } 00445 00446 UNLOCK_IF_NEEDED(chan, need_lock); 00447 00448 return 0; 00449 }
int ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Pause monitoring of channel.
Definition at line 380 of file res_monitor.c.
References AST_MONITOR_PAUSED, ast_monitor_set_state(), and chan.
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00381 { 00382 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00383 }
static int ast_monitor_set_state | ( | struct ast_channel * | chan, | |
int | state | |||
) | [static] |
Change state of monitored channel.
chan | ||
state | monitor state |
0 | on success. | |
-1 | on failure. |
Definition at line 124 of file res_monitor.c.
References chan, LOCK_IF_NEEDED, ast_channel::monitor, ast_channel_monitor::state, and UNLOCK_IF_NEEDED.
Referenced by ast_monitor_pause(), ast_monitor_start(), and ast_monitor_unpause().
00125 { 00126 LOCK_IF_NEEDED(chan, 1); 00127 if (!chan->monitor) { 00128 UNLOCK_IF_NEEDED(chan, 1); 00129 return -1; 00130 } 00131 chan->monitor->state = state; 00132 UNLOCK_IF_NEEDED(chan, 1); 00133 return 0; 00134 }
void ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
int | turnon | |||
) |
Definition at line 680 of file res_monitor.c.
References chan, 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_copy_string(), ast_debug, AST_FILE_MODE, ast_filedelete(), ast_fileexists(), ast_free, ast_log(), ast_mkdir(), AST_MONITOR_RUNNING, ast_monitor_set_state(), ast_monitor_stop(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdup, ast_strdupa, ast_strlen_zero(), ast_writefile(), chan, EVENT_FLAG_CALL, FILENAME_MAX, LOCK_IF_NEEDED, LOG_WARNING, manager_event, monitor, ast_channel::monitor, monitorlock, ast_channel::name, name, pbx_builtin_setvar_helper(), ast_channel::uniqueid, UNLOCK_IF_NEEDED, X_REC_IN, and X_REC_OUT.
Referenced by __agent_start_monitoring(), start_monitor_action(), 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 ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base)); 00180 } else { 00181 ast_mutex_lock(&monitorlock); 00182 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00183 ast_config_AST_MONITOR_DIR, seq); 00184 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00185 ast_config_AST_MONITOR_DIR, seq); 00186 seq++; 00187 ast_mutex_unlock(&monitorlock); 00188 00189 channel_name = ast_strdupa(chan->name); 00190 while ((p = strchr(channel_name, '/'))) { 00191 *p = '-'; 00192 } 00193 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00194 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00195 monitor->filename_changed = 1; 00196 } 00197 00198 monitor->stop = ast_monitor_stop; 00199 00200 /* Determine file format */ 00201 if (!ast_strlen_zero(format_spec)) { 00202 monitor->format = ast_strdup(format_spec); 00203 } else { 00204 monitor->format = ast_strdup("wav"); 00205 } 00206 00207 /* open files */ 00208 if (stream_action & X_REC_IN) { 00209 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) 00210 ast_filedelete(monitor->read_filename, NULL); 00211 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00212 monitor->format, NULL, 00213 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00214 ast_log(LOG_WARNING, "Could not create file %s\n", 00215 monitor->read_filename); 00216 ast_free(monitor); 00217 UNLOCK_IF_NEEDED(chan, need_lock); 00218 return -1; 00219 } 00220 } else 00221 monitor->read_stream = NULL; 00222 00223 if (stream_action & X_REC_OUT) { 00224 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00225 ast_filedelete(monitor->write_filename, NULL); 00226 } 00227 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00228 monitor->format, NULL, 00229 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) { 00230 ast_log(LOG_WARNING, "Could not create file %s\n", 00231 monitor->write_filename); 00232 ast_closestream(monitor->read_stream); 00233 ast_free(monitor); 00234 UNLOCK_IF_NEEDED(chan, need_lock); 00235 return -1; 00236 } 00237 } else 00238 monitor->write_stream = NULL; 00239 00240 chan->monitor = monitor; 00241 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00242 /* so we know this call has been monitored in case we need to bill for it or something */ 00243 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00244 00245 manager_event(EVENT_FLAG_CALL, "MonitorStart", 00246 "Channel: %s\r\n" 00247 "Uniqueid: %s\r\n", 00248 chan->name, 00249 chan->uniqueid 00250 ); 00251 } else { 00252 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name); 00253 res = -1; 00254 } 00255 00256 UNLOCK_IF_NEEDED(chan, need_lock); 00257 00258 return res; 00259 }
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 287 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(), chan, 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, 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().
00288 { 00289 int delfiles = 0; 00290 00291 LOCK_IF_NEEDED(chan, need_lock); 00292 00293 if (chan->monitor) { 00294 char filename[ FILENAME_MAX ]; 00295 00296 if (chan->monitor->read_stream) { 00297 ast_closestream(chan->monitor->read_stream); 00298 } 00299 if (chan->monitor->write_stream) { 00300 ast_closestream(chan->monitor->write_stream); 00301 } 00302 00303 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00304 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00305 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00306 if (ast_fileexists(filename, NULL, NULL) > 0) { 00307 ast_filedelete(filename, NULL); 00308 } 00309 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00310 } else { 00311 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00312 } 00313 00314 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00315 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00316 if (ast_fileexists(filename, NULL, NULL) > 0) { 00317 ast_filedelete(filename, NULL); 00318 } 00319 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00320 } else { 00321 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00322 } 00323 } 00324 00325 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00326 char tmp[1024]; 00327 char tmp2[1024]; 00328 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00329 char *name = chan->monitor->filename_base; 00330 int directory = strchr(name, '/') ? 1 : 0; 00331 const char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; 00332 const char *execute, *execute_args; 00333 const char *absolute = *name == '/' ? "" : "/"; 00334 00335 /* Set the execute application */ 00336 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00337 if (ast_strlen_zero(execute)) { 00338 #ifdef HAVE_SOXMIX 00339 execute = "nice -n 19 soxmix"; 00340 #else 00341 execute = "nice -n 19 sox -m"; 00342 #endif 00343 format = get_soxmix_format(format); 00344 delfiles = 1; 00345 } 00346 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00347 if (ast_strlen_zero(execute_args)) { 00348 execute_args = ""; 00349 } 00350 00351 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); 00352 if (delfiles) { 00353 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */ 00354 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00355 } 00356 ast_debug(1,"monitor executing %s\n",tmp); 00357 if (ast_safe_system(tmp) == -1) 00358 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00359 } 00360 00361 ast_free(chan->monitor->format); 00362 ast_free(chan->monitor); 00363 chan->monitor = NULL; 00364 00365 manager_event(EVENT_FLAG_CALL, "MonitorStop", 00366 "Channel: %s\r\n" 00367 "Uniqueid: %s\r\n", 00368 chan->name, 00369 chan->uniqueid 00370 ); 00371 } 00372 00373 UNLOCK_IF_NEEDED(chan, need_lock); 00374 00375 return 0; 00376 }
int ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Unpause monitoring of channel.
Definition at line 386 of file res_monitor.c.
References AST_MONITOR_RUNNING, ast_monitor_set_state(), and chan.
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00387 { 00388 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00389 }
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 652 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_change_fname(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, and s.
Referenced by load_module().
00653 { 00654 struct ast_channel *c = NULL; 00655 const char *name = astman_get_header(m, "Channel"); 00656 const char *fname = astman_get_header(m, "File"); 00657 if (ast_strlen_zero(name)) { 00658 astman_send_error(s, m, "No channel specified"); 00659 return 0; 00660 } 00661 if (ast_strlen_zero(fname)) { 00662 astman_send_error(s, m, "No filename specified"); 00663 return 0; 00664 } 00665 c = ast_get_channel_by_name_locked(name); 00666 if (!c) { 00667 astman_send_error(s, m, "No such channel"); 00668 return 0; 00669 } 00670 if (ast_monitor_change_fname(c, fname, 1)) { 00671 astman_send_error(s, m, "Could not change monitored filename of channel"); 00672 ast_channel_unlock(c); 00673 return 0; 00674 } 00675 ast_channel_unlock(c); 00676 astman_send_ack(s, m, "Changed monitor filename"); 00677 return 0; 00678 }
static int change_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper function.
Definition at line 549 of file res_monitor.c.
References ast_monitor_change_fname(), and chan.
Referenced by load_module().
00550 { 00551 return ast_monitor_change_fname(chan, (const char*)data, 1); 00552 }
static int do_pause_or_unpause | ( | struct mansession * | s, | |
const struct message * | m, | |||
int | action | |||
) | [static] |
Definition at line 692 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_pause(), ast_monitor_unpause(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), MONITOR_ACTION_PAUSE, name, and s.
Referenced by pause_monitor_action(), and unpause_monitor_action().
00693 { 00694 struct ast_channel *c = NULL; 00695 const char *name = astman_get_header(m, "Channel"); 00696 00697 if (ast_strlen_zero(name)) { 00698 astman_send_error(s, m, "No channel specified"); 00699 return -1; 00700 } 00701 00702 c = ast_get_channel_by_name_locked(name); 00703 if (!c) { 00704 astman_send_error(s, m, "No such channel"); 00705 return -1; 00706 } 00707 00708 if (action == MONITOR_ACTION_PAUSE) 00709 ast_monitor_pause(c); 00710 else 00711 ast_monitor_unpause(c); 00712 00713 ast_channel_unlock(c); 00714 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel")); 00715 return 0; 00716 }
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 268 of file res_monitor.c.
Referenced by ast_monitor_stop().
00269 { 00270 const char *res = format; 00271 00272 if (!strcasecmp(format,"ulaw")) 00273 res = "ul"; 00274 if (!strcasecmp(format,"alaw")) 00275 res = "al"; 00276 00277 return res; 00278 }
static int load_module | ( | void | ) | [static] |
Definition at line 741 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().
00742 { 00743 ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip); 00744 ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip); 00745 ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip); 00746 ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip); 00747 ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip); 00748 ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help); 00749 ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help); 00750 ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help); 00751 ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help); 00752 ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help); 00753 00754 return AST_MODULE_LOAD_SUCCESS; 00755 }
static int pause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 724 of file res_monitor.c.
References do_pause_or_unpause(), MONITOR_ACTION_PAUSE, and s.
Referenced by load_module().
00725 { 00726 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE); 00727 }
static int pause_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper for ast_monitor_pause.
Definition at line 392 of file res_monitor.c.
References ast_monitor_pause(), and chan.
Referenced by load_module().
00393 { 00394 return ast_monitor_pause(chan); 00395 }
static int start_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Start monitoring a channel by manager connection.
Definition at line 569 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), ast_strdupa, ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), format, ast_channel::name, name, s, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00570 { 00571 struct ast_channel *c = NULL; 00572 const char *name = astman_get_header(m, "Channel"); 00573 const char *fname = astman_get_header(m, "File"); 00574 const char *format = astman_get_header(m, "Format"); 00575 const char *mix = astman_get_header(m, "Mix"); 00576 char *d; 00577 00578 if (ast_strlen_zero(name)) { 00579 astman_send_error(s, m, "No channel specified"); 00580 return 0; 00581 } 00582 c = ast_get_channel_by_name_locked(name); 00583 if (!c) { 00584 astman_send_error(s, m, "No such channel"); 00585 return 0; 00586 } 00587 00588 if (ast_strlen_zero(fname)) { 00589 /* No filename base specified, default to channel name as per CLI */ 00590 fname = ast_strdupa(c->name); 00591 /* Channels have the format technology/channel_name - have to replace that / */ 00592 if ((d = strchr(fname, '/'))) 00593 *d = '-'; 00594 } 00595 00596 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) { 00597 if (ast_monitor_change_fname(c, fname, 1)) { 00598 astman_send_error(s, m, "Could not start monitoring channel"); 00599 ast_channel_unlock(c); 00600 return 0; 00601 } 00602 } 00603 00604 if (ast_true(mix)) { 00605 ast_monitor_setjoinfiles(c, 1); 00606 } 00607 00608 ast_channel_unlock(c); 00609 astman_send_ack(s, m, "Started monitoring channel"); 00610 return 0; 00611 }
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 459 of file res_monitor.c.
References AST_APP_ARG, ast_cdr_alloc(), ast_cdr_setuserfield(), AST_DECLARE_APP_ARGS, ast_log(), ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_channel::cdr, chan, format, ast_channel_monitor::joinfiles, LOG_ERROR, LOG_WARNING, parse(), pbx_builtin_setvar_helper(), urlprefix, X_JOIN, X_REC_IN, and X_REC_OUT.
Referenced by load_module().
00460 { 00461 char *arg = NULL; 00462 char *options = NULL; 00463 char *delay = NULL; 00464 char *urlprefix = NULL; 00465 char tmp[256]; 00466 int stream_action = X_REC_IN | X_REC_OUT; 00467 int joinfiles = 0; 00468 int waitforbridge = 0; 00469 int res = 0; 00470 char *parse; 00471 AST_DECLARE_APP_ARGS(args, 00472 AST_APP_ARG(format); 00473 AST_APP_ARG(fname_base); 00474 AST_APP_ARG(options); 00475 ); 00476 00477 /* Parse arguments. */ 00478 if (ast_strlen_zero((char*)data)) { 00479 ast_log(LOG_ERROR, "Monitor requires an argument\n"); 00480 return 0; 00481 } 00482 00483 parse = ast_strdupa((char*)data); 00484 AST_STANDARD_APP_ARGS(args, parse); 00485 00486 if (!ast_strlen_zero(args.options)) { 00487 if (strchr(args.options, 'm')) 00488 stream_action |= X_JOIN; 00489 if (strchr(args.options, 'b')) 00490 waitforbridge = 1; 00491 if (strchr(args.options, 'i')) 00492 stream_action &= ~X_REC_IN; 00493 if (strchr(args.options, 'o')) 00494 stream_action &= ~X_REC_OUT; 00495 } 00496 00497 arg = strchr(args.format, ':'); 00498 if (arg) { 00499 *arg++ = 0; 00500 urlprefix = arg; 00501 } 00502 00503 if (urlprefix) { 00504 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base, 00505 ((strcmp(args.format, "gsm")) ? "wav" : "gsm")); 00506 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) 00507 return -1; 00508 ast_cdr_setuserfield(chan, tmp); 00509 } 00510 if (waitforbridge) { 00511 /* We must remove the "b" option if listed. In principle none of 00512 the following could give NULL results, but we check just to 00513 be pedantic. Reconstructing with checks for 'm' option does not 00514 work if we end up adding more options than 'm' in the future. */ 00515 delay = ast_strdupa(data); 00516 options = strrchr(delay, ','); 00517 if (options) { 00518 arg = strchr(options, 'b'); 00519 if (arg) { 00520 *arg = 'X'; 00521 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay); 00522 } 00523 } 00524 return 0; 00525 } 00526 00527 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action); 00528 if (res < 0) 00529 res = ast_monitor_change_fname(chan, args.fname_base, 1); 00530 00531 if (stream_action & X_JOIN) { 00532 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT)) 00533 joinfiles = 1; 00534 else 00535 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n"); 00536 } 00537 ast_monitor_setjoinfiles(chan, joinfiles); 00538 00539 return res; 00540 }
static int stop_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Stop monitoring a channel by manager connection.
Definition at line 619 of file res_monitor.c.
References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_stop(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), name, and s.
Referenced by load_module().
00620 { 00621 struct ast_channel *c = NULL; 00622 const char *name = astman_get_header(m, "Channel"); 00623 int res; 00624 if (ast_strlen_zero(name)) { 00625 astman_send_error(s, m, "No channel specified"); 00626 return 0; 00627 } 00628 c = ast_get_channel_by_name_locked(name); 00629 if (!c) { 00630 astman_send_error(s, m, "No such channel"); 00631 return 0; 00632 } 00633 res = ast_monitor_stop(c, 1); 00634 ast_channel_unlock(c); 00635 if (res) { 00636 astman_send_error(s, m, "Could not stop monitoring channel"); 00637 return 0; 00638 } 00639 astman_send_ack(s, m, "Stopped monitoring channel"); 00640 return 0; 00641 }
static int stop_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper function.
Definition at line 543 of file res_monitor.c.
References ast_monitor_stop(), and chan.
Referenced by load_module().
00544 { 00545 return ast_monitor_stop(chan, 1); 00546 }
static int unload_module | ( | void | ) | [static] |
Definition at line 757 of file res_monitor.c.
References ast_manager_unregister(), and ast_unregister_application().
00758 { 00759 ast_unregister_application("Monitor"); 00760 ast_unregister_application("StopMonitor"); 00761 ast_unregister_application("ChangeMonitor"); 00762 ast_unregister_application("PauseMonitor"); 00763 ast_unregister_application("UnpauseMonitor"); 00764 ast_manager_unregister("Monitor"); 00765 ast_manager_unregister("StopMonitor"); 00766 ast_manager_unregister("ChangeMonitor"); 00767 ast_manager_unregister("PauseMonitor"); 00768 ast_manager_unregister("UnpauseMonitor"); 00769 00770 return 0; 00771 }
static int unpause_monitor_action | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Definition at line 735 of file res_monitor.c.
References do_pause_or_unpause(), and s.
Referenced by load_module().
00736 { 00737 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE); 00738 }
static int unpause_monitor_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Wrapper for ast_monitor_unpause.
Definition at line 398 of file res_monitor.c.
References ast_monitor_unpause(), and chan.
Referenced by load_module().
00399 { 00400 return ast_monitor_unpause(chan); 00401 }
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 777 of file res_monitor.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 777 of file res_monitor.c.
char change_monitor_action_help[] [static] |
Definition at line 643 of file res_monitor.c.
char* changemonitor_descrip [static] |
Initial value:
" ChangeMonitor(filename_base):\n" "Changes monitoring filename of a channel. Has no effect if the channel is not monitored.\n" "The argument is the new filename base to use for monitoring this channel.\n"
Definition at line 102 of file res_monitor.c.
char* changemonitor_synopsis = "Change monitoring filename of a channel" [static] |
Definition at line 100 of file res_monitor.c.
char* monitor_descrip [static] |
Definition at line 63 of file res_monitor.c.
char* monitor_synopsis = "Monitor a channel" [static] |
Definition at line 61 of file res_monitor.c.
ast_mutex_t monitorlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
char pause_monitor_action_help[] [static] |
Initial value:
"Description: The 'PauseMonitor' action may be used to temporarily stop the\n" " recording of a channel. The following parameters may\n" " be used to control this:\n" " Channel - Required. Used to specify the channel to record.\n"
Definition at line 718 of file res_monitor.c.
char* pausemonitor_descrip [static] |
Initial value:
" PauseMonitor():\n" "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n"
Definition at line 108 of file res_monitor.c.
char* pausemonitor_synopsis = "Pause monitoring of a channel" [static] |
Definition at line 106 of file res_monitor.c.
unsigned long seq = 0 [static] |
Definition at line 59 of file res_monitor.c.
char start_monitor_action_help[] [static] |
Definition at line 554 of file res_monitor.c.
char stop_monitor_action_help[] [static] |
Initial value:
"Description: The 'StopMonitor' action may be used to end a previously\n" " started 'Monitor' action. The only parameter is 'Channel', the name\n" " of the channel monitored.\n"
Definition at line 613 of file res_monitor.c.
char* stopmonitor_descrip [static] |
Initial value:
" StopMonitor():\n" "Stops monitoring a channel. Has no effect if the channel is not monitored\n"
Definition at line 97 of file res_monitor.c.
char* stopmonitor_synopsis = "Stop monitoring a channel" [static] |
Definition at line 95 of file res_monitor.c.
char unpause_monitor_action_help[] [static] |
Initial value:
"Description: The 'UnpauseMonitor' action may be used to re-enable recording\n" " of a channel after calling PauseMonitor. The following parameters may\n" " be used to control this:\n" " Channel - Required. Used to specify the channel to record.\n"
Definition at line 729 of file res_monitor.c.
char* unpausemonitor_descrip [static] |
Initial value:
" UnpauseMonitor():\n" "Unpauses monitoring of a channel on which monitoring had\n" "previously been paused with PauseMonitor.\n"
Definition at line 113 of file res_monitor.c.
char* unpausemonitor_synopsis = "Unpause monitoring of a channel" [static] |
Definition at line 111 of file res_monitor.c.