Thu Dec 17 17:41:03 2009

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 653 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 655 of file res_monitor.c.

00656 {
00657    MONITOR_ACTION_PAUSE,
00658    MONITOR_ACTION_UNPAUSE
00659 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 746 of file res_monitor.c.

static void __unreg_module ( void   )  [static]

Definition at line 746 of file res_monitor.c.

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

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 }

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 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, 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 == '/' ? "" : "/";
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",
00173                 ast_config_AST_MONITOR_DIR, 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, format, ast_channel_monitor::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 }

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

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

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

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

Definition at line 519 of file res_monitor.c.

References ast_monitor_change_fname().

Referenced by load_module().

00520 {
00521    return ast_monitor_change_fname(chan, (const char*)data, 1);
00522 }

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

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

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

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

Definition at line 247 of file res_monitor.c.

Referenced by ast_monitor_stop().

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

static int load_module ( void   )  [static]

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

References do_pause_or_unpause(), MONITOR_ACTION_PAUSE, and s.

Referenced by load_module().

00694 {
00695    return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00696 }

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

Definition at line 357 of file res_monitor.c.

References ast_monitor_pause().

Referenced by load_module().

00358 {
00359    return ast_monitor_pause(chan);
00360 }

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

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

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

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

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

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

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

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

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

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

Definition at line 514 of file res_monitor.c.

References ast_monitor_stop().

Referenced by load_module().

00515 {
00516    return ast_monitor_stop(chan, 1);
00517 }

static int unload_module ( void   )  [static]

Definition at line 726 of file res_monitor.c.

References ast_manager_unregister(), and ast_unregister_application().

00727 {
00728    ast_unregister_application("Monitor");
00729    ast_unregister_application("StopMonitor");
00730    ast_unregister_application("ChangeMonitor");
00731    ast_unregister_application("PauseMonitor");
00732    ast_unregister_application("UnpauseMonitor");
00733    ast_manager_unregister("Monitor");
00734    ast_manager_unregister("StopMonitor");
00735    ast_manager_unregister("ChangeMonitor");
00736    ast_manager_unregister("PauseMonitor");
00737    ast_manager_unregister("UnpauseMonitor");
00738 
00739    return 0;
00740 }

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

Definition at line 704 of file res_monitor.c.

References do_pause_or_unpause(), and s.

Referenced by load_module().

00705 {
00706    return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00707 }

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

Definition at line 362 of file res_monitor.c.

References ast_monitor_unpause().

Referenced by load_module().

00363 {
00364    return ast_monitor_unpause(chan);
00365 }


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 746 of file res_monitor.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 746 of file res_monitor.c.

char change_monitor_action_help[] [static]

Definition at line 611 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 687 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 524 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 582 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 698 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 Thu Dec 17 17:41:03 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7