Fri Jul 24 00:41:56 2009

Asterisk developer's documentation


res_monitor.c File Reference

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 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_infoast_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"


Detailed Description

PBX channel monitoring.

Author:
Mark Spencer <markster@digium.com>

Definition in file res_monitor.c.


Define Documentation

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


Enumeration Type Documentation

enum MONITOR_PAUSING_ACTION

Enumerator:
MONITOR_ACTION_PAUSE 
MONITOR_ACTION_UNPAUSE 

Definition at line 686 of file res_monitor.c.

00687 {
00688    MONITOR_ACTION_PAUSE,
00689    MONITOR_ACTION_UNPAUSE
00690 };


Function Documentation

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.

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, 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.

Parameters:
chan 
state monitor state
Return values:
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().

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, 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.

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, 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.

See also:
ast_monitor_change_fname

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.

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

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.

Parameters:
chan 
data arguments passed fname|options
Return values:
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.

See also:
ast_monitor_stop

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 }


Variable Documentation

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]

Definition at line 47 of file res_monitor.c.

Referenced by ast_monitor_start().

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.


Generated on Fri Jul 24 00:41:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7