Wed Oct 28 13:33:29 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"

Include dependency graph for res_monitor.c:

Go to the source code of this file.

Defines

#define AST_API_MODULE
#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_OPTIONAL_API_NAME() ast_monitor_change_fname (struct ast_channel *chan, const char *fname_base, int need_lock)
 Change monitored filename of channel.
int AST_OPTIONAL_API_NAME() 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_OPTIONAL_API_NAME() ast_monitor_setjoinfiles (struct ast_channel *chan, int turnon)
int AST_OPTIONAL_API_NAME() 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_OPTIONAL_API_NAME() ast_monitor_stop (struct ast_channel *chan, int need_lock)
 Stop monitoring channel.
int AST_OPTIONAL_API_NAME() 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, const char *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, const char *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, const char *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, const char *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, const char *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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static struct ast_module_infoast_module_info = &__mod_info
static ast_mutex_t monitorlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static unsigned long seq = 0


Detailed Description

PBX channel monitoring.

Author:
Mark Spencer <markster@digium.com>

Definition in file res_monitor.c.


Define Documentation

#define AST_API_MODULE

Definition at line 41 of file res_monitor.c.

#define LOCK_IF_NEEDED ( lock,
needed   ) 

Value:

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

Definition at line 244 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 249 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

Enumerator:
MONITOR_ACTION_PAUSE 
MONITOR_ACTION_UNPAUSE 

Definition at line 817 of file res_monitor.c.

00818 {
00819    MONITOR_ACTION_PAUSE,
00820    MONITOR_ACTION_UNPAUSE
00821 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 898 of file res_monitor.c.

static void __unreg_module ( void   )  [static]

Definition at line 898 of file res_monitor.c.

int AST_OPTIONAL_API_NAME() 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 550 of file res_monitor.c.

References ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_log(), ast_mkdir(), ast_strdupa, ast_strlen_zero(), 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().

00551 {
00552    if (ast_strlen_zero(fname_base)) {
00553       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00554       return -1;
00555    }
00556 
00557    LOCK_IF_NEEDED(chan, need_lock);
00558 
00559    if (chan->monitor) {
00560       int directory = strchr(fname_base, '/') ? 1 : 0;
00561       const char *absolute = *fname_base == '/' ? "" : "/";
00562       char tmpstring[sizeof(chan->monitor->filename_base)] = "";
00563 
00564       /* before continuing, see if we're trying to rename the file to itself... */
00565       snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00566       if (!strcmp(tmpstring, chan->monitor->filename_base)) {
00567          if (option_debug > 2)
00568             ast_log(LOG_DEBUG, "No need to rename monitor filename to itself\n");
00569          UNLOCK_IF_NEEDED(chan, need_lock);
00570          return 0;
00571       }
00572 
00573       /* try creating the directory just in case it doesn't exist */
00574       if (directory) {
00575          char *name = ast_strdupa(fname_base);
00576          ast_mkdir(dirname(name), 0777);
00577       }
00578 
00579       ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base));
00580       chan->monitor->filename_changed = 1;
00581    } else {
00582       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00583    }
00584 
00585    UNLOCK_IF_NEEDED(chan, need_lock);
00586 
00587    return 0;
00588 }

int AST_OPTIONAL_API_NAME() ast_monitor_pause ( struct ast_channel chan  ) 

Pause monitoring of channel.

Definition at line 519 of file res_monitor.c.

References AST_MONITOR_PAUSED, and ast_monitor_set_state().

Referenced by do_pause_or_unpause(), and pause_monitor_exec().

00520 {
00521    return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00522 }

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

00264 {
00265    LOCK_IF_NEEDED(chan, 1);
00266    if (!chan->monitor) {
00267       UNLOCK_IF_NEEDED(chan, 1);
00268       return -1;
00269    }
00270    chan->monitor->state = state;
00271    UNLOCK_IF_NEEDED(chan, 1);
00272    return 0;
00273 }

void AST_OPTIONAL_API_NAME() ast_monitor_setjoinfiles ( struct ast_channel chan,
int  turnon 
)

Definition at line 811 of file res_monitor.c.

References ast_channel_monitor::joinfiles, and ast_channel::monitor.

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

00812 {
00813    if (chan->monitor)
00814       chan->monitor->joinfiles = turnon;
00815 }

int AST_OPTIONAL_API_NAME() 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 286 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(), EVENT_FLAG_CALL, ast_channel_monitor::filename_base, ast_channel_monitor::filename_changed, FILENAME_MAX, ast_channel_monitor::format, LOCK_IF_NEEDED, LOG_WARNING, manager_event, monitor, ast_channel::monitor, monitorlock, ast_channel::name, name, pbx_builtin_setvar_helper(), ast_channel_monitor::read_filename, ast_channel_monitor::read_stream, ast_channel_monitor::stop, ast_channel::uniqueid, UNLOCK_IF_NEEDED, ast_channel_monitor::write_filename, ast_channel_monitor::write_stream, X_REC_IN, and X_REC_OUT.

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

00288 {
00289    int res = 0;
00290 
00291    LOCK_IF_NEEDED(chan, need_lock);
00292 
00293    if (!(chan->monitor)) {
00294       struct ast_channel_monitor *monitor;
00295       char *channel_name, *p;
00296 
00297       /* Create monitoring directory if needed */
00298       ast_mkdir(ast_config_AST_MONITOR_DIR, 0777);
00299 
00300       if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
00301          UNLOCK_IF_NEEDED(chan, need_lock);
00302          return -1;
00303       }
00304 
00305       /* Determine file names */
00306       if (!ast_strlen_zero(fname_base)) {
00307          int directory = strchr(fname_base, '/') ? 1 : 0;
00308          const char *absolute = *fname_base == '/' ? "" : "/";
00309          /* try creating the directory just in case it doesn't exist */
00310          if (directory) {
00311             char *name = ast_strdupa(fname_base);
00312             ast_mkdir(dirname(name), 0777);
00313          }
00314          snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in",
00315                   directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00316          snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",
00317                   directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00318          ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base));
00319       } else {
00320          ast_mutex_lock(&monitorlock);
00321          snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
00322                   ast_config_AST_MONITOR_DIR, seq);
00323          snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
00324                   ast_config_AST_MONITOR_DIR, seq);
00325          seq++;
00326          ast_mutex_unlock(&monitorlock);
00327 
00328          channel_name = ast_strdupa(chan->name);
00329          while ((p = strchr(channel_name, '/'))) {
00330             *p = '-';
00331          }
00332          snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00333                 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00334          monitor->filename_changed = 1;
00335       }
00336 
00337       monitor->stop = ast_monitor_stop;
00338 
00339       /* Determine file format */
00340       if (!ast_strlen_zero(format_spec)) {
00341          monitor->format = ast_strdup(format_spec);
00342       } else {
00343          monitor->format = ast_strdup("wav");
00344       }
00345       
00346       /* open files */
00347       if (stream_action & X_REC_IN) {
00348          if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0)
00349             ast_filedelete(monitor->read_filename, NULL);
00350          if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00351                      monitor->format, NULL,
00352                      O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00353             ast_log(LOG_WARNING, "Could not create file %s\n",
00354                      monitor->read_filename);
00355             ast_free(monitor);
00356             UNLOCK_IF_NEEDED(chan, need_lock);
00357             return -1;
00358          }
00359       } else
00360          monitor->read_stream = NULL;
00361 
00362       if (stream_action & X_REC_OUT) {
00363          if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00364             ast_filedelete(monitor->write_filename, NULL);
00365          }
00366          if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00367                      monitor->format, NULL,
00368                      O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00369             ast_log(LOG_WARNING, "Could not create file %s\n",
00370                      monitor->write_filename);
00371             ast_closestream(monitor->read_stream);
00372             ast_free(monitor);
00373             UNLOCK_IF_NEEDED(chan, need_lock);
00374             return -1;
00375          }
00376       } else
00377          monitor->write_stream = NULL;
00378 
00379       chan->monitor = monitor;
00380       ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00381       /* so we know this call has been monitored in case we need to bill for it or something */
00382       pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00383 
00384       manager_event(EVENT_FLAG_CALL, "MonitorStart",
00385                          "Channel: %s\r\n"
00386                           "Uniqueid: %s\r\n",                        
00387                            chan->name,
00388                          chan->uniqueid                        
00389                           );
00390    } else {
00391       ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name);
00392       res = -1;
00393    }
00394 
00395    UNLOCK_IF_NEEDED(chan, need_lock);
00396 
00397    return res;
00398 }

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

00427 {
00428    int delfiles = 0;
00429 
00430    LOCK_IF_NEEDED(chan, need_lock);
00431 
00432    if (chan->monitor) {
00433       char filename[ FILENAME_MAX ];
00434 
00435       if (chan->monitor->read_stream) {
00436          ast_closestream(chan->monitor->read_stream);
00437       }
00438       if (chan->monitor->write_stream) {
00439          ast_closestream(chan->monitor->write_stream);
00440       }
00441 
00442       if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00443          if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00444             snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00445             if (ast_fileexists(filename, NULL, NULL) > 0) {
00446                ast_filedelete(filename, NULL);
00447             }
00448             ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00449          } else {
00450             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00451          }
00452 
00453          if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00454             snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00455             if (ast_fileexists(filename, NULL, NULL) > 0) {
00456                ast_filedelete(filename, NULL);
00457             }
00458             ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00459          } else {
00460             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00461          }
00462       }
00463 
00464       if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00465          char tmp[1024];
00466          char tmp2[1024];
00467          const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00468          char *name = chan->monitor->filename_base;
00469          int directory = strchr(name, '/') ? 1 : 0;
00470          const char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
00471          const char *execute, *execute_args;
00472          const char *absolute = *name == '/' ? "" : "/";
00473 
00474          /* Set the execute application */
00475          execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00476          if (ast_strlen_zero(execute)) {
00477 #ifdef HAVE_SOXMIX
00478             execute = "nice -n 19 soxmix";
00479 #else
00480             execute = "nice -n 19 sox -m";
00481 #endif
00482             format = get_soxmix_format(format);
00483             delfiles = 1;
00484          } 
00485          execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00486          if (ast_strlen_zero(execute_args)) {
00487             execute_args = "";
00488          }
00489          
00490          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);
00491          if (delfiles) {
00492             snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name); /* remove legs when done mixing */
00493             ast_copy_string(tmp, tmp2, sizeof(tmp));
00494          }
00495          ast_debug(1,"monitor executing %s\n",tmp);
00496          if (ast_safe_system(tmp) == -1)
00497             ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00498       }
00499       
00500       ast_free(chan->monitor->format);
00501       ast_free(chan->monitor);
00502       chan->monitor = NULL;
00503 
00504       manager_event(EVENT_FLAG_CALL, "MonitorStop",
00505                          "Channel: %s\r\n"
00506                            "Uniqueid: %s\r\n",
00507                            chan->name,
00508                            chan->uniqueid
00509                            );
00510    }
00511 
00512    UNLOCK_IF_NEEDED(chan, need_lock);
00513 
00514    return 0;
00515 }

int AST_OPTIONAL_API_NAME() ast_monitor_unpause ( struct ast_channel chan  ) 

Unpause monitoring of channel.

Definition at line 525 of file res_monitor.c.

References AST_MONITOR_RUNNING, and ast_monitor_set_state().

Referenced by do_pause_or_unpause(), and unpause_monitor_exec().

00526 {
00527    return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00528 }

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

