Tue Nov 16 17:07:43 2010

Asterisk developer's documentation


monitor.h File Reference

Channel monitoring. More...

#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)


Detailed Description

Channel monitoring.

Definition in file monitor.h.


Enumeration Type Documentation

enum AST_MONITORING_STATE

Enumerator:
AST_MONITOR_RUNNING 
AST_MONITOR_PAUSED 

Definition at line 28 of file monitor.h.

00028                           {
00029    AST_MONITOR_RUNNING,
00030    AST_MONITOR_PAUSED
00031 };


Function Documentation

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().

00648 {
00649    if (chan->monitor)
00650       chan->monitor->joinfiles = turnon;
00651 }

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 }


Generated on Tue Nov 16 17:07:43 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7