Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:00:54 2007

Asterisk developer's documentation :: Codename Pineapple


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: 49691 $")
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 #include "asterisk/options.h"
00051 
00052 AST_MUTEX_DEFINE_STATIC(monitorlock);
00053 
00054 #define LOCK_IF_NEEDED(lock, needed) do { \
00055    if (needed) \
00056       ast_channel_lock(lock); \
00057    } while(0)
00058 
00059 #define UNLOCK_IF_NEEDED(lock, needed) do { \
00060    if (needed) \
00061       ast_channel_unlock(lock); \
00062    } while (0)
00063 
00064 static unsigned long seq = 0;
00065 
00066 static char *monitor_synopsis = "Monitor a channel";
00067 
00068 static char *monitor_descrip = "Monitor([file_format[:urlbase]|[fname_base]|[options]]):\n"
00069 "Used to start monitoring a channel. The channel's input and output\n"
00070 "voice packets are logged to files until the channel hangs up or\n"
00071 "monitoring is stopped by the StopMonitor application.\n"
00072 "  file_format    optional, if not set, defaults to \"wav\"\n"
00073 "  fname_base     if set, changes the filename used to the one specified.\n"
00074 "  options:\n"
00075 "    m   - when the recording ends mix the two leg files into one and\n"
00076 "          delete the two leg files.  If the variable MONITOR_EXEC is set, the\n"
00077 "          application referenced in it will be executed instead of\n"
00078 "          soxmix and the raw leg files will NOT be deleted automatically.\n"
00079 "          soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
00080 "          and a target mixed file name which is the same as the leg file names\n"
00081 "          only without the in/out designator.\n"
00082 "          If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
00083 "          additional arguements to MONITOR_EXEC\n"
00084 "          Both MONITOR_EXEC and the Mix flag can be set from the\n"
00085 "          administrator interface\n"
00086 "\n"
00087 "    b   - Don't begin recording unless a call is bridged to another channel\n"
00088 "\nReturns -1 if monitor files can't be opened or if the channel is already\n"
00089 "monitored, otherwise 0.\n"
00090 ;
00091 
00092 static char *stopmonitor_synopsis = "Stop monitoring a channel";
00093 
00094 static char *stopmonitor_descrip = "StopMonitor\n"
00095    "Stops monitoring a channel. Has no effect if the channel is not monitored\n";
00096 
00097 static char *changemonitor_synopsis = "Change monitoring filename of a channel";
00098 
00099 static char *changemonitor_descrip = "ChangeMonitor(filename_base)\n"
00100    "Changes monitoring filename of a channel. Has no effect if the channel is not monitored\n"
00101    "The argument is the new filename base to use for monitoring this channel.\n";
00102 
00103 static char *pausemonitor_synopsis = "Pause monitoring of a channel";
00104 
00105 static char *pausemonitor_descrip = "PauseMonitor\n"
00106    "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n";
00107 
00108 static char *unpausemonitor_synopsis = "Unpause monitoring of a channel";
00109 
00110 static char *unpausemonitor_descrip = "UnpauseMonitor\n"
00111    "Unpauses monitoring of a channel on which monitoring had\n"
00112    "previously been paused with PauseMonitor.\n";
00113 
00114 static int ast_monitor_set_state(struct ast_channel *chan, int state)
00115 {
00116    LOCK_IF_NEEDED(chan, 1);
00117    if (!chan->monitor) {
00118       UNLOCK_IF_NEEDED(chan, 1);
00119       return -1;
00120    }
00121    chan->monitor->state = state;
00122    UNLOCK_IF_NEEDED(chan, 1);
00123    return 0;
00124 }
00125 
00126 /* Start monitoring a channel */
00127 int ast_monitor_start(  struct ast_channel *chan, const char *format_spec,
00128       const char *fname_base, int need_lock)
00129 {
00130    int res = 0;
00131    char tmp[256];
00132 
00133    LOCK_IF_NEEDED(chan, need_lock);
00134 
00135    if (!(chan->monitor)) {
00136       struct ast_channel_monitor *monitor;
00137       char *channel_name, *p;
00138 
00139       /* Create monitoring directory if needed */
00140       if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) {
00141          if (errno != EEXIST) {
00142             ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n",
00143                strerror(errno));
00144          }
00145       }
00146 
00147       if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
00148          UNLOCK_IF_NEEDED(chan, need_lock);
00149          return -1;
00150       }
00151 
00152       /* Determine file names */
00153       if (!ast_strlen_zero(fname_base)) {
00154          int directory = strchr(fname_base, '/') ? 1 : 0;
00155          /* try creating the directory just in case it doesn't exist */
00156          if (directory) {
00157             char *name = strdup(fname_base);
00158             snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name));
00159             free(name);
00160             ast_safe_system(tmp);
00161          }
00162          snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in",
00163                   directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00164          snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out",
00165                   directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00166          ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base));
00167       } else {
00168          ast_mutex_lock(&monitorlock);
00169          snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
00170                   ast_config_AST_MONITOR_DIR, seq);
00171          snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
00172                   ast_config_AST_MONITOR_DIR, seq);
00173          seq++;
00174          ast_mutex_unlock(&monitorlock);
00175 
00176          channel_name = ast_strdupa(chan->name);
00177          while ((p = strchr(channel_name, '/'))) {
00178             *p = '-';
00179          }
00180          snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00181                 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00182          monitor->filename_changed = 1;
00183       }
00184 
00185       monitor->stop = ast_monitor_stop;
00186 
00187       /* Determine file format */
00188       if (!ast_strlen_zero(format_spec)) {
00189          monitor->format = strdup(format_spec);
00190       } else {
00191          monitor->format = strdup("wav");
00192       }
00193       
00194       /* open files */
00195       if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) {
00196          ast_filedelete(monitor->read_filename, NULL);
00197       }
00198       if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00199                   monitor->format, NULL,
00200                   O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00201          ast_log(LOG_WARNING, "Could not create file %s\n",
00202                   monitor->read_filename);
00203          free(monitor);
00204          UNLOCK_IF_NEEDED(chan, need_lock);
00205          return -1;
00206       }
00207       if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00208          ast_filedelete(monitor->write_filename, NULL);
00209       }
00210       if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00211                   monitor->format, NULL,
00212                   O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00213          ast_log(LOG_WARNING, "Could not create file %s\n",
00214                   monitor->write_filename);
00215          ast_closestream(monitor->read_stream);
00216          free(monitor);
00217          UNLOCK_IF_NEEDED(chan, need_lock);
00218          return -1;
00219       }
00220       chan->monitor = monitor;
00221       ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00222       /* so we know this call has been monitored in case we need to bill for it or something */
00223       pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00224    } else {
00225       if (option_debug)
00226          ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n",
00227                   chan->name);
00228       res = -1;
00229    }
00230 
00231    UNLOCK_IF_NEEDED(chan, need_lock);
00232 
00233    return res;
00234 }
00235 
00236 /*
00237  * The file format extensions that Asterisk uses are not all the same as that
00238  * which soxmix expects.  This function ensures that the format used as the
00239  * extension on the filename is something soxmix will understand.
00240  */
00241 static const char *get_soxmix_format(const char *format)
00242 {
00243    const char *res = format;
00244 
00245    if (!strcasecmp(format,"ulaw"))
00246       res = "ul";
00247    if (!strcasecmp(format,"alaw"))
00248       res = "al";
00249    
00250    return res;
00251 }
00252 
00253 /* Stop monitoring a channel */
00254 int ast_monitor_stop(struct ast_channel *chan, int need_lock)
00255 {
00256    int delfiles = 0;
00257 
00258    LOCK_IF_NEEDED(chan, need_lock);
00259 
00260    if (chan->monitor) {
00261       char filename[ FILENAME_MAX ];
00262 
00263       if (chan->monitor->read_stream) {
00264          ast_closestream(chan->monitor->read_stream);
00265       }
00266       if (chan->monitor->write_stream) {
00267          ast_closestream(chan->monitor->write_stream);
00268       }
00269 
00270       if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00271          if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00272             snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00273             if (ast_fileexists(filename, NULL, NULL) > 0) {
00274                ast_filedelete(filename, NULL);
00275             }
00276             ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00277          } else {
00278             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00279          }
00280 
00281          if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00282             snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00283             if (ast_fileexists(filename, NULL, NULL) > 0) {
00284                ast_filedelete(filename, NULL);
00285             }
00286             ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00287          } else {
00288             ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00289          }
00290       }
00291 
00292       if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00293          char tmp[1024];
00294          char tmp2[1024];
00295          const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00296          char *name = chan->monitor->filename_base;
00297          int directory = strchr(name, '/') ? 1 : 0;
00298          char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
00299          const char *execute, *execute_args;
00300 
00301          /* Set the execute application */
00302          execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00303          if (ast_strlen_zero(execute)) { 
00304             execute = "nice -n 19 soxmix";
00305             format = get_soxmix_format(format);
00306             delfiles = 1;
00307          } 
00308          execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00309          if (ast_strlen_zero(execute_args)) {
00310             execute_args = "";
00311          }
00312          
00313          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);
00314          if (delfiles) {
00315             snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name); /* remove legs when done mixing */
00316             ast_copy_string(tmp, tmp2, sizeof(tmp));
00317          }
00318          if (option_debug)
00319             ast_log(LOG_DEBUG,"monitor executing %s\n",tmp);
00320          if (ast_safe_system(tmp) == -1)
00321             ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00322       }
00323       
00324       free(chan->monitor->format);
00325       free(chan->monitor);
00326       chan->monitor = NULL;
00327    }
00328 
00329    UNLOCK_IF_NEEDED(chan, need_lock);
00330 
00331    return 0;
00332 }
00333 
00334 
00335 /* Pause monitoring of a channel */
00336 int ast_monitor_pause(struct ast_channel *chan)
00337 {
00338    return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00339 }
00340 
00341 /* Unpause monitoring of a channel */
00342 int ast_monitor_unpause(struct ast_channel *chan)
00343 {
00344    return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00345 }
00346 
00347 static int pause_monitor_exec(struct ast_channel *chan, void *data)
00348 {
00349    return ast_monitor_pause(chan);
00350 }
00351 
00352 static int unpause_monitor_exec(struct ast_channel *chan, void *data)
00353 {
00354    return ast_monitor_unpause(chan);
00355 }
00356 
00357 /* Change monitoring filename of a channel */
00358 int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
00359 {
00360    char tmp[256];
00361    if (ast_strlen_zero(fname_base)) {
00362       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00363       return -1;
00364    }
00365 
00366    LOCK_IF_NEEDED(chan, need_lock);
00367 
00368    if (chan->monitor) {
00369       int directory = strchr(fname_base, '/') ? 1 : 0;
00370       /* try creating the directory just in case it doesn't exist */
00371       if (directory) {
00372          char *name = strdup(fname_base);
00373          snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name));
00374          free(name);
00375          ast_safe_system(tmp);
00376       }
00377 
00378       snprintf(chan->monitor->filename_base, FILENAME_MAX, "%s/%s", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00379    } else {
00380       ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00381    }
00382 
00383    UNLOCK_IF_NEEDED(chan, need_lock);
00384 
00385    return 0;
00386 }
00387 
00388 static int start_monitor_exec(struct ast_channel *chan, void *data)
00389 {
00390    char *arg = NULL;
00391    char *format = NULL;
00392    char *fname_base = NULL;
00393    char *options = NULL;
00394    char *delay = NULL;
00395    char *urlprefix = NULL;
00396    char tmp[256];
00397    int joinfiles = 0;
00398    int waitforbridge = 0;
00399    int res = 0;
00400    
00401    /* Parse arguments. */
00402    if (!ast_strlen_zero((char*)data)) {
00403       arg = ast_strdupa((char*)data);
00404       format = arg;
00405       fname_base = strchr(arg, '|');
00406       if (fname_base) {
00407          *fname_base = 0;
00408          fname_base++;
00409          if ((options = strchr(fname_base, '|'))) {
00410             *options = 0;
00411             options++;
00412             if (strchr(options, 'm'))
00413                joinfiles = 1;
00414             if (strchr(options, 'b'))
00415                waitforbridge = 1;
00416          }
00417       }
00418       arg = strchr(format,':');
00419       if (arg) {
00420          *arg++ = 0;
00421          urlprefix = arg;
00422       }
00423    }
00424    if (urlprefix) {
00425       snprintf(tmp,sizeof(tmp) - 1,"%s/%s.%s",urlprefix,fname_base,
00426          ((strcmp(format,"gsm")) ? "wav" : "gsm"));
00427       if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00428          return -1;
00429       ast_cdr_setuserfield(chan, tmp);
00430    }
00431    if (waitforbridge) {
00432       /* We must remove the "b" option if listed.  In principle none of
00433          the following could give NULL results, but we check just to
00434          be pedantic. Reconstructing with checks for 'm' option does not
00435          work if we end up adding more options than 'm' in the future. */
00436       delay = ast_strdupa(data);
00437       options = strrchr(delay, '|');
00438       if (options) {
00439          arg = strchr(options, 'b');
00440          if (arg) {
00441             *arg = 'X';
00442             pbx_builtin_setvar_helper(chan,"AUTO_MONITOR",delay);
00443          }
00444       }
00445       return 0;
00446    }
00447 
00448    res = ast_monitor_start(chan, format, fname_base, 1);
00449    if (res < 0)
00450       res = ast_monitor_change_fname(chan, fname_base, 1);
00451    ast_monitor_setjoinfiles(chan, joinfiles);
00452 
00453    return res;
00454 }
00455 
00456 static int stop_monitor_exec(struct ast_channel *chan, void *data)
00457 {
00458    return ast_monitor_stop(chan, 1);
00459 }
00460 
00461 static int change_monitor_exec(struct ast_channel *chan, void *data)
00462 {
00463    return ast_monitor_change_fname(chan, (const char*)data, 1);
00464 }
00465 
00466 static char start_monitor_action_help[] =
00467 "Description: The 'Monitor' action may be used to record the audio on a\n"
00468 "  specified channel.  The following parameters may be used to control\n"
00469 "  this:\n"
00470 "  Channel     - Required.  Used to specify the channel to record.\n"
00471 "  File        - Optional.  Is the name of the file created in the\n"
00472 "                monitor spool directory.  Defaults to the same name\n"
00473 "                as the channel (with slashes replaced with dashes).\n"
00474 "  Format      - Optional.  Is the audio recording format.  Defaults\n"
00475 "                to \"wav\".\n"
00476 "  Mix         - Optional.  Boolean parameter as to whether to mix\n"
00477 "                the input and output channels together after the\n"
00478 "                recording is finished.\n";
00479 
00480 static int start_monitor_action(struct mansession *s, const struct message *m)
00481 {
00482    struct ast_channel *c = NULL;
00483    const char *name = astman_get_header(m, "Channel");
00484    const char *fname = astman_get_header(m, "File");
00485    const char *format = astman_get_header(m, "Format");
00486    const char *mix = astman_get_header(m, "Mix");
00487    char *d;
00488    
00489    if (ast_strlen_zero(name)) {
00490       astman_send_error(s, m, "No channel specified");
00491       return 0;
00492    }
00493    c = ast_get_channel_by_name_locked(name);
00494    if (!c) {
00495       astman_send_error(s, m, "No such channel");
00496       return 0;
00497    }
00498 
00499    if (ast_strlen_zero(fname)) {
00500       /* No filename base specified, default to channel name as per CLI */    
00501       if (!(fname = ast_strdup(c->name))) {
00502          astman_send_error(s, m, "Could not start monitoring channel");
00503          ast_channel_unlock(c);
00504          return 0;
00505       }
00506       /* Channels have the format technology/channel_name - have to replace that /  */
00507       if ((d = strchr(fname, '/'))) 
00508          *d = '-';
00509    }
00510    
00511    if (ast_monitor_start(c, format, fname, 1)) {
00512       if (ast_monitor_change_fname(c, fname, 1)) {
00513          astman_send_error(s, m, "Could not start monitoring channel");
00514          ast_channel_unlock(c);
00515          return 0;
00516       }
00517    }
00518 
00519    if (ast_true(mix)) {
00520       ast_monitor_setjoinfiles(c, 1);
00521    }
00522 
00523    ast_channel_unlock(c);
00524    astman_send_ack(s, m, "Started monitoring channel");
00525    return 0;
00526 }
00527 
00528 static char stop_monitor_action_help[] =
00529 "Description: The 'StopMonitor' action may be used to end a previously\n"
00530 "  started 'Monitor' action.  The only parameter is 'Channel', the name\n"
00531 "  of the channel monitored.\n";
00532 
00533 static int stop_monitor_action(struct mansession *s, const struct message *m)
00534 {
00535    struct ast_channel *c = NULL;
00536    const char *name = astman_get_header(m, "Channel");
00537    int res;
00538    if (ast_strlen_zero(name)) {
00539       astman_send_error(s, m, "No channel specified");
00540       return 0;
00541    }
00542    c = ast_get_channel_by_name_locked(name);
00543    if (!c) {
00544       astman_send_error(s, m, "No such channel");
00545       return 0;
00546    }
00547    res = ast_monitor_stop(c, 1);
00548    ast_channel_unlock(c);
00549    if (res) {
00550       astman_send_error(s, m, "Could not stop monitoring channel");
00551       return 0;
00552    }
00553    astman_send_ack(s, m, "Stopped monitoring channel");
00554    return 0;
00555 }
00556 
00557 static char change_monitor_action_help[] =
00558 "Description: The 'ChangeMonitor' action may be used to change the file\n"
00559 "  started by a previous 'Monitor' action.  The following parameters may\n"
00560 "  be used to control this:\n"
00561 "  Channel     - Required.  Used to specify the channel to record.\n"
00562 "  File        - Required.  Is the new name of the file created in the\n"
00563 "                monitor spool directory.\n";
00564 
00565 static int change_monitor_action(struct mansession *s, const struct message *m)
00566 {
00567    struct ast_channel *c = NULL;
00568    const char *name = astman_get_header(m, "Channel");
00569    const char *fname = astman_get_header(m, "File");
00570    if (ast_strlen_zero(name)) {
00571       astman_send_error(s, m, "No channel specified");
00572       return 0;
00573    }
00574    if (ast_strlen_zero(fname)) {
00575       astman_send_error(s, m, "No filename specified");
00576       return 0;
00577    }
00578    c = ast_get_channel_by_name_locked(name);
00579    if (!c) {
00580       astman_send_error(s, m, "No such channel");
00581       return 0;
00582    }
00583    if (ast_monitor_change_fname(c, fname, 1)) {
00584       astman_send_error(s, m, "Could not change monitored filename of channel");
00585       ast_channel_unlock(c);
00586       return 0;
00587    }
00588    ast_channel_unlock(c);
00589    astman_send_ack(s, m, "Changed monitor filename");
00590    return 0;
00591 }
00592 
00593 void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
00594 {
00595    if (chan->monitor)
00596       chan->monitor->joinfiles = turnon;
00597 }
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 (ast_strlen_zero(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, "Paused 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       );

Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen