Sat Aug 6 00:40:03 2011

Asterisk developer's documentation


res_monitor.c File Reference

PBX channel monitoring. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <libgen.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/logger.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 IS_NULL_STRING(string)   ((!(string)) || (ast_strlen_zero((string))))
#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)
int ast_monitor_pause (struct ast_channel *chan)
static int ast_monitor_set_state (struct ast_channel *chan, int state)
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)
static int change_monitor_action (struct mansession *s, const struct message *m)
static int change_monitor_exec (struct ast_channel *chan, void *data)
static int do_pause_or_unpause (struct mansession *s, const struct message *m, int action)
static const char * get_soxmix_format (const char *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)
static int start_monitor_action (struct mansession *s, const struct message *m)
static int start_monitor_exec (struct ast_channel *chan, void *data)
static int stop_monitor_action (struct mansession *s, const struct message *m)
static int stop_monitor_exec (struct ast_channel *chan, void *data)
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)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static const 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_MUTEX_INITIALIZER )
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 IS_NULL_STRING ( string   )     ((!(string)) || (ast_strlen_zero((string))))

Definition at line 658 of file res_monitor.c.

Referenced by do_pause_or_unpause().

#define LOCK_IF_NEEDED ( lock,
needed   ) 

Value:

do { \
   if (needed) \
      ast_channel_lock(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().

#define UNLOCK_IF_NEEDED ( lock,
needed   ) 

Value:

do { \
   if (needed) \
      ast_channel_unlock(lock); \
   } while (0)

Definition at line 59 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 660 of file res_monitor.c.

00661 {
00662    MONITOR_ACTION_PAUSE,
00663    MONITOR_ACTION_UNPAUSE
00664 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 751 of file res_monitor.c.

static void __unreg_module ( void   )  [static]

Definition at line 751 of file res_monitor.c.

int ast_monitor_change_fname ( struct ast_channel chan,
const char *  fname_base,
int  need_lock 
)

Definition at line 371 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, name, ast_channel::name, option_debug, strdup, and UNLOCK_IF_NEEDED.

Referenced by change_monitor_action(), change_monitor_exec(), start_monitor_action(), and start_monitor_exec().

00372 {
00373    char tmp[256];
00374    if (ast_strlen_zero(fname_base)) {
00375       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00376       return -1;
00377    }
00378 
00379    LOCK_IF_NEEDED(chan, need_lock);
00380 
00381    if (chan->monitor) {
00382       int directory = strchr(fname_base, '/') ? 1 : 0;
00383       const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;
00384       const char *absolute_suffix = *fname_base == '/' ? "" : "/";
00385       char tmpstring[sizeof(chan->monitor->filename_base)] = "";
00386       int i, fd[2] = { -1, -1 }, doexit = 0;
00387 
00388       /* before continuing, see if we're trying to rename the file to itself... */
00389       snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base);
00390 
00391       /* try creating the directory just in case it doesn't exist */
00392       if (directory) {
00393          char *name = strdup(fname_base);
00394          snprintf(tmp, sizeof(tmp), "mkdir -p \"%s%s%s\"", absolute, absolute_suffix, dirname(name));
00395          free(name);
00396          ast_safe_system(tmp);
00397       }
00398 
00399       /*!\note We cannot just compare filenames, due to symlinks, relative
00400        * paths, and other possible filesystem issues.  We could use
00401        * realpath(3), but its use is discouraged.  However, if we try to
00402        * create the same file from two different paths, the second will
00403        * fail, and so we have our notification that the filenames point to
00404        * the same path.
00405        *
00406        * Remember, also, that we're using the basename of the file (i.e.
00407        * the file without the format suffix), so it does not already exist
00408        * and we aren't interfering with the recording itself.
00409        */
00410       if (option_debug > 2) {
00411          ast_log(LOG_DEBUG, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base);
00412       }
00413       if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
00414          (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
00415          if (fd[0] < 0) {
00416             ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));
00417          } else {
00418             if (option_debug > 2) {
00419                ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n");
00420             }
00421          }
00422          doexit = 1;
00423       }
00424 
00425       /* Cleanup temporary files */
00426       for (i = 0; i < 2; i++) {
00427          if (fd[i] >= 0) {
00428             while (close(fd[i]) < 0 && errno == EINTR);
00429          }
00430       }
00431       unlink(tmpstring);
00432       /* if previous monitor file existed in a subdirectory, the directory will not be removed */
00433       unlink(chan->monitor->filename_base);
00434 
00435       if (doexit) {
00436          UNLOCK_IF_NEEDED(chan, need_lock);
00437          return 0;
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  ) 

Definition at line 349 of file res_monitor.c.

References AST_MONITOR_PAUSED, and ast_monitor_set_state().

Referenced by do_pause_or_unpause(), and pause_monitor_exec().

00350 {
00351    return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00352 }

static int ast_monitor_set_state ( struct ast_channel chan,
int  state 
) [static]

Definition at line 119 of file res_monitor.c.

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

00120 {
00121    LOCK_IF_NEEDED(chan, 1);
00122    if (!chan->monitor) {
00123       UNLOCK_IF_NEEDED(chan, 1);
00124       return -1;
00125    }
00126    chan->monitor->state = state;
00127    UNLOCK_IF_NEEDED(chan, 1);
00128    return 0;
00129 }

void ast_monitor_setjoinfiles ( struct ast_channel chan,
int  turnon 
)

Definition at line 652 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().

00653 {
00654    if (chan->monitor)
00655       chan->monitor->joinfiles = turnon;
00656 }

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, monitor, ast_channel::monitor, monitorlock, ast_channel::name, 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 == '/' ? "" : ast_config_AST_MONITOR_DIR;
00161          const char *absolute_suffix = *fname_base == '/' ? "" : "/";
00162          /* try creating the directory just in case it doesn't exist */
00163          if (directory) {
00164             char *name = strdup(fname_base);
00165             snprintf(tmp, sizeof(tmp), "mkdir -p \"%s%s%s\"",
00166                      absolute, absolute_suffix, dirname(name));
00167             free(name);
00168             ast_safe_system(tmp);
00169          }
00170          snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in",
00171                   absolute, absolute_suffix, fname_base);
00172          snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",
00173                   absolute, absolute_suffix, fname_base);
00174          snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s",
00175                   absolute, absolute_suffix, fname_base);
00176       } else {
00177          ast_mutex_lock(&monitorlock);
00178          snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
00179                   ast_config_AST_MONITOR_DIR, seq);
00180          snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
00181                   ast_config_AST_MONITOR_DIR, seq);
00182          seq++;
00183          ast_mutex_unlock(&monitorlock);
00184 
00185          channel_name = ast_strdupa(chan->name);
00186          while ((p = strchr(channel_name, '/'))) {
00187             *p = '-';
00188          }
00189          snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00190                 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00191          monitor->filename_changed = 1;
00192       }
00193 
00194       monitor->stop = ast_monitor_stop;
00195 
00196       /* Determine file format */
00197       if (!ast_strlen_zero(format_spec)) {
00198          monitor->format = strdup(format_spec);
00199       } else {
00200          monitor->format = strdup("wav");
00201       }
00202       
00203       /* open files */
00204       if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) {
00205          ast_filedelete(monitor->read_filename, NULL);
00206       }
00207       if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00208                   monitor->format, NULL,
00209                   O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
00210          ast_log(LOG_WARNING, "Could not create file %s\n",
00211                   monitor->read_filename);
00212          free(monitor);
00213          UNLOCK_IF_NEEDED(chan, need_lock);
00214          return -1;
00215       }
00216       if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00217          ast_filedelete(monitor->write_filename, NULL);
00218       }
00219       if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00220                   monitor->format, NULL,
00221                   O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
00222          ast_log(LOG_WARNING, "Could not create file %s\n",
00223                   monitor->write_filename);
00224          ast_closestream(monitor->read_stream);
00225          free(monitor);
00226          UNLOCK_IF_NEEDED(chan, need_lock);
00227          return -1;
00228       }
00229       chan->monitor = monitor;
00230       ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00231       /* so we know this call has been monitored in case we need to bill for it or something */
00232       pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00233    } else {
00234       ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n",
00235                chan->name);
00236       res = -1;
00237    }
00238 
00239    UNLOCK_IF_NEEDED(chan, need_lock);
00240 
00241    return res;
00242 }

