Wed Aug 15 01:24:24 2007

Asterisk developer's documentation


res_monitor.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief PBX channel monitoring
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  */
00025  
00026 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 61961 $")
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <errno.h>
00033 #include <string.h>
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <libgen.h>
00037 
00038 #include "asterisk/lock.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/logger.h"
00041 #include "asterisk/file.h"
00042 #include "asterisk/pbx.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/manager.h"
00045 #include "asterisk/cli.h"
00046 #include "asterisk/monitor.h"
00047 #include "asterisk/app.h"
00048 #include "asterisk/utils.h"
00049 #include "asterisk/config.h"
00050 
00051 AST_MUTEX_DEFINE_STATIC(monitorlock);
00052 
00053 #define LOCK_IF_NEEDED(lock, needed) do { \
00054    if (needed) \
00055       ast_channel_lock(lock); \
00056    } while(0)
00057 
00058 #define UNLOCK_IF_NEEDED(lock, needed) do { \
00059    if (needed) \
00060       ast_channel_unlock(lock); \
00061    } while (0)
00062 
00063 static unsigned long seq = 0;
00064 
00065 static char *monitor_synopsis = "Monitor a channel";
00066 
00067 static char *monitor_descrip = "Monitor([file_format[:urlbase]|[fname_base]|[options]]):\n"
00068 "Used to start monitoring a channel. The channel's input and output\n"
00069 "voice packets are logged to files until the channel hangs up or\n"
00070 "monitoring is stopped by the StopMonitor application.\n"
00071 "  file_format    optional, if not set, defaults to \"wav\"\n"
00072 "  fname_base     if set, changes the filename used to the one specified.\n"
00073 "  options:\n"
00074 "    m   - when the recording ends mix the two leg files into one and\n"
00075 "          delete the two leg files.  If the variable MONITOR_EXEC is set, the\n"
00076 "          application referenced in it will be executed instead of\n"
00077 "          soxmix and the raw leg files will NOT be deleted automatically.\n"
00078 "          soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
00079 "          and a target mixed file name which is the same as the leg file names\n"
00080 "          only without the in/out designator.\n"
00081 "          If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
00082 "          additional arguements to MONITOR_EXEC\n"
00083 "          Both MONITOR_EXEC and the Mix flag can be set from the\n"
00084 "          administrator interface\n"
00085 "\n"
00086 "    b   - Don't begin recording unless a call is bridged to another channel\n"
00087 "\nReturns -1 if monitor files can't be opened or if the channel is already\n"
00088 "monitored, otherwise 0.\n"
00089 ;
00090 
00091 static char *stopmonitor_synopsis = "Stop monitoring a channel";
00092 
00093 static char *stopmonitor_descrip = "StopMonitor\n"
00094    "Stops monitoring a channel. Has no effect if the channel is not monitored\n";
00095 
00096 static char *changemonitor_synopsis = "Change monitoring filename of a channel";
00097 
00098 static char *changemonitor_descrip = "ChangeMonitor(filename_base)\n"
00099    "Changes monitoring filename of a channel. Has no effect if the channel is not monitored\n"
00100    "The argument is the new filename base to use for monitoring this channel.\n";
00101 
00102 static char *pausemonitor_synopsis = "Pause monitoring of a channel";
00103 
00104 static char *pausemonitor_descrip = "PauseMonitor\n"
00105    "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n";
00106 
00107 static char *unpausemonitor_synopsis = "Unpause monitoring of a channel";
00108 
00109 static char *unpausemonitor_descrip = "UnpauseMonitor\n"
00110    "Unpauses monitoring of a channel on which monitoring had\n"
00111    "previously been paused with PauseMonitor.\n";
00112 
00113 static int ast_monitor_set_state(struct ast_channel *chan, int state)
00114 {
00115    LOCK_IF_NEEDED(chan, 1);
00116    if (!chan->monitor) {
00117       UNLOCK_IF_NEEDED(chan, 1);
00118       return -1;
00119    }
00120    chan->monitor->state = state;
00121    UNLOCK_IF_NEEDED(chan, 1);
00122    return 0;
00123 }
00124 
00125 /* Start monitoring a channel */
00126 int ast_monitor_start(  struct ast_channel *chan, const char *format_spec,
00127       const char *fname_base, int need_lock)
00128 {
00129    int res = 0;
00130    char tmp[256];
00131 
00132    LOCK_IF_NEEDED(chan, need_lock);
00133 
00134    if (!(chan->monitor)) {
00135       struct ast_channel_monitor *monitor;
00136       char *channel_name, *p;
00137 
00138       /* Create monitoring directory if needed */
00139       if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) {
00140          if (errno != EEXIST) {
00141             ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n",
00142                strerror(errno));
00143          }
00144       }
00145 
00146       if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
00147          UNLOCK_IF_NEEDED(chan, need_lock);
00148          return -1;
00149       }
00150 
00151       /* Determine file names */
00152       if (!ast_strlen_zero(fname_base)) {
00153          int directory = strchr(fname_base, '/') ? 1 : 0;
00154          /* try creating the directory just in case it doesn't exist */
00155          if (directory) {
00156             char *name = strdup(fname_base);
00157             snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name));
00158             free(name);
00159             ast_safe_system(tmp);
00160          }
00161          snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in",
00162                   directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00163          snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out",
00164                   directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00165          ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base));
00166       } else {
00167          ast_mutex_lock(&monitorlock);
00168          snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
00169                   ast_config_AST_MONITOR_DIR, seq);
00170          snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
00171                   ast_config_AST_MONITOR_DIR, seq);
00172          seq++;
00173          ast_mutex_unlock(&monitorlock);
00174 
00175          channel_name = ast_strdupa(chan->name);
00176          while ((p = strchr(channel_name, '/'))) {
00177             *p = '-';
00178          }
00179          snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00180                 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00181          monitor->filename_changed = 1;
00182       }
00183 
00184       monitor->stop = ast_monitor_stop;
00185 
00186       /* Determine file format */
00187       if (!ast_strlen_zero(format_spec)) {
00188          monitor->format = strdup(format_spec);
00189       } else {
00190          monitor->format = strdup("wav");
00191       }
00192       
00193       /* open files */
00194       if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) {
00195          ast_filedelete(monitor->read_filename, NULL);
00196       }
00197       if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00198                   monitor->format, NULL,
00199                   O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
00200          ast_log(LOG_WARNING, "Could not create file %s\n",
00201                   monitor->read_filename);
00202          free(monitor);
00203          UNLOCK_IF_NEEDED(chan, need_lock);
00204          return -1;
00205       }
00206       if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00207          ast_filedelete(monitor->write_filename, NULL);
00208       }
00209       if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00210                   monitor->format, NULL,
00211                   O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
00212          ast_log(LOG_WARNING, "Could not create file %s\n",
00213                   monitor->write_filename);
00214          ast_closestream(monitor->read_stream);
00215          free(monitor);
00216          UNLOCK_IF_NEEDED(chan, need_lock);
00217          return -1;
00218       }
00219       chan->monitor = monitor;
00220       ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00221       /* so we know this call has been monitored in case we need to bill for it or something */
00222       pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00223    } else {
00224       ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n",
00225                chan->name);
00226       res = -1;
00227    }
00228 
00229    UNLOCK_IF_NEEDED(chan, need_lock);
00230 
00231    return res;
00232 }
00233 
00234 /*
00235  * The file format extensions that Asterisk uses are not all the same as that
00236  * which soxmix expects.  This function ensures that the format used as the
00237  * extension on the filename is something soxmix will understand.
00238  */
00239 static const char *get_soxmix_format(const char *format)
00240 {
00241    const char *res = format;
00242 
00243    if (!strcasecmp(format,"ulaw"))
00244       res = "ul";
00245    if (!strcasecmp(format,"alaw"))
00246       res = "al";
00247    
00248    return res;
00249 }
00250 
00251 /* Stop monitoring a channel */
00252 int ast_monitor_stop(struct ast_channel *chan, int need_lock)
00253 {
00254    int delfiles = 0;
00255 
00256    LOCK_IF_NEEDED(chan, need_lock);
00257 
00258    if (chan->monitor) {
00259       char filename[ FILENAME_MAX ];
00260 
00261       if (chan->monitor->read_stream) {
00262          ast_closestream(chan->monitor->read_stream);
00263       }
00264       if (chan->monitor->write_stream) {
00265          ast_closestream(chan->monitor->write_stream);
00266       }
00267 
00268       if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00269          if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00270             snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00271             if (ast_fileexists(filename, NULL, NULL) > 0) {
00272                ast_filedelete(filename, NULL);
00273             }
00274             ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00275          } else {
00276             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00277          }
00278 
00279          if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00280             snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00281             if (ast_fileexists(filename, NULL, NULL) > 0) {
00282                ast_filedelete(filename, NULL);
00283             }
00284             ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00285          } else {
00286             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00287          }
00288       }
00289 
00290       if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00291          char tmp[1024];
00292          char tmp2[1024];
00293          const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00294          char *name = chan->monitor->filename_base;
00295          int directory = strchr(name, '/') ? 1 : 0;
00296          char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
00297          const char *execute, *execute_args;
00298 
00299          /* Set the execute application */
00300          execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00301          if (ast_strlen_zero(execute)) { 
00302             execute = "nice -n 19 soxmix";
00303             format = get_soxmix_format(format);
00304             delfiles = 1;
00305          } 
00306          execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00307          if (ast_strlen_zero(execute_args)) {
00308             execute_args = "";
00309          }
00310          
00311          snprintf(tmp, sizeof(tmp), "%s \"%s/%s-in.%s\" \"%s/%s-out.%s\" \"%s/%s.%s\" %s &", execute, dir, name, format, dir, name, format, dir, name, format,execute_args);
00312          if (delfiles) {
00313             snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
00314             ast_copy_string(tmp, tmp2, sizeof(tmp));
00315          }
00316          ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
00317          if (ast_safe_system(tmp) == -1)
00318             ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00319       }
00320       
00321       free(chan->monitor->format);
00322       free(chan->monitor);
00323       chan->monitor = NULL;
00324    }
00325 
00326    UNLOCK_IF_NEEDED(chan, need_lock);
00327 
00328    return 0;
00329 }
00330 
00331 
00332 /* Pause monitoring of a channel */
00333 int ast_monitor_pause(struct ast_channel *chan)
00334 {
00335    return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00336 }
00337 
00338 /* Unpause monitoring of a channel */
00339 int ast_monitor_unpause(struct ast_channel *chan)
00340 {
00341    return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00342 }
00343 
00344 static int pause_monitor_exec(struct ast_channel *chan, void *data)
00345 {
00346    return ast_monitor_pause(chan);
00347 }
00348 
00349 static int unpause_monitor_exec(struct ast_channel *chan, void *data)
00350 {
00351    return ast_monitor_unpause(chan);
00352 }
00353 
00354 /* Change monitoring filename of a channel */
00355 int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
00356 {
00357    char tmp[256];
00358    if (ast_strlen_zero(fname_base)) {
00359       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00360       return -1;
00361    }
00362 
00363    LOCK_IF_NEEDED(chan, need_lock);
00364 
00365    if (chan->monitor) {
00366       int directory = strchr(fname_base, '/') ? 1 : 0;
00367       /* try creating the directory just in case it doesn't exist */
00368       if (directory) {
00369          char *name = strdup(fname_base);
00370          snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name));
00371          free(name);
00372          ast_safe_system(tmp);
00373       }
00374 
00375       snprintf(chan->monitor->filename_base, FILENAME_MAX, "%s/%s", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00376       chan->monitor->filename_changed = 1;
00377    } else {
00378       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00379    }
00380 
00381    UNLOCK_IF_NEEDED(chan, need_lock);
00382 
00383    return 0;
00384 }
00385 
00386 static int start_monitor_exec(struct ast_channel *chan, void *data)
00387 {
00388    char *arg = NULL;
00389    char *format = NULL;
00390    char *fname_base = NULL;
00391    char *options = NULL;
00392    char *delay = NULL;
00393    char *urlprefix = NULL;
00394    char tmp[256];
00395    int joinfiles = 0;
00396    int waitforbridge = 0;
00397    int res = 0;
00398    
00399    /* Parse arguments. */
00400    if (!ast_strlen_zero((char*)data)) {
00401       arg = ast_strdupa((char*)data);
00402       format = arg;
00403       fname_base = strchr(arg, '|');
00404       if (fname_base) {
00405          *fname_base = 0;
00406          fname_base++;
00407          if ((options = strchr(fname_base, '|'))) {
00408             *options = 0;
00409             options++;
00410             if (strchr(options, 'm'))
00411                joinfiles = 1;
00412             if (strchr(options, 'b'))
00413                waitforbridge = 1;
00414          }
00415       }
00416       arg = strchr(format,':');
00417       if (arg) {
00418          *arg++ = 0;
00419          urlprefix = arg;
00420       }
00421    }
00422    if (urlprefix) {
00423       snprintf(tmp,sizeof(tmp) - 1,"%s/%s.%s",urlprefix,fname_base,
00424          ((strcmp(format,"gsm")) ? "wav" : "gsm"));
00425       if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00426          return -1;
00427       ast_cdr_setuserfield(chan, tmp);
00428    }
00429    if (waitforbridge) {
00430       /* We must remove the "b" option if listed.  In principle none of
00431          the following could give NULL results, but we check just to
00432          be pedantic. Reconstructing with checks for 'm' option does not
00433          work if we end up adding more options than 'm' in the future. */
00434       delay = ast_strdupa(data);
00435       options = strrchr(delay, '|');
00436       if (options) {
00437          arg = strchr(options, 'b');
00438          if (arg) {
00439             *arg = 'X';
00440             pbx_builtin_setvar_helper(chan,"AUTO_MONITOR",delay);
00441          }
00442       }
00443       return 0;
00444    }
00445 
00446    res = ast_monitor_start(chan, format, fname_base, 1);
00447    if (res < 0)
00448       res = ast_monitor_change_fname(chan, fname_base, 1);
00449    ast_monitor_setjoinfiles(chan, joinfiles);
00450 
00451    return res;
00452 }
00453 
00454 static int stop_monitor_exec(struct ast_channel *chan, void *data)
00455 {
00456    return ast_monitor_stop(chan, 1);
00457 }
00458 
00459 static int change_monitor_exec(struct ast_channel *chan, void *data)
00460 {
00461    return ast_monitor_change_fname(chan, (const char*)data, 1);
00462 }
00463 
00464 static char start_monitor_action_help[] =
00465 "Description: The 'Monitor' action may be used to record the audio on a\n"
00466 "  specified channel.  The following parameters may be used to control\n"
00467 "  this:\n"
00468 "  Channel     - Required.  Used to specify the channel to record.\n"
00469 "  File        - Optional.  Is the name of the file created in the\n"
00470 "                monitor spool directory.  Defaults to the same name\n"
00471 "                as the channel (with slashes replaced with dashes).\n"
00472 "  Format      - Optional.  Is the audio recording format.  Defaults\n"
00473 "                to \"wav\".\n"
00474 "  Mix         - Optional.  Boolean parameter as to whether to mix\n"
00475 "                the input and output channels together after the\n"
00476 "                recording is finished.\n";
00477 
00478 static int start_monitor_action(struct mansession *s, const struct message *m)
00479 {
00480    struct ast_channel *c = NULL;
00481    const char *name = astman_get_header(m, "Channel");
00482    const char *fname = astman_get_header(m, "File");
00483    const char *format = astman_get_header(m, "Format");
00484    const char *mix = astman_get_header(m, "Mix");
00485    char *d;
00486    
00487    if (ast_strlen_zero(name)) {
00488       astman_send_error(s, m, "No channel specified");
00489       return 0;
00490    }
00491    c = ast_get_channel_by_name_locked(name);
00492    if (!c) {
00493       astman_send_error(s, m, "No such channel");
00494       return 0;
00495    }
00496 
00497    if (ast_strlen_zero(fname)) {
00498       /* No filename base specified, default to channel name as per CLI */    
00499       if (!(fname = ast_strdup(c->name))) {
00500          astman_send_error(s, m, "Could not start monitoring channel");
00501          ast_channel_unlock(c);
00502          return 0;
00503       }
00504       /* Channels have the format technology/channel_name - have to replace that /  */
00505       if ((d = strchr(fname, '/'))) 
00506          *d = '-';
00507    }
00508    
00509    if (ast_monitor_start(c, format, fname, 1)) {
00510       if (ast_monitor_change_fname(c, fname, 1)) {
00511          astman_send_error(s, m, "Could not start monitoring channel");
00512          ast_channel_unlock(c);
00513          return 0;
00514       }
00515    }
00516 
00517    if (ast_true(mix)) {
00518       ast_monitor_setjoinfiles(c, 1);
00519    }
00520 
00521    ast_channel_unlock(c);
00522    astman_send_ack(s, m, "Started monitoring channel");
00523    return 0;
00524 }
00525 
00526 static char stop_monitor_action_help[] =
00527 "Description: The 'StopMonitor' action may be used to end a previously\n"
00528 "  started 'Monitor' action.  The only parameter is 'Channel', the name\n"
00529 "  of the channel monitored.\n";
00530 
00531 static int stop_monitor_action(struct mansession *s, const struct message *m)
00532 {
00533    struct ast_channel *c = NULL;
00534    const char *name = astman_get_header(m, "Channel");
00535    int res;
00536    if (ast_strlen_zero(name)) {
00537       astman_send_error(s, m, "No channel specified");
00538       return 0;
00539    }
00540    c = ast_get_channel_by_name_locked(name);
00541    if (!c) {
00542       astman_send_error(s, m, "No such channel");
00543       return 0;
00544    }
00545    res = ast_monitor_stop(c, 1);
00546    ast_channel_unlock(c);
00547    if (res) {
00548       astman_send_error(s, m, "Could not stop monitoring channel");
00549       return 0;
00550    }
00551    astman_send_ack(s, m, "Stopped monitoring channel");
00552    return 0;
00553 }
00554 
00555 static char change_monitor_action_help[] =
00556 "Description: The 'ChangeMonitor' action may be used to change the file\n"
00557 "  started by a previous 'Monitor' action.  The following parameters may\n"
00558 "  be used to control this:\n"
00559 "  Channel     - Required.  Used to specify the channel to record.\n"
00560 "  File        - Required.  Is the new name of the file created in the\n"
00561 "                monitor spool directory.\n";
00562 
00563 static int change_monitor_action(struct mansession *s, const struct message *m)
00564 {
00565    struct ast_channel *c = NULL;
00566    const char *name = astman_get_header(m, "Channel");
00567    const char *fname = astman_get_header(m, "File");
00568    if (ast_strlen_zero(name)) {
00569       astman_send_error(s, m, "No channel specified");
00570       return 0;
00571    }
00572    if (ast_strlen_zero(fname)) {
00573       astman_send_error(s, m, "No filename specified");
00574       return 0;
00575    }
00576    c = ast_get_channel_by_name_locked(name);
00577    if (!c) {
00578       astman_send_error(s, m, "No such channel");
00579       return 0;
00580    }
00581    if (ast_monitor_change_fname(c, fname, 1)) {
00582       astman_send_error(s, m, "Could not change monitored filename of channel");
00583       ast_channel_unlock(c);
00584       return 0;
00585    }
00586    ast_channel_unlock(c);
00587    astman_send_ack(s, m, "Changed monitor filename");
00588    return 0;
00589 }
00590 
00591 void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
00592 {
00593    if (chan->monitor)
00594       chan->monitor->joinfiles = turnon;
00595 }
00596 
00597 #define IS_NULL_STRING(string) ((!(string)) || (ast_strlen_zero((string))))
00598 
00599 enum MONITOR_PAUSING_ACTION
00600 {
00601    MONITOR_ACTION_PAUSE,
00602    MONITOR_ACTION_UNPAUSE
00603 };
00604      
00605 static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
00606 {
00607    struct ast_channel *c = NULL;
00608    const char *name = astman_get_header(m, "Channel");
00609    
00610    if (IS_NULL_STRING(name)) {
00611       astman_send_error(s, m, "No channel specified");
00612       return -1;
00613    }
00614    
00615    c = ast_get_channel_by_name_locked(name);
00616    if (!c) {
00617       astman_send_error(s, m, "No such channel");
00618       return -1;
00619    }
00620 
00621    if (action == MONITOR_ACTION_PAUSE)
00622       ast_monitor_pause(c);
00623    else
00624       ast_monitor_unpause(c);
00625    
00626    ast_channel_unlock(c);
00627    astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00628    return 0;   
00629 }
00630 
00631 static char pause_monitor_action_help[] =
00632    "Description: The 'PauseMonitor' action may be used to temporarily stop the\n"
00633    " recording of a channel.  The following parameters may\n"
00634    " be used to control this:\n"
00635    "  Channel     - Required.  Used to specify the channel to record.\n";
00636 
00637 static int pause_monitor_action(struct mansession *s, const struct message *m)
00638 {
00639    return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00640 }
00641 
00642 static char unpause_monitor_action_help[] =
00643    "Description: The 'UnpauseMonitor' action may be used to re-enable recording\n"
00644    "  of a channel after calling PauseMonitor.  The following parameters may\n"
00645    "  be used to control this:\n"
00646    "  Channel     - Required.  Used to specify the channel to record.\n";
00647 
00648 static int unpause_monitor_action(struct mansession *s, const struct message *m)
00649 {
00650    return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00651 }
00652    
00653 
00654 static int load_module(void)
00655 {
00656    ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip);
00657    ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip);
00658    ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip);
00659    ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip);
00660    ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip);
00661    ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help);
00662    ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help);
00663    ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help);
00664    ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help);
00665    ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help);
00666 
00667    return 0;
00668 }
00669 
00670 static int unload_module(void)
00671 {
00672    ast_unregister_application("Monitor");
00673    ast_unregister_application("StopMonitor");
00674    ast_unregister_application("ChangeMonitor");
00675    ast_unregister_application("PauseMonitor");
00676    ast_unregister_application("UnpauseMonitor");
00677    ast_manager_unregister("Monitor");
00678    ast_manager_unregister("StopMonitor");
00679    ast_manager_unregister("ChangeMonitor");
00680    ast_manager_unregister("PauseMonitor");
00681    ast_manager_unregister("UnpauseMonitor");
00682 
00683    return 0;
00684 }
00685 
00686 /* usecount semantics need to be defined */
00687 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Monitoring Resource",
00688       .load = load_module,
00689       .unload = unload_module,
00690       );

Generated on Wed Aug 15 01:24:24 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3