References ast_channel_get_by_name(), ast_channel_unref, ast_monitor_change_fname(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.

Referenced by load_module().

00778 {
00779    struct ast_channel *c = NULL;
00780    const char *name = astman_get_header(m, "Channel");
00781    const char *fname = astman_get_header(m, "File");
00782 
00783    if (ast_strlen_zero(name)) {
00784       astman_send_error(s, m, "No channel specified");
00785       return 0;
00786    }
00787 
00788    if (ast_strlen_zero(fname)) {
00789       astman_send_error(s, m, "No filename specified");
00790       return 0;
00791    }
00792 
00793    if (!(c = ast_channel_get_by_name(name))) {
00794       astman_send_error(s, m, "No such channel");
00795       return 0;
00796    }
00797 
00798    if (ast_monitor_change_fname(c, fname, 1)) {
00799       c = ast_channel_unref(c);
00800       astman_send_error(s, m, "Could not change monitored filename of channel");
00801       return 0;
00802    }
00803 
00804    c = ast_channel_unref(c);
00805 
00806    astman_send_ack(s, m, "Changed monitor filename");
00807 
00808    return 0;
00809 }

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

Wrapper function.

See also:
ast_monitor_change_fname

Definition at line 688 of file res_monitor.c.

References ast_monitor_change_fname().

Referenced by load_module().

00689 {
00690    return ast_monitor_change_fname(chan, data, 1);
00691 }

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

Definition at line 823 of file res_monitor.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_monitor_pause(), ast_monitor_unpause(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), MONITOR_ACTION_PAUSE, and name.

Referenced by pause_monitor_action(), and unpause_monitor_action().

00824 {
00825    struct ast_channel *c = NULL;
00826    const char *name = astman_get_header(m, "Channel");
00827 
00828    if (ast_strlen_zero(name)) {
00829       astman_send_error(s, m, "No channel specified");
00830       return -1;
00831    }
00832 
00833    if (!(c = ast_channel_get_by_name(name))) {
00834       astman_send_error(s, m, "No such channel");
00835       return -1;
00836    }
00837 
00838    if (action == MONITOR_ACTION_PAUSE) {
00839       ast_monitor_pause(c);
00840    } else {
00841       ast_monitor_unpause(c);
00842    }
00843 
00844    c = ast_channel_unref(c);
00845 
00846    astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00847 
00848    return 0;
00849 }

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

Referenced by ast_monitor_stop().

00408 {
00409    const char *res = format;
00410 
00411    if (!strcasecmp(format,"ulaw"))
00412       res = "ul";
00413    if (!strcasecmp(format,"alaw"))
00414       res = "al";
00415    
00416    return res;
00417 }

static int load_module ( void   )  [static]

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

Definition at line 851 of file res_monitor.c.

References do_pause_or_unpause(), and MONITOR_ACTION_PAUSE.

Referenced by load_module().

00852 {
00853    return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00854 }

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

Wrapper for ast_monitor_pause.

Definition at line 531 of file res_monitor.c.

References ast_monitor_pause().

Referenced by load_module().

00532 {
00533    return ast_monitor_pause(chan);
00534 }

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

Start monitoring a channel by manager connection.

Definition at line 694 of file res_monitor.c.

References ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, 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, X_REC_IN, and X_REC_OUT.

Referenced by load_module().

00695 {
00696    struct ast_channel *c = NULL;
00697    const char *name = astman_get_header(m, "Channel");
00698    const char *fname = astman_get_header(m, "File");
00699    const char *format = astman_get_header(m, "Format");
00700    const char *mix = astman_get_header(m, "Mix");
00701    char *d;
00702 
00703    if (ast_strlen_zero(name)) {
00704       astman_send_error(s, m, "No channel specified");
00705       return 0;
00706    }
00707 
00708    if (!(c = ast_channel_get_by_name(name))) {
00709       astman_send_error(s, m, "No such channel");
00710       return 0;
00711    }
00712 
00713    if (ast_strlen_zero(fname)) {
00714       /* No filename base specified, default to channel name as per CLI */
00715       ast_channel_lock(c);
00716       fname = ast_strdupa(c->name);
00717       ast_channel_unlock(c);
00718       /* Channels have the format technology/channel_name - have to replace that /  */
00719       if ((d = strchr(fname, '/'))) {
00720          *d = '-';
00721       }
00722    }
00723 
00724    if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
00725       if (ast_monitor_change_fname(c, fname, 1)) {
00726          astman_send_error(s, m, "Could not start monitoring channel");
00727          c = ast_channel_unref(c);
00728          return 0;
00729       }
00730    }
00731 
00732    if (ast_true(mix)) {
00733       ast_channel_lock(c);
00734       ast_monitor_setjoinfiles(c, 1);
00735       ast_channel_unlock(c);
00736    }
00737 
00738    c = ast_channel_unref(c);
00739 
00740    astman_send_ack(s, m, "Started monitoring channel");
00741 
00742    return 0;
00743 }

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

Start monitor.

Parameters:
chan 
data arguments passed fname|options
Return values:
0 on success.
-1 on failure.

Definition at line 598 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, format, LOG_ERROR, LOG_WARNING, parse(), pbx_builtin_setvar_helper(), urlprefix, X_JOIN, X_REC_IN, and X_REC_OUT.

Referenced by load_module().