int ast_monitor_stop ( struct ast_channel chan,
int  need_lock 
)

Definition at line 262 of file res_monitor.c.

References ast_closestream(), 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, format, ast_channel_monitor::format, free, get_soxmix_format(), ast_channel_monitor::joinfiles, LOCK_IF_NEEDED, LOG_DEBUG, LOG_WARNING, ast_channel::monitor, pbx_builtin_getvar_helper(), pbx_builtin_setvar_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().

00263 {
00264    int delfiles = 0;
00265 
00266    LOCK_IF_NEEDED(chan, need_lock);
00267 
00268    if (chan->monitor) {
00269       char filename[ FILENAME_MAX ];
00270 
00271       if (chan->monitor->read_stream) {
00272          ast_closestream(chan->monitor->read_stream);
00273       }
00274       if (chan->monitor->write_stream) {
00275          ast_closestream(chan->monitor->write_stream);
00276       }
00277 
00278       if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00279          if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00280             snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00281             if (ast_fileexists(filename, NULL, NULL) > 0) {
00282                ast_filedelete(filename, NULL);
00283             }
00284             ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00285          } else {
00286             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00287          }
00288 
00289          if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00290             snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00291             if (ast_fileexists(filename, NULL, NULL) > 0) {
00292                ast_filedelete(filename, NULL);
00293             }
00294             ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00295          } else {
00296             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00297          }
00298       }
00299 
00300       if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00301          char tmp[1024];
00302          char tmp2[1024];
00303          const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00304          char *fname_base = chan->monitor->filename_base;
00305          const char *execute, *execute_args;
00306          /* at this point, fname_base really is the full path */
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-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &",
00325             execute, fname_base, format, fname_base, format, fname_base, format,execute_args);
00326          if (delfiles) {
00327             snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base); /* remove legs when done mixing */
00328             ast_copy_string(tmp, tmp2, sizeof(tmp));
00329          }
00330          ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
00331          if (ast_safe_system(tmp) == -1)
00332             ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00333       }
00334       
00335       free(chan->monitor->format);
00336       free(chan->monitor);
00337       chan->monitor = NULL;
00338       pbx_builtin_setvar_helper(chan, "MONITORED", NULL);
00339    }
00340    pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL);
00341 
00342    UNLOCK_IF_NEEDED(chan, need_lock);
00343 
00344    return 0;
00345 }

