#include "asterisk/channel.h"
Go to the source code of this file.
Data Structures | |
struct | ast_channel_monitor |
Enumerations | |
enum | AST_MONITORING_STATE { AST_MONITOR_RUNNING, AST_MONITOR_PAUSED } |
Functions | |
int | ast_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock) |
int | ast_monitor_pause (struct ast_channel *chan) |
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 | ast_monitor_stop (struct ast_channel *chan, int need_lock) |
int | ast_monitor_unpause (struct ast_channel *chan) |
Definition in file monitor.h.
enum AST_MONITORING_STATE |
Definition at line 28 of file monitor.h.
00028 { 00029 AST_MONITOR_RUNNING, 00030 AST_MONITOR_PAUSED 00031 };
int ast_monitor_change_fname | ( | struct ast_channel * | chan, | |
const char * | fname_base, | |||
int | need_lock | |||
) |
Definition at line 368 of file res_monitor.c.
References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_log(), ast_safe_system(), ast_strlen_zero(), errno, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, free, LOCK_IF_NEEDED, LOG_DEBUG, LOG_ERROR, LOG_WARNING, ast_channel::monitor, ast_channel::name, name, option_debug, strdup, and UNLOCK_IF_NEEDED.
Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().
00369 { 00370 char tmp[256]; 00371 if (ast_strlen_zero(fname_base)) { 00372 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); 00373 return -1; 00374 } 00375 00376 LOCK_IF_NEEDED(chan, need_lock); 00377 00378 if (chan->monitor) { 00379 int directory = strchr(fname_base, '/') ? 1 : 0; 00380 const char *absolute = *fname_base == '/' ? "" : "/"; 00381 char tmpstring[sizeof(chan->monitor->filename_base)] = ""; 00382 int i, fd[2] = { -1, -1 }, doexit = 0; 00383 00384 /* before continuing, see if we're trying to rename the file to itself... */ 00385 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00386 00387 /*!\note We cannot just compare filenames, due to symlinks, relative 00388 * paths, and other possible filesystem issues. We could use 00389 * realpath(3), but its use is discouraged. However, if we try to 00390 * create the same file from two different paths, the second will 00391 * fail, and so we have our notification that the filenames point to 00392 * the same path. 00393 * 00394 * Remember, also, that we're using the basename of the file (i.e. 00395 * the file without the format suffix), so it does not already exist 00396 * and we aren't interfering with the recording itself. 00397 */ 00398 if (option_debug > 2) { 00399 ast_log(LOG_DEBUG, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base); 00400 } 00401 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 || 00402 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) { 00403 if (fd[0] < 0) { 00404 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno)); 00405 } else { 00406 if (option_debug > 2) { 00407 ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n"); 00408 } 00409 } 00410 doexit = 1; 00411 } 00412 00413 /* Cleanup temporary files */ 00414 for (i = 0; i < 2; i++) { 00415 if (fd[i] >= 0) { 00416 while (close(fd[i]) < 0 && errno == EINTR); 00417 } 00418 } 00419 unlink(tmpstring); 00420 unlink(chan->monitor->filename_base); 00421 00422 if (doexit) { 00423 UNLOCK_IF_NEEDED(chan, need_lock); 00424 return 0; 00425 } 00426 00427 /* try creating the directory just in case it doesn't exist */ 00428 if (directory) { 00429 char *name = strdup(fname_base); 00430 snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name)); 00431 free(name); 00432 ast_safe_system(tmp); 00433 } 00434 00435 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base)); 00436 chan->monitor->filename_changed = 1; 00437 } else { 00438 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base); 00439 } 00440 00441 UNLOCK_IF_NEEDED(chan, need_lock); 00442 00443 return 0; 00444 }
int ast_monitor_pause | ( | struct ast_channel * | chan | ) |
Definition at line 346 of file res_monitor.c.
References AST_MONITOR_PAUSED, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and pause_monitor_exec().
00347 { 00348 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED); 00349 }
void ast_monitor_setjoinfiles | ( | struct ast_channel * | chan, | |
int | turnon | |||
) |
Definition at line 647 of file res_monitor.c.
References ast_channel_monitor::joinfiles, and ast_channel::monitor.
Referenced by __agent_start_monitoring(), start_monitor_action(), and start_monitor_exec().
int ast_monitor_start | ( | struct ast_channel * | chan, | |
const char * | format_spec, | |||
const char * | fname_base, | |||
int | need_lock | |||
) |
Definition at line 132 of file res_monitor.c.
References ast_calloc, ast_closestream(), ast_config_AST_MONITOR_DIR, ast_filedelete(), ast_fileexists(), ast_log(), AST_MONITOR_RUNNING, ast_monitor_set_state(), ast_monitor_stop(), ast_mutex_lock, ast_mutex_unlock, ast_safe_system(), ast_strdupa, ast_strlen_zero(), ast_writefile(), errno, FILENAME_MAX, free, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, ast_channel::monitor, monitor, monitorlock, name, ast_channel::name, pbx_builtin_setvar_helper(), strdup, and UNLOCK_IF_NEEDED.
Referenced by __agent_start_monitoring(), start_monitor_action(), and start_monitor_exec().
00134 { 00135 int res = 0; 00136 char tmp[256]; 00137 00138 LOCK_IF_NEEDED(chan, need_lock); 00139 00140 if (!(chan->monitor)) { 00141 struct ast_channel_monitor *monitor; 00142 char *channel_name, *p; 00143 00144 /* Create monitoring directory if needed */ 00145 if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) { 00146 if (errno != EEXIST) { 00147 ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n", 00148 strerror(errno)); 00149 } 00150 } 00151 00152 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { 00153 UNLOCK_IF_NEEDED(chan, need_lock); 00154 return -1; 00155 } 00156 00157 /* Determine file names */ 00158 if (!ast_strlen_zero(fname_base)) { 00159 int directory = strchr(fname_base, '/') ? 1 : 0; 00160 const char *absolute = *fname_base == '/' ? "" : "/"; 00161 /* try creating the directory just in case it doesn't exist */ 00162 if (directory) { 00163 char *name = strdup(fname_base); 00164 snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name)); 00165 free(name); 00166 ast_safe_system(tmp); 00167 } 00168 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in", 00169 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00170 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out", 00171 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00172 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s", 00173 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base); 00174 } else { 00175 ast_mutex_lock(&monitorlock); 00176 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld", 00177 ast_config_AST_MONITOR_DIR, seq); 00178 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld", 00179 ast_config_AST_MONITOR_DIR, seq); 00180 seq++; 00181 ast_mutex_unlock(&monitorlock); 00182 00183 channel_name = ast_strdupa(chan->name); 00184 while ((p = strchr(channel_name, '/'))) { 00185 *p = '-'; 00186 } 00187 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s", 00188 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name); 00189 monitor->filename_changed = 1; 00190 } 00191 00192 monitor->stop = ast_monitor_stop; 00193 00194 /* Determine file format */ 00195 if (!ast_strlen_zero(format_spec)) { 00196 monitor->format = strdup(format_spec); 00197 } else { 00198 monitor->format = strdup("wav"); 00199 } 00200 00201 /* open files */ 00202 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) { 00203 ast_filedelete(monitor->read_filename, NULL); 00204 } 00205 if (!(monitor->read_stream = ast_writefile(monitor->read_filename, 00206 monitor->format, NULL, 00207 O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { 00208 ast_log(LOG_WARNING, "Could not create file %s\n", 00209 monitor->read_filename); 00210 free(monitor); 00211 UNLOCK_IF_NEEDED(chan, need_lock); 00212 return -1; 00213 } 00214 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) { 00215 ast_filedelete(monitor->write_filename, NULL); 00216 } 00217 if (!(monitor->write_stream = ast_writefile(monitor->write_filename, 00218 monitor->format, NULL, 00219 O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) { 00220 ast_log(LOG_WARNING, "Could not create file %s\n", 00221 monitor->write_filename); 00222 ast_closestream(monitor->read_stream); 00223 free(monitor); 00224 UNLOCK_IF_NEEDED(chan, need_lock); 00225 return -1; 00226 } 00227 chan->monitor = monitor; 00228 ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00229 /* so we know this call has been monitored in case we need to bill for it or something */ 00230 pbx_builtin_setvar_helper(chan, "__MONITORED","true"); 00231 } else { 00232 ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n", 00233 chan->name); 00234 res = -1; 00235 } 00236 00237 UNLOCK_IF_NEEDED(chan, need_lock); 00238 00239 return res; 00240 }
int ast_monitor_stop | ( | struct ast_channel * | chan, | |
int | need_lock | |||
) |
Definition at line 260 of file res_monitor.c.
References ast_closestream(), ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_filedelete(), ast_fileexists(), ast_filerename(), ast_log(), ast_safe_system(), ast_strlen_zero(), ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, ast_channel_monitor::format, format, free, get_soxmix_format(), ast_channel_monitor::joinfiles, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, 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(), builtin_automonitor(), stop_monitor_action(), and stop_monitor_exec().
00261 { 00262 int delfiles = 0; 00263 00264 LOCK_IF_NEEDED(chan, need_lock); 00265 00266 if (chan->monitor) { 00267 char filename[ FILENAME_MAX ]; 00268 00269 if (chan->monitor->read_stream) { 00270 ast_closestream(chan->monitor->read_stream); 00271 } 00272 if (chan->monitor->write_stream) { 00273 ast_closestream(chan->monitor->write_stream); 00274 } 00275 00276 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) { 00277 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) { 00278 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base); 00279 if (ast_fileexists(filename, NULL, NULL) > 0) { 00280 ast_filedelete(filename, NULL); 00281 } 00282 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format); 00283 } else { 00284 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename); 00285 } 00286 00287 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) { 00288 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base); 00289 if (ast_fileexists(filename, NULL, NULL) > 0) { 00290 ast_filedelete(filename, NULL); 00291 } 00292 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format); 00293 } else { 00294 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename); 00295 } 00296 } 00297 00298 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) { 00299 char tmp[1024]; 00300 char tmp2[1024]; 00301 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format; 00302 char *name = chan->monitor->filename_base; 00303 int directory = strchr(name, '/') ? 1 : 0; 00304 char *dir = directory ? "" : ast_config_AST_MONITOR_DIR; 00305 const char *execute, *execute_args; 00306 const char *absolute = *name == '/' ? "" : "/"; 00307 00308 /* Set the execute application */ 00309 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC"); 00310 if (ast_strlen_zero(execute)) { 00311 #ifdef HAVE_SOXMIX 00312 execute = "nice -n 19 soxmix"; 00313 #else 00314 execute = "nice -n 19 sox -m"; 00315 #endif 00316 format = get_soxmix_format(format); 00317 delfiles = 1; 00318 } 00319 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS"); 00320 if (ast_strlen_zero(execute_args)) { 00321 execute_args = ""; 00322 } 00323 00324 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); 00325 if (delfiles) { 00326 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */ 00327 ast_copy_string(tmp, tmp2, sizeof(tmp)); 00328 } 00329 ast_log(LOG_DEBUG,"monitor executing %s\n",tmp); 00330 if (ast_safe_system(tmp) == -1) 00331 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp); 00332 } 00333 00334 free(chan->monitor->format); 00335 free(chan->monitor); 00336 chan->monitor = NULL; 00337 } 00338 00339 UNLOCK_IF_NEEDED(chan, need_lock); 00340 00341 return 0; 00342 }
int ast_monitor_unpause | ( | struct ast_channel * | chan | ) |
Definition at line 352 of file res_monitor.c.
References AST_MONITOR_RUNNING, and ast_monitor_set_state().
Referenced by do_pause_or_unpause(), and unpause_monitor_exec().
00353 { 00354 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING); 00355 }