Thu Jul 9 13:41:24 2009

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

Defines

#define X_JOIN   4
#define X_REC_IN   1
#define X_REC_OUT   2

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) attribute_weak
 Change monitored filename of channel.
int ast_monitor_pause (struct ast_channel *chan) attribute_weak
 Pause monitoring of channel.
void ast_monitor_setjoinfiles (struct ast_channel *chan, int turnon) attribute_weak
int ast_monitor_start (struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock, int stream_action) attribute_weak
 Start monitoring a channel.
int ast_monitor_stop (struct ast_channel *chan, int need_lock) attribute_weak
 Stop monitoring channel.
int ast_monitor_unpause (struct ast_channel *chan) attribute_weak
 Unpause monitoring of channel.


Detailed Description

Channel monitoring.

Definition in file monitor.h.


Define Documentation

#define X_JOIN   4

Definition at line 36 of file monitor.h.

Referenced by start_monitor_exec().

#define X_REC_IN   1

Definition at line 34 of file monitor.h.

Referenced by __agent_start_monitoring(), ast_monitor_start(), start_monitor_action(), and start_monitor_exec().

#define X_REC_OUT   2

Definition at line 35 of file monitor.h.

Referenced by __agent_start_monitoring(), ast_monitor_start(), start_monitor_action(), and start_monitor_exec().


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 
)

Change monitored filename of channel.

Parameters:
chan 
fname_base new filename
need_lock 
Return values:
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, ast_channel::name, 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 }

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(), and start_monitor_exec().

00681 {
00682    if (chan->monitor)
00683       chan->monitor->joinfiles = turnon;
00684 }

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.

Parameters:
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
Return values:
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, ast_channel::monitor, monitor, monitorlock, name, ast_channel::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(), and start_monitor_exec().

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.

Parameters:
chan 
need_lock Stop the recording, close any open streams, mix in/out channels if required
Returns:
Always 0

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, ast_channel_monitor::format, format, get_soxmix_format(), ast_channel_monitor::joinfiles, LOCK_IF_NEEDED, LOG_WARNING, manager_event, ast_channel::monitor, name, ast_channel::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 }


Generated on Thu Jul 9 13:41:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7