int ast_monitor_unpause ( struct ast_channel chan  ) 

Definition at line 355 of file res_monitor.c.

References AST_MONITOR_RUNNING, and ast_monitor_set_state().

Referenced by do_pause_or_unpause(), and unpause_monitor_exec().

00356 {
00357    return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00358 }

static int change_monitor_action ( struct mansession s,
const struct message m 
) [static]

Definition at line 624 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().

00625 {
00626    struct ast_channel *c = NULL;
00627    const char *name = astman_get_header(m, "Channel");
00628    const char *fname = astman_get_header(m, "File");
00629    if (ast_strlen_zero(name)) {
00630       astman_send_error(s, m, "No channel specified");
00631       return 0;
00632    }
00633    if (ast_strlen_zero(fname)) {
00634       astman_send_error(s, m, "No filename specified");
00635       return 0;
00636    }
00637    c = ast_get_channel_by_name_locked(name);
00638    if (!c) {
00639       astman_send_error(s, m, "No such channel");
00640       return 0;
00641    }
00642    if (ast_monitor_change_fname(c, fname, 1)) {
00643       astman_send_error(s, m, "Could not change monitored filename of channel");
00644       ast_channel_unlock(c);
00645       return 0;
00646    }
00647    ast_channel_unlock(c);
00648    astman_send_ack(s, m, "Changed monitor filename");
00649    return 0;
00650 }

static int change_monitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 524 of file res_monitor.c.

References ast_monitor_change_fname().

Referenced by load_module().

00525 {
00526    return ast_monitor_change_fname(chan, (const char*)data, 1);
00527 }

static int do_pause_or_unpause ( struct mansession s,
const struct message m,
int  action 
) [static]

Definition at line 666 of file res_monitor.c.

References ast_channel_unlock, ast_get_channel_by_name_locked(), ast_monitor_pause(), ast_monitor_unpause(), astman_get_header(), astman_send_ack(), astman_send_error(), IS_NULL_STRING, MONITOR_ACTION_PAUSE, name, and s.

Referenced by pause_monitor_action(), and unpause_monitor_action().

00667 {
00668    struct ast_channel *c = NULL;
00669    const char *name = astman_get_header(m, "Channel");
00670    
00671    if (IS_NULL_STRING(name)) {
00672       astman_send_error(s, m, "No channel specified");
00673       return -1;
00674    }
00675    
00676    c = ast_get_channel_by_name_locked(name);
00677    if (!c) {
00678       astman_send_error(s, m, "No such channel");
00679       return -1;
00680    }
00681 
00682    if (action == MONITOR_ACTION_PAUSE)
00683       ast_monitor_pause(c);
00684    else
00685       ast_monitor_unpause(c);
00686    
00687    ast_channel_unlock(c);
00688    astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00689    return 0;   
00690 }