00599 {
00600    char *arg = NULL;
00601    char *options = NULL;
00602    char *delay = NULL;
00603    char *urlprefix = NULL;
00604    char tmp[256];
00605    int stream_action = X_REC_IN | X_REC_OUT;
00606    int joinfiles = 0;
00607    int waitforbridge = 0;
00608    int res = 0;
00609    char *parse;
00610    AST_DECLARE_APP_ARGS(args,
00611       AST_APP_ARG(format);
00612       AST_APP_ARG(fname_base);
00613       AST_APP_ARG(options);
00614    );
00615    
00616    /* Parse arguments. */
00617    if (ast_strlen_zero(data)) {
00618       ast_log(LOG_ERROR, "Monitor requires an argument\n");
00619       return 0;
00620    }
00621 
00622    parse = ast_strdupa(data);
00623    AST_STANDARD_APP_ARGS(args, parse);
00624 
00625    if (!ast_strlen_zero(args.options)) {
00626       if (strchr(args.options, 'm'))
00627          stream_action |= X_JOIN;
00628       if (strchr(args.options, 'b'))
00629          waitforbridge = 1;
00630       if (strchr(args.options, 'i'))
00631          stream_action &= ~X_REC_IN;
00632       if (strchr(args.options, 'o'))
00633          stream_action &= ~X_REC_OUT;
00634    }
00635 
00636    arg = strchr(args.format, ':');
00637    if (arg) {
00638       *arg++ = 0;
00639       urlprefix = arg;
00640    }
00641 
00642    if (urlprefix) {
00643       snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base,
00644          ((strcmp(args.format, "gsm")) ? "wav" : "gsm"));
00645       if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00646          return -1;
00647       ast_cdr_setuserfield(chan, tmp);
00648    }
00649    if (waitforbridge) {
00650       /* We must remove the "b" option if listed.  In principle none of
00651          the following could give NULL results, but we check just to
00652          be pedantic. Reconstructing with checks for 'm' option does not
00653          work if we end up adding more options than 'm' in the future. */
00654       delay = ast_strdupa(data);
00655       options = strrchr(delay, ',');
00656       if (options) {
00657          arg = strchr(options, 'b');
00658          if (arg) {
00659             *arg = 'X';
00660             pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);
00661          }
00662       }
00663       return 0;
00664    }
00665 
00666    res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action);
00667    if (res < 0)
00668       res = ast_monitor_change_fname(chan, args.fname_base, 1);
00669 
00670    if (stream_action & X_JOIN) {
00671       if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))
00672          joinfiles = 1;
00673       else
00674          ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");
00675    }
00676    ast_monitor_setjoinfiles(chan, joinfiles);
00677 
00678    return res;
00679 }

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

Stop monitoring a channel by manager connection.

Definition at line 746 of file res_monitor.c.

References ast_channel_get_by_name(), ast_channel_unref, ast_monitor_stop(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), and name.

Referenced by load_module().

00747 {
00748    struct ast_channel *c = NULL;
00749    const char *name = astman_get_header(m, "Channel");
00750    int res;
00751 
00752    if (ast_strlen_zero(name)) {
00753       astman_send_error(s, m, "No channel specified");
00754       return 0;
00755    }
00756 
00757    if (!(c = ast_channel_get_by_name(name))) {
00758       astman_send_error(s, m, "No such channel");
00759       return 0;
00760    }
00761 
00762    res = ast_monitor_stop(c, 1);
00763 
00764    c = ast_channel_unref(c);
00765 
00766    if (res) {
00767       astman_send_error(s, m, "Could not stop monitoring channel");
00768       return 0;
00769    }
00770 
00771    astman_send_ack(s, m, "Stopped monitoring channel");
00772 
00773    return 0;
00774 }

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

Wrapper function.

See also:
ast_monitor_stop

Definition at line 682 of file res_monitor.c.

References ast_monitor_stop().

Referenced by load_module().

00683 {
00684    return ast_monitor_stop(chan, 1);
00685 }

static int unload_module ( void   )  [static]

Definition at line 878 of file res_monitor.c.

References ast_manager_unregister(), and ast_unregister_application().

00879 {
00880    ast_unregister_application("Monitor");
00881    ast_unregister_application("StopMonitor");
00882    ast_unregister_application("ChangeMonitor");
00883    ast_unregister_application("PauseMonitor");
00884    ast_unregister_application("UnpauseMonitor");
00885    ast_manager_unregister("Monitor");
00886    ast_manager_unregister("StopMonitor");
00887    ast_manager_unregister("ChangeMonitor");
00888    ast_manager_unregister("PauseMonitor");
00889    ast_manager_unregister("UnpauseMonitor");
00890 
00891    return 0;
00892 }

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

Definition at line 856 of file res_monitor.c.

References do_pause_or_unpause(), and MONITOR_ACTION_UNPAUSE.

Referenced by load_module().

00857 {
00858    return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00859 }

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

Wrapper for ast_monitor_unpause.

Definition at line 537 of file res_monitor.c.

References ast_monitor_unpause().

Referenced by load_module().

00538 {
00539    return ast_monitor_unpause(chan);
00540 }


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 898 of file res_monitor.c.

Definition at line 898 of file res_monitor.c.

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

Definition at line 242 of file res_monitor.c.

Referenced by ast_monitor_start().

unsigned long seq = 0 [static]

Definition at line 254 of file res_monitor.c.


Generated on Wed Oct 28 13:33:30 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6