00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 94122 $")
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 #ifdef HAVE_SOXMIX
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 #else
00081 " sox and the raw leg files will NOT be deleted automatically.\n"
00082 " sox or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
00083 #endif
00084 " and a target mixed file name which is the same as the leg file names\n"
00085 " only without the in/out designator.\n"
00086 " If MONITOR_EXEC_ARGS is set, the contents will be passed on as\n"
00087 " additional arguements to MONITOR_EXEC\n"
00088 " Both MONITOR_EXEC and the Mix flag can be set from the\n"
00089 " administrator interface\n"
00090 "\n"
00091 " b - Don't begin recording unless a call is bridged to another channel\n"
00092 "\nReturns -1 if monitor files can't be opened or if the channel is already\n"
00093 "monitored, otherwise 0.\n"
00094 ;
00095
00096 static char *stopmonitor_synopsis = "Stop monitoring a channel";
00097
00098 static char *stopmonitor_descrip = "StopMonitor\n"
00099 "Stops monitoring a channel. Has no effect if the channel is not monitored\n";
00100
00101 static char *changemonitor_synopsis = "Change monitoring filename of a channel";
00102
00103 static char *changemonitor_descrip = "ChangeMonitor(filename_base)\n"
00104 "Changes monitoring filename of a channel. Has no effect if the channel is not monitored\n"
00105 "The argument is the new filename base to use for monitoring this channel.\n";
00106
00107 static char *pausemonitor_synopsis = "Pause monitoring of a channel";
00108
00109 static char *pausemonitor_descrip = "PauseMonitor\n"
00110 "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n";
00111
00112 static char *unpausemonitor_synopsis = "Unpause monitoring of a channel";
00113
00114 static char *unpausemonitor_descrip = "UnpauseMonitor\n"
00115 "Unpauses monitoring of a channel on which monitoring had\n"
00116 "previously been paused with PauseMonitor.\n";
00117
00118 static int ast_monitor_set_state(struct ast_channel *chan, int state)
00119 {
00120 LOCK_IF_NEEDED(chan, 1);
00121 if (!chan->monitor) {
00122 UNLOCK_IF_NEEDED(chan, 1);
00123 return -1;
00124 }
00125 chan->monitor->state = state;
00126 UNLOCK_IF_NEEDED(chan, 1);
00127 return 0;
00128 }
00129
00130
00131 int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
00132 const char *fname_base, const char *target_url, const char *target_script, int need_lock)
00133 {
00134 int res = 0;
00135 char tmp[256];
00136
00137 LOCK_IF_NEEDED(chan, need_lock);
00138
00139 if (!(chan->monitor)) {
00140 struct ast_channel_monitor *monitor;
00141 char *channel_name, *p;
00142
00143
00144 if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) {
00145 if (errno != EEXIST) {
00146 ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n",
00147 strerror(errno));
00148 }
00149 }
00150
00151 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
00152 UNLOCK_IF_NEEDED(chan, need_lock);
00153 return -1;
00154 }
00155
00156 if (target_url)
00157 ast_copy_string(monitor->target_url, target_url, sizeof(monitor->target_url));
00158 if (target_script)
00159 ast_copy_string(monitor->target_script, target_script, sizeof(monitor->target_script));
00160
00161
00162 if (!ast_strlen_zero(fname_base)) {
00163 int directory = strchr(fname_base, '/') ? 1 : 0;
00164
00165 if (directory) {
00166 char *name = strdup(fname_base);
00167 snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name));
00168 free(name);
00169 ast_safe_system(tmp);
00170 }
00171 snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in",
00172 directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00173 snprintf(monitor->write_filename, FILENAME_MAX, "%s/%s-out",
00174 directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00175 ast_copy_string(monitor->filename_base, fname_base, sizeof(monitor->filename_base));
00176 } else {
00177 ast_mutex_lock(&monitorlock);
00178 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
00179 ast_config_AST_MONITOR_DIR, seq);
00180 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
00181 ast_config_AST_MONITOR_DIR, seq);
00182 seq++;
00183 ast_mutex_unlock(&monitorlock);
00184
00185 channel_name = ast_strdupa(chan->name);
00186 while ((p = strchr(channel_name, '/'))) {
00187 *p = '-';
00188 }
00189 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00190 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00191 monitor->filename_changed = 1;
00192 }
00193
00194 monitor->stop = ast_monitor_stop;
00195
00196
00197 if (!ast_strlen_zero(format_spec)) {
00198 monitor->format = strdup(format_spec);
00199 } else {
00200 monitor->format = strdup("wav");
00201 }
00202
00203
00204 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0) {
00205 ast_filedelete(monitor->read_filename, NULL);
00206 }
00207 if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00208 monitor->format, NULL,
00209 O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
00210 ast_log(LOG_WARNING, "Could not create file %s\n",
00211 monitor->read_filename);
00212 free(monitor);
00213 UNLOCK_IF_NEEDED(chan, need_lock);
00214 return -1;
00215 }
00216 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00217 ast_filedelete(monitor->write_filename, NULL);
00218 }
00219 if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00220 monitor->format, NULL,
00221 O_CREAT|O_TRUNC|O_WRONLY, 0, 0644))) {
00222 ast_log(LOG_WARNING, "Could not create file %s\n",
00223 monitor->write_filename);
00224 ast_closestream(monitor->read_stream);
00225 free(monitor);
00226 UNLOCK_IF_NEEDED(chan, need_lock);
00227 return -1;
00228 }
00229 chan->monitor = monitor;
00230 ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00231
00232 pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00233 } else {
00234 ast_log(LOG_DEBUG,"Cannot start monitoring %s, already monitored\n",
00235 chan->name);
00236 res = -1;
00237 }
00238
00239 UNLOCK_IF_NEEDED(chan, need_lock);
00240
00241 return res;
00242 }
00243
00244
00245
00246
00247
00248
00249 static const char *get_soxmix_format(const char *format)
00250 {
00251 const char *res = format;
00252
00253 if (!strcasecmp(format,"ulaw"))
00254 res = "ul";
00255 if (!strcasecmp(format,"alaw"))
00256 res = "al";
00257
00258 return res;
00259 }
00260
00261
00262 int ast_monitor_stop(struct ast_channel *chan, int need_lock)
00263 {
00264 int delfiles = 0;
00265
00266 LOCK_IF_NEEDED(chan, need_lock);
00267
00268 if (chan->monitor) {
00269 char filename[ FILENAME_MAX ];
00270
00271 if (chan->monitor->read_stream) {
00272 ast_closestream(chan->monitor->read_stream);
00273 }
00274 if (chan->monitor->write_stream) {
00275 ast_closestream(chan->monitor->write_stream);
00276 }
00277
00278 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00279 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00280 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00281 if (ast_fileexists(filename, NULL, NULL) > 0) {
00282 ast_filedelete(filename, NULL);
00283 }
00284 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00285 } else {
00286 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00287 }
00288
00289 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00290 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00291 if (ast_fileexists(filename, NULL, NULL) > 0) {
00292 ast_filedelete(filename, NULL);
00293 }
00294 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00295 } else {
00296 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00297 }
00298 }
00299
00300 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00301 char tmp[1024];
00302 char tmp2[1024];
00303 char tmp3[1024];
00304 int result;
00305 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00306 char *name = chan->monitor->filename_base;
00307 int directory = strchr(name, '/') ? 1 : 0;
00308 char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
00309 const char *execute, *execute_args;
00310
00311
00312 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00313 if (ast_strlen_zero(execute)) {
00314 #ifdef HAVE_SOXMIX
00315 execute = "nice -n 19 soxmix";
00316 #else
00317 execute = "nice -n 19 sox -m";
00318 #endif
00319 format = get_soxmix_format(format);
00320 delfiles = 1;
00321 }
00322 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00323 if (ast_strlen_zero(execute_args)) {
00324 execute_args = "";
00325 }
00326
00327 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);
00328 if (delfiles) {
00329 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s/%s-\"* ) &",tmp, dir ,name);
00330 ast_copy_string(tmp, tmp2, sizeof(tmp));
00331 }
00332 if (!ast_strlen_zero(chan->monitor->target_script) && !ast_strlen_zero(chan->monitor->target_url)) {
00333 snprintf(tmp3,sizeof(tmp3), "( %s& nice -19 %s \"%s/%s.%s\" \"%s\" ) &",tmp, chan->monitor->target_script , dir, name, format, chan->monitor->target_url);
00334 ast_copy_string(tmp, tmp3, sizeof(tmp));
00335 }
00336 ast_log(LOG_NOTICE,"monitor executing %s\n",tmp);
00337 result = ast_safe_system(tmp);
00338 if (result == -1)
00339 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00340 manager_event(EVENT_FLAG_CALL, "MonitorStopped",
00341 "Channel: %s\r\n"
00342 "Uniqueid: %s\r\n"
00343 "Result: %d\r\n"
00344 ,chan->name, chan->uniqueid, result);
00345 }
00346
00347 free(chan->monitor->format);
00348 free(chan->monitor);
00349 chan->monitor = NULL;
00350 }
00351
00352 UNLOCK_IF_NEEDED(chan, need_lock);
00353
00354 return 0;
00355 }
00356
00357
00358
00359 int ast_monitor_pause(struct ast_channel *chan)
00360 {
00361 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00362 }
00363
00364
00365 int ast_monitor_unpause(struct ast_channel *chan)
00366 {
00367 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00368 }
00369
00370 static int pause_monitor_exec(struct ast_channel *chan, void *data)
00371 {
00372 return ast_monitor_pause(chan);
00373 }
00374
00375 static int unpause_monitor_exec(struct ast_channel *chan, void *data)
00376 {
00377 return ast_monitor_unpause(chan);
00378 }
00379
00380
00381 int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
00382 {
00383 char tmp[256];
00384 if (ast_strlen_zero(fname_base)) {
00385 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00386 return -1;
00387 }
00388
00389 LOCK_IF_NEEDED(chan, need_lock);
00390
00391 if (chan->monitor) {
00392 int directory = strchr(fname_base, '/') ? 1 : 0;
00393
00394 if (directory) {
00395 char *name = strdup(fname_base);
00396 snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name));
00397 free(name);
00398 ast_safe_system(tmp);
00399 }
00400
00401 snprintf(chan->monitor->filename_base, FILENAME_MAX, "%s/%s", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);
00402 chan->monitor->filename_changed = 1;
00403 } else {
00404 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00405 }
00406
00407 UNLOCK_IF_NEEDED(chan, need_lock);
00408
00409 return 0;
00410 }
00411
00412 static int start_monitor_exec(struct ast_channel *chan, void *data)
00413 {
00414 char *arg = NULL;
00415 char *format = NULL;
00416 char *fname_base = NULL;
00417 char *options = NULL;
00418 char *delay = NULL;
00419 char *urlprefix = NULL;
00420 char tmp[256];
00421 int joinfiles = 0;
00422 int waitforbridge = 0;
00423 int res = 0;
00424
00425
00426 if (!ast_strlen_zero((char*)data)) {
00427 arg = ast_strdupa((char*)data);
00428 format = arg;
00429 fname_base = strchr(arg, '|');
00430 if (fname_base) {
00431 *fname_base = 0;
00432 fname_base++;
00433 if ((options = strchr(fname_base, '|'))) {
00434 *options = 0;
00435 options++;
00436 if (strchr(options, 'm'))
00437 joinfiles = 1;
00438 if (strchr(options, 'b'))
00439 waitforbridge = 1;
00440 }
00441 }
00442 arg = strchr(format,':');
00443 if (arg) {
00444 *arg++ = 0;
00445 urlprefix = arg;
00446 }
00447 }
00448 if (urlprefix) {
00449 snprintf(tmp,sizeof(tmp) - 1,"%s/%s.%s",urlprefix,fname_base,
00450 ((strcmp(format,"gsm")) ? "wav" : "gsm"));
00451 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00452 return -1;
00453 ast_cdr_setuserfield(chan, tmp);
00454 }
00455 if (waitforbridge) {
00456
00457
00458
00459
00460 delay = ast_strdupa(data);
00461 options = strrchr(delay, '|');
00462 if (options) {
00463 arg = strchr(options, 'b');
00464 if (arg) {
00465 *arg = 'X';
00466 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR",delay);
00467 }
00468 }
00469 return 0;
00470 }
00471
00472 res = ast_monitor_start(chan, format, fname_base, NULL, NULL, 1);
00473 if (res < 0)
00474 res = ast_monitor_change_fname(chan, fname_base, 1);
00475 ast_monitor_setjoinfiles(chan, joinfiles);
00476
00477 return res;
00478 }
00479
00480 static int stop_monitor_exec(struct ast_channel *chan, void *data)
00481 {
00482 return ast_monitor_stop(chan, 1);
00483 }
00484
00485 static int change_monitor_exec(struct ast_channel *chan, void *data)
00486 {
00487 return ast_monitor_change_fname(chan, (const char*)data, 1);
00488 }
00489
00490 static char start_monitor_action_help[] =
00491 "Description: The 'Monitor' action may be used to record the audio on a\n"
00492 " specified channel. The following parameters may be used to control\n"
00493 " this:\n"
00494 " Channel - Required. Used to specify the channel to record.\n"
00495 " File - Optional. Is the name of the file created in the\n"
00496 " monitor spool directory. Defaults to the same name\n"
00497 " as the channel (with slashes replaced with dashes).\n"
00498 " Format - Optional. Is the audio recording format. Defaults\n"
00499 " to \"wav\".\n"
00500 " Mix - Optional. Boolean parameter as to whether to mix\n"
00501 " the input and output channels together after the\n"
00502 " recording is finished.\n";
00503
00504 static int start_monitor_action(struct mansession *s, const struct message *m)
00505 {
00506 struct ast_channel *c = NULL;
00507 const char *name = astman_get_header(m, "Channel");
00508 const char *fname = astman_get_header(m, "File");
00509 const char *format = astman_get_header(m, "Format");
00510 const char *mix = astman_get_header(m, "Mix");
00511 const char *uniqueid = astman_get_header(m, "Uniqueid");
00512 const char *target_url = astman_get_header(m, "TargetURL");
00513 const char *target_script = astman_get_header(m, "TargetScript");
00514 char *d;
00515
00516 if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
00517 astman_send_error(s, m, "No channel/uniqueid specified");
00518 return 0;
00519 }
00520
00521 if (!ast_strlen_zero(uniqueid)) {
00522 c = ast_get_channel_by_uniqueid_locked(uniqueid);
00523 if (!c) {
00524 astman_send_error(s, m, "No such uniqueid");
00525 return 0;
00526 }
00527 } else {
00528 c = ast_get_channel_by_name_locked(name);
00529 if (!c) {
00530 astman_send_error(s, m, "No such channel");
00531 return 0;
00532 }
00533 }
00534
00535 if (ast_strlen_zero(fname)) {
00536
00537 if (!(fname = ast_strdup(c->name))) {
00538 astman_send_error(s, m, "Could not start monitoring channel");
00539 ast_channel_unlock(c);
00540 return 0;
00541 }
00542
00543 if ((d = strchr(fname, '/')))
00544 *d = '-';
00545 }
00546
00547 if (ast_monitor_start(c, format, fname, target_url, target_script, 1)) {
00548 if (ast_monitor_change_fname(c, fname, 1)) {
00549 astman_send_error(s, m, "Could not start monitoring channel");
00550 ast_channel_unlock(c);
00551 return 0;
00552 }
00553 }
00554
00555 if (ast_true(mix)) {
00556 ast_monitor_setjoinfiles(c, 1);
00557 }
00558
00559 ast_channel_unlock(c);
00560 astman_send_ack(s, m, "Started monitoring channel");
00561 return 0;
00562 }
00563
00564 static char stop_monitor_action_help[] =
00565 "Description: The 'StopMonitor' action may be used to end a previously\n"
00566 " started 'Monitor' action. The only parameter is 'Channel', the name\n"
00567 " of the channel monitored.\n";
00568
00569 static int stop_monitor_action(struct mansession *s, const struct message *m)
00570 {
00571 struct ast_channel *c = NULL;
00572 const char *name = astman_get_header(m, "Channel");
00573 const char *uniqueid = astman_get_header(m, "Uniqueid");
00574 int res;
00575 if (ast_strlen_zero(name)) {
00576 astman_send_error(s, m, "No channel specified");
00577 return 0;
00578 }
00579 if (ast_strlen_zero(name) && ast_strlen_zero(uniqueid)) {
00580 astman_send_error(s, m, "No channel/uniqueid specified");
00581 return 0;
00582 }
00583 if (!ast_strlen_zero(uniqueid)) {
00584 c = ast_get_channel_by_uniqueid_locked(uniqueid);
00585 if (!c) {
00586 astman_send_error(s, m, "No such uniqueid");
00587 return 0;
00588 }
00589 } else {
00590 c = ast_get_channel_by_name_locked(name);
00591 if (!c) {
00592 astman_send_error(s, m, "No such channel");
00593 return 0;
00594 }
00595 }
00596
00597 res = ast_monitor_stop(c, 1);
00598 ast_channel_unlock(c);
00599 if (res) {
00600 astman_send_error(s, m, "Could not stop monitoring channel");
00601 return 0;
00602 }
00603 astman_send_ack(s, m, "Stopped monitoring channel");
00604 return 0;
00605 }
00606
00607 static char change_monitor_action_help[] =
00608 "Description: The 'ChangeMonitor' action may be used to change the file\n"
00609 " started by a previous 'Monitor' action. The following parameters may\n"
00610 " be used to control this:\n"
00611 " Channel - Required. Used to specify the channel to record.\n"
00612 " File - Required. Is the new name of the file created in the\n"
00613 " monitor spool directory.\n";
00614
00615 static int change_monitor_action(struct mansession *s, const struct message *m)
00616 {
00617 struct ast_channel *c = NULL;
00618 const char *name = astman_get_header(m, "Channel");
00619 const char *fname = astman_get_header(m, "File");
00620 if (ast_strlen_zero(name)) {
00621 astman_send_error(s, m, "No channel specified");
00622 return 0;
00623 }
00624 if (ast_strlen_zero(fname)) {
00625 astman_send_error(s, m, "No filename specified");
00626 return 0;
00627 }
00628 c = ast_get_channel_by_name_locked(name);
00629 if (!c) {
00630 astman_send_error(s, m, "No such channel");
00631 return 0;
00632 }
00633 if (ast_monitor_change_fname(c, fname, 1)) {
00634 astman_send_error(s, m, "Could not change monitored filename of channel");
00635 ast_channel_unlock(c);
00636 return 0;
00637 }
00638 ast_channel_unlock(c);
00639 astman_send_ack(s, m, "Changed monitor filename");
00640 return 0;
00641 }
00642
00643 void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
00644 {
00645 if (chan->monitor)
00646 chan->monitor->joinfiles = turnon;
00647 }
00648
00649 #define IS_NULL_STRING(string) ((!(string)) || (ast_strlen_zero((string))))
00650
00651 enum MONITOR_PAUSING_ACTION
00652 {
00653 MONITOR_ACTION_PAUSE,
00654 MONITOR_ACTION_UNPAUSE
00655 };
00656
00657 static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
00658 {
00659 struct ast_channel *c = NULL;
00660 const char *name = astman_get_header(m, "Channel");
00661
00662 if (IS_NULL_STRING(name)) {
00663 astman_send_error(s, m, "No channel specified");
00664 return -1;
00665 }
00666
00667 c = ast_get_channel_by_name_locked(name);
00668 if (!c) {
00669 astman_send_error(s, m, "No such channel");
00670 return -1;
00671 }
00672
00673 if (action == MONITOR_ACTION_PAUSE)
00674 ast_monitor_pause(c);
00675 else
00676 ast_monitor_unpause(c);
00677
00678 ast_channel_unlock(c);
00679 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00680 return 0;
00681 }
00682
00683 static char pause_monitor_action_help[] =
00684 "Description: The 'PauseMonitor' action may be used to temporarily stop the\n"
00685 " recording of a channel. The following parameters may\n"
00686 " be used to control this:\n"
00687 " Channel - Required. Used to specify the channel to record.\n";
00688
00689 static int pause_monitor_action(struct mansession *s, const struct message *m)
00690 {
00691 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00692 }
00693
00694 static char unpause_monitor_action_help[] =
00695 "Description: The 'UnpauseMonitor' action may be used to re-enable recording\n"
00696 " of a channel after calling PauseMonitor. The following parameters may\n"
00697 " be used to control this:\n"
00698 " Channel - Required. Used to specify the channel to record.\n";
00699
00700 static int unpause_monitor_action(struct mansession *s, const struct message *m)
00701 {
00702 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00703 }
00704
00705
00706 static int load_module(void)
00707 {
00708 ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip);
00709 ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip);
00710 ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip);
00711 ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip);
00712 ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip);
00713 ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help);
00714 ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help);
00715 ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help);
00716 ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help);
00717 ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help);
00718
00719 return 0;
00720 }
00721
00722 static int unload_module(void)
00723 {
00724 ast_unregister_application("Monitor");
00725 ast_unregister_application("StopMonitor");
00726 ast_unregister_application("ChangeMonitor");
00727 ast_unregister_application("PauseMonitor");
00728 ast_unregister_application("UnpauseMonitor");
00729 ast_manager_unregister("Monitor");
00730 ast_manager_unregister("StopMonitor");
00731 ast_manager_unregister("ChangeMonitor");
00732 ast_manager_unregister("PauseMonitor");
00733 ast_manager_unregister("UnpauseMonitor");
00734
00735 return 0;
00736 }
00737
00738
00739 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Monitoring Resource",
00740 .load = load_module,
00741 .unload = unload_module,
00742 );