static const char* get_soxmix_format ( const char *  format  )  [static]

Definition at line 249 of file res_monitor.c.

Referenced by ast_monitor_stop().

00250 {
00251    const char *res = format;
00252 
00253    if (!strcasecmp(format,"ulaw"))
00254       res = "ul";
00255    if (!strcasecmp(format,"alaw"))
00256       res = "al";
00257    
00258    return res;
00259 }

static int load_module ( void   )  [static]

Definition at line 715 of file res_monitor.c.

References ast_manager_register2(), 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 698 of file res_monitor.c.

References do_pause_or_unpause(), MONITOR_ACTION_PAUSE, and s.

Referenced by load_module().

00699 {
00700    return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00701 }

static int pause_monitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 360 of file res_monitor.c.

References ast_monitor_pause().

Referenced by load_module().

00361 {
00362    return ast_monitor_pause(chan);
00363 }

static int start_monitor_action ( struct mansession s,
const struct message m 
) [static]

Definition at line 543 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, and s.

Referenced by load_module().

00544 {
00545    struct ast_channel *c = NULL;
00546    const char *name = astman_get_header(m, "Channel");
00547    const char *fname = astman_get_header(m, "File");
00548    const char *format = astman_get_header(m, "Format");
00549    const char *mix = astman_get_header(m, "Mix");
00550    char *d;
00551    
00552    if (ast_strlen_zero(name)) {
00553       astman_send_error(s, m, "No channel specified");
00554       return 0;
00555    }
00556    c = ast_get_channel_by_name_locked(name);
00557    if (!c) {
00558       astman_send_error(s, m, "No such channel");
00559       return 0;
00560    }
00561 
00562    if (ast_strlen_zero(fname)) {
00563       /* No filename base specified, default to channel name as per CLI */    
00564       fname = ast_strdupa(c->name);
00565       /* Channels have the format technology/channel_name - have to replace that /  */
00566       if ((d = strchr(fname, '/'))) 
00567          *d = '-';
00568    }
00569    
00570    if (ast_monitor_start(c, format, fname, 1)) {
00571       if (ast_monitor_change_fname(c, fname, 1)) {
00572          astman_send_error(s, m, "Could not start monitoring channel");
00573          ast_channel_unlock(c);
00574          return 0;
00575       }
00576    }
00577 
00578    if (ast_true(mix)) {
00579       ast_monitor_setjoinfiles(c, 1);
00580    }
00581 
00582    ast_channel_unlock(c);
00583    astman_send_ack(s, m, "Started monitoring channel");
00584    return 0;
00585 }

static int start_monitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 451 of file res_monitor.c.

References ast_cdr_alloc(), ast_cdr_setuserfield(), ast_monitor_change_fname(), ast_monitor_setjoinfiles(), ast_monitor_start(), ast_strdupa, ast_strlen_zero(), ast_channel::cdr, format, ast_channel_monitor::joinfiles, pbx_builtin_setvar_helper(), and urlprefix.

Referenced by load_module().

00452 {
00453    char *arg = NULL;
00454    char *format = NULL;
00455    char *fname_base = NULL;
00456    char *options = NULL;
00457    char *delay = NULL;
00458    char *urlprefix = NULL;
00459    char tmp[256];
00460    int joinfiles = 0;
00461    int waitforbridge = 0;
00462    int res = 0;
00463    
00464    /* Parse arguments. */
00465    if (!ast_strlen_zero((char*)data)) {
00466       arg = ast_strdupa((char*)data);
00467       format = arg;
00468       fname_base = strchr(arg, '|');
00469       if (fname_base) {
00470          *fname_base = 0;
00471          fname_base++;
00472          if ((options = strchr(fname_base, '|'))) {
00473             *options = 0;
00474             options++;
00475             if (strchr(options, 'm'))
00476                joinfiles = 1;
00477             if (strchr(options, 'b'))
00478                waitforbridge = 1;
00479          }
00480       }
00481       arg = strchr(format,':');
00482       if (arg) {
00483          *arg++ = 0;
00484          urlprefix = arg;
00485       }
00486    }
00487    if (urlprefix) {
00488       snprintf(tmp,sizeof(tmp) - 1,"%s/%s.%s",urlprefix,fname_base,
00489          ((strcmp(format,"gsm")) ? "wav" : "gsm"));
00490       if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00491          return -1;
00492       ast_cdr_setuserfield(chan, tmp);
00493    }
00494    if (waitforbridge) {
00495       /* We must remove the "b" option if listed.  In principle none of
00496          the following could give NULL results, but we check just to
00497          be pedantic. Reconstructing with checks for 'm' option does not
00498          work if we end up adding more options than 'm' in the future. */
00499       delay = ast_strdupa(data);
00500       options = strrchr(delay, '|');
00501       if (options) {
00502          arg = strchr(options, 'b');
00503          if (arg) {
00504             *arg = 'X';
00505             pbx_builtin_setvar_helper(chan,"AUTO_MONITOR",delay);
00506          }
00507       }
00508       return 0;
00509    }
00510 
00511    res = ast_monitor_start(chan, format, fname_base, 1);
00512    if (res < 0)
00513       res = ast_monitor_change_fname(chan, fname_base, 1);
00514    ast_monitor_setjoinfiles(chan, joinfiles);
00515 
00516    return res;
00517 }

static int stop_monitor_action ( struct mansession s,
const struct message m 
) [static]

Definition at line 592 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().

00593 {
00594    struct ast_channel *c = NULL;
00595    const char *name = astman_get_header(m, "Channel");
00596    int res;
00597    if (ast_strlen_zero(name)) {
00598       astman_send_error(s, m, "No channel specified");
00599       return 0;
00600    }
00601    c = ast_get_channel_by_name_locked(name);
00602    if (!c) {
00603       astman_send_error(s, m, "No such channel");
00604       return 0;
00605    }
00606    res = ast_monitor_stop(c, 1);
00607    ast_channel_unlock(c);
00608    if (res) {
00609       astman_send_error(s, m, "Could not stop monitoring channel");
00610       return 0;
00611    }
00612    astman_send_ack(s, m, "Stopped monitoring channel");
00613    return 0;
00614 }

static int stop_monitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 519 of file res_monitor.c.

References ast_monitor_stop().

Referenced by load_module().

00520 {
00521    return ast_monitor_stop(chan, 1);
00522 }

static int unload_module ( void   )  [static]

Definition at line 731 of file res_monitor.c.

References ast_manager_unregister(), and ast_unregister_application().

00732 {
00733    ast_unregister_application("Monitor");
00734    ast_unregister_application("StopMonitor");
00735    ast_unregister_application("ChangeMonitor");
00736    ast_unregister_application("PauseMonitor");
00737    ast_unregister_application("UnpauseMonitor");
00738    ast_manager_unregister("Monitor");
00739    ast_manager_unregister("StopMonitor");
00740    ast_manager_unregister("ChangeMonitor");
00741    ast_manager_unregister("PauseMonitor");
00742    ast_manager_unregister("UnpauseMonitor");
00743 
00744    return 0;
00745 }

static int unpause_monitor_action ( struct mansession s,
const struct message m 
) [static]

Definition at line 709 of file res_monitor.c.

References do_pause_or_unpause(), and s.

Referenced by load_module().

00710 {
00711    return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00712 }

static int unpause_monitor_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 365 of file res_monitor.c.

References ast_monitor_unpause().

Referenced by load_module().

00366 {
00367    return ast_monitor_unpause(chan);
00368 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 751 of file res_monitor.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 751 of file res_monitor.c.

char change_monitor_action_help[] [static]

Definition at line 616 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 104 of file res_monitor.c.

char* changemonitor_synopsis = "Change monitoring filename of a channel" [static]

Definition at line 102 of file res_monitor.c.

char* monitor_descrip [static]

Definition at line 68 of file res_monitor.c.

char* monitor_synopsis = "Monitor a channel" [static]

Definition at line 66 of file res_monitor.c.

ast_mutex_t monitorlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 52 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 692 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 110 of file res_monitor.c.

char* pausemonitor_synopsis = "Pause monitoring of a channel" [static]

Definition at line 108 of file res_monitor.c.

unsigned long seq = 0 [static]

Definition at line 64 of file res_monitor.c.

char start_monitor_action_help[] [static]

Definition at line 529 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 587 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 99 of file res_monitor.c.

char* stopmonitor_synopsis = "Stop monitoring a channel" [static]

Definition at line 97 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 703 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 115 of file res_monitor.c.

char* unpausemonitor_synopsis = "Unpause monitoring of a channel" [static]

Definition at line 113 of file res_monitor.c.


Generated on Sat Aug 6 00:40:03 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7