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: 235943 $")
00029
00030 #include <sys/stat.h>
00031 #include <libgen.h>
00032
00033 #include "asterisk/paths.h"
00034 #include "asterisk/lock.h"
00035 #include "asterisk/channel.h"
00036 #include "asterisk/file.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/module.h"
00039 #include "asterisk/manager.h"
00040 #include "asterisk/cli.h"
00041 #include "asterisk/monitor.h"
00042 #include "asterisk/app.h"
00043 #include "asterisk/utils.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/options.h"
00046
00047 AST_MUTEX_DEFINE_STATIC(monitorlock);
00048
00049 #define LOCK_IF_NEEDED(lock, needed) do { \
00050 if (needed) \
00051 ast_channel_lock(lock); \
00052 } while(0)
00053
00054 #define UNLOCK_IF_NEEDED(lock, needed) do { \
00055 if (needed) \
00056 ast_channel_unlock(lock); \
00057 } while (0)
00058
00059 static unsigned long seq = 0;
00060
00061 static char *monitor_synopsis = "Monitor a channel";
00062
00063 static char *monitor_descrip = " Monitor([file_format[:urlbase],[fname_base],[options]]):\n"
00064 "Used to start monitoring a channel. The channel's input and output\n"
00065 "voice packets are logged to files until the channel hangs up or\n"
00066 "monitoring is stopped by the StopMonitor application.\n"
00067 " file_format optional, if not set, defaults to \"wav\"\n"
00068 " fname_base if set, changes the filename used to the one specified.\n"
00069 " options:\n"
00070 " m - when the recording ends mix the two leg files into one and\n"
00071 " delete the two leg files. If the variable MONITOR_EXEC is set, the\n"
00072 " application referenced in it will be executed instead of\n"
00073 #ifdef HAVE_SOXMIX
00074 " soxmix and the raw leg files will NOT be deleted automatically.\n"
00075 " soxmix or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
00076 #else
00077 " sox and the raw leg files will NOT be deleted automatically.\n"
00078 " sox or MONITOR_EXEC is handed 3 arguments, the two leg files\n"
00079 #endif
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 arguments 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 " i - Skip recording of input stream (disables m option)\n"
00089 " o - Skip recording of output stream (disables m option)\n"
00090 "\nBy default, files are stored to /var/spool/asterisk/monitor/.\n"
00091 "\nReturns -1 if monitor files can't be opened or if the channel is already\n"
00092 "monitored, otherwise 0.\n"
00093 ;
00094
00095 static char *stopmonitor_synopsis = "Stop monitoring a channel";
00096
00097 static char *stopmonitor_descrip = " StopMonitor():\n"
00098 "Stops monitoring a channel. Has no effect if the channel is not monitored\n";
00099
00100 static char *changemonitor_synopsis = "Change monitoring filename of a channel";
00101
00102 static char *changemonitor_descrip = " ChangeMonitor(filename_base):\n"
00103 "Changes monitoring filename of a channel. Has no effect if the channel is not monitored.\n"
00104 "The argument is the new filename base to use for monitoring this channel.\n";
00105
00106 static char *pausemonitor_synopsis = "Pause monitoring of a channel";
00107
00108 static char *pausemonitor_descrip = " PauseMonitor():\n"
00109 "Pauses monitoring of a channel until it is re-enabled by a call to UnpauseMonitor.\n";
00110
00111 static char *unpausemonitor_synopsis = "Unpause monitoring of a channel";
00112
00113 static char *unpausemonitor_descrip = " UnpauseMonitor():\n"
00114 "Unpauses monitoring of a channel on which monitoring had\n"
00115 "previously been paused with PauseMonitor.\n";
00116
00117
00118
00119
00120
00121
00122
00123
00124 static int ast_monitor_set_state(struct ast_channel *chan, int state)
00125 {
00126 LOCK_IF_NEEDED(chan, 1);
00127 if (!chan->monitor) {
00128 UNLOCK_IF_NEEDED(chan, 1);
00129 return -1;
00130 }
00131 chan->monitor->state = state;
00132 UNLOCK_IF_NEEDED(chan, 1);
00133 return 0;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 int ast_monitor_start( struct ast_channel *chan, const char *format_spec,
00148 const char *fname_base, int need_lock, int stream_action)
00149 {
00150 int res = 0;
00151
00152 LOCK_IF_NEEDED(chan, need_lock);
00153
00154 if (!(chan->monitor)) {
00155 struct ast_channel_monitor *monitor;
00156 char *channel_name, *p;
00157
00158
00159 ast_mkdir(ast_config_AST_MONITOR_DIR, 0777);
00160
00161 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
00162 UNLOCK_IF_NEEDED(chan, need_lock);
00163 return -1;
00164 }
00165
00166
00167 if (!ast_strlen_zero(fname_base)) {
00168 int directory = strchr(fname_base, '/') ? 1 : 0;
00169 const char *absolute = *fname_base == '/' ? "" : "/";
00170
00171 if (directory) {
00172 char *name = ast_strdupa(fname_base);
00173 ast_mkdir(dirname(name), 0777);
00174 }
00175 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in",
00176 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00177 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",
00178 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00179 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s",
00180 directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00181 } else {
00182 ast_mutex_lock(&monitorlock);
00183 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%ld",
00184 ast_config_AST_MONITOR_DIR, seq);
00185 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
00186 ast_config_AST_MONITOR_DIR, seq);
00187 seq++;
00188 ast_mutex_unlock(&monitorlock);
00189
00190 channel_name = ast_strdupa(chan->name);
00191 while ((p = strchr(channel_name, '/'))) {
00192 *p = '-';
00193 }
00194 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00195 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00196 monitor->filename_changed = 1;
00197 }
00198
00199 monitor->stop = ast_monitor_stop;
00200
00201
00202 if (!ast_strlen_zero(format_spec)) {
00203 monitor->format = ast_strdup(format_spec);
00204 } else {
00205 monitor->format = ast_strdup("wav");
00206 }
00207
00208
00209 if (stream_action & X_REC_IN) {
00210 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0)
00211 ast_filedelete(monitor->read_filename, NULL);
00212 if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00213 monitor->format, NULL,
00214 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00215 ast_log(LOG_WARNING, "Could not create file %s\n",
00216 monitor->read_filename);
00217 ast_free(monitor);
00218 UNLOCK_IF_NEEDED(chan, need_lock);
00219 return -1;
00220 }
00221 } else
00222 monitor->read_stream = NULL;
00223
00224 if (stream_action & X_REC_OUT) {
00225 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00226 ast_filedelete(monitor->write_filename, NULL);
00227 }
00228 if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00229 monitor->format, NULL,
00230 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00231 ast_log(LOG_WARNING, "Could not create file %s\n",
00232 monitor->write_filename);
00233 ast_closestream(monitor->read_stream);
00234 ast_free(monitor);
00235 UNLOCK_IF_NEEDED(chan, need_lock);
00236 return -1;
00237 }
00238 } else
00239 monitor->write_stream = NULL;
00240
00241 chan->monitor = monitor;
00242 ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00243
00244 pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00245
00246 manager_event(EVENT_FLAG_CALL, "MonitorStart",
00247 "Channel: %s\r\n"
00248 "Uniqueid: %s\r\n",
00249 chan->name,
00250 chan->uniqueid
00251 );
00252 } else {
00253 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name);
00254 res = -1;
00255 }
00256
00257 UNLOCK_IF_NEEDED(chan, need_lock);
00258
00259 return res;
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269 static const char *get_soxmix_format(const char *format)
00270 {
00271 const char *res = format;
00272
00273 if (!strcasecmp(format,"ulaw"))
00274 res = "ul";
00275 if (!strcasecmp(format,"alaw"))
00276 res = "al";
00277
00278 return res;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287
00288 int ast_monitor_stop(struct ast_channel *chan, int need_lock)
00289 {
00290 int delfiles = 0;
00291
00292 LOCK_IF_NEEDED(chan, need_lock);
00293
00294 if (chan->monitor) {
00295 char filename[ FILENAME_MAX ];
00296
00297 if (chan->monitor->read_stream) {
00298 ast_closestream(chan->monitor->read_stream);
00299 }
00300 if (chan->monitor->write_stream) {
00301 ast_closestream(chan->monitor->write_stream);
00302 }
00303
00304 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00305 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00306 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00307 if (ast_fileexists(filename, NULL, NULL) > 0) {
00308 ast_filedelete(filename, NULL);
00309 }
00310 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00311 } else {
00312 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00313 }
00314
00315 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00316 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00317 if (ast_fileexists(filename, NULL, NULL) > 0) {
00318 ast_filedelete(filename, NULL);
00319 }
00320 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00321 } else {
00322 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00323 }
00324 }
00325
00326 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00327 char tmp[1024];
00328 char tmp2[1024];
00329 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00330 char *name = chan->monitor->filename_base;
00331 int directory = strchr(name, '/') ? 1 : 0;
00332 const char *dir = directory ? "" : ast_config_AST_MONITOR_DIR;
00333 const char *execute, *execute_args;
00334 const char *absolute = *name == '/' ? "" : "/";
00335
00336
00337 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00338 if (ast_strlen_zero(execute)) {
00339 #ifdef HAVE_SOXMIX
00340 execute = "nice -n 19 soxmix";
00341 #else
00342 execute = "nice -n 19 sox -m";
00343 #endif
00344 format = get_soxmix_format(format);
00345 delfiles = 1;
00346 }
00347 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00348 if (ast_strlen_zero(execute_args)) {
00349 execute_args = "";
00350 }
00351
00352 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);
00353 if (delfiles) {
00354 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s%s%s-\"* ) &",tmp, dir, absolute, name);
00355 ast_copy_string(tmp, tmp2, sizeof(tmp));
00356 }
00357 ast_debug(1,"monitor executing %s\n",tmp);
00358 if (ast_safe_system(tmp) == -1)
00359 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00360 }
00361
00362 ast_free(chan->monitor->format);
00363 ast_free(chan->monitor);
00364 chan->monitor = NULL;
00365
00366 manager_event(EVENT_FLAG_CALL, "MonitorStop",
00367 "Channel: %s\r\n"
00368 "Uniqueid: %s\r\n",
00369 chan->name,
00370 chan->uniqueid
00371 );
00372 }
00373
00374 UNLOCK_IF_NEEDED(chan, need_lock);
00375
00376 return 0;
00377 }
00378
00379
00380
00381 int ast_monitor_pause(struct ast_channel *chan)
00382 {
00383 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00384 }
00385
00386
00387 int ast_monitor_unpause(struct ast_channel *chan)
00388 {
00389 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00390 }
00391
00392
00393 static int pause_monitor_exec(struct ast_channel *chan, void *data)
00394 {
00395 return ast_monitor_pause(chan);
00396 }
00397
00398
00399 static int unpause_monitor_exec(struct ast_channel *chan, void *data)
00400 {
00401 return ast_monitor_unpause(chan);
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412 int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock)
00413 {
00414 if (ast_strlen_zero(fname_base)) {
00415 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00416 return -1;
00417 }
00418
00419 LOCK_IF_NEEDED(chan, need_lock);
00420
00421 if (chan->monitor) {
00422 int directory = strchr(fname_base, '/') ? 1 : 0;
00423 const char *absolute = *fname_base == '/' ? "" : "/";
00424 char tmpstring[sizeof(chan->monitor->filename_base)] = "";
00425 int i, fd[2] = { -1, -1 }, doexit = 0;
00426
00427
00428 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", directory ? "" : ast_config_AST_MONITOR_DIR, absolute, fname_base);
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base);
00442
00443 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
00444 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
00445 if (fd[0] < 0) {
00446 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));
00447 } else {
00448 ast_debug(2, "No need to rename monitor filename to itself\n");
00449 }
00450 doexit = 1;
00451 }
00452
00453
00454 for (i = 0; i < 2; i++) {
00455 if (fd[i] >= 0) {
00456 while (close(fd[i]) < 0 && errno == EINTR);
00457 }
00458 }
00459 unlink(tmpstring);
00460 unlink(chan->monitor->filename_base);
00461
00462 if (doexit) {
00463 UNLOCK_IF_NEEDED(chan, need_lock);
00464 return 0;
00465 }
00466
00467
00468 if (directory) {
00469 char *name = ast_strdupa(fname_base);
00470 ast_mkdir(dirname(name), 0777);
00471 }
00472
00473 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base));
00474 chan->monitor->filename_changed = 1;
00475 } else {
00476 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00477 }
00478
00479 UNLOCK_IF_NEEDED(chan, need_lock);
00480
00481 return 0;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492 static int start_monitor_exec(struct ast_channel *chan, void *data)
00493 {
00494 char *arg = NULL;
00495 char *options = NULL;
00496 char *delay = NULL;
00497 char *urlprefix = NULL;
00498 char tmp[256];
00499 int stream_action = X_REC_IN | X_REC_OUT;
00500 int joinfiles = 0;
00501 int waitforbridge = 0;
00502 int res = 0;
00503 char *parse;
00504 AST_DECLARE_APP_ARGS(args,
00505 AST_APP_ARG(format);
00506 AST_APP_ARG(fname_base);
00507 AST_APP_ARG(options);
00508 );
00509
00510
00511 if (ast_strlen_zero((char*)data)) {
00512 ast_log(LOG_ERROR, "Monitor requires an argument\n");
00513 return 0;
00514 }
00515
00516 parse = ast_strdupa((char*)data);
00517 AST_STANDARD_APP_ARGS(args, parse);
00518
00519 if (!ast_strlen_zero(args.options)) {
00520 if (strchr(args.options, 'm'))
00521 stream_action |= X_JOIN;
00522 if (strchr(args.options, 'b'))
00523 waitforbridge = 1;
00524 if (strchr(args.options, 'i'))
00525 stream_action &= ~X_REC_IN;
00526 if (strchr(args.options, 'o'))
00527 stream_action &= ~X_REC_OUT;
00528 }
00529
00530 arg = strchr(args.format, ':');
00531 if (arg) {
00532 *arg++ = 0;
00533 urlprefix = arg;
00534 }
00535
00536 if (urlprefix) {
00537 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base,
00538 ((strcmp(args.format, "gsm")) ? "wav" : "gsm"));
00539 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00540 return -1;
00541 ast_cdr_setuserfield(chan, tmp);
00542 }
00543 if (waitforbridge) {
00544
00545
00546
00547
00548 delay = ast_strdupa(data);
00549 options = strrchr(delay, ',');
00550 if (options) {
00551 arg = strchr(options, 'b');
00552 if (arg) {
00553 *arg = 'X';
00554 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);
00555 }
00556 }
00557 return 0;
00558 }
00559
00560 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action);
00561 if (res < 0)
00562 res = ast_monitor_change_fname(chan, args.fname_base, 1);
00563
00564 if (stream_action & X_JOIN) {
00565 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))
00566 joinfiles = 1;
00567 else
00568 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");
00569 }
00570 ast_monitor_setjoinfiles(chan, joinfiles);
00571
00572 return res;
00573 }
00574
00575
00576 static int stop_monitor_exec(struct ast_channel *chan, void *data)
00577 {
00578 return ast_monitor_stop(chan, 1);
00579 }
00580
00581
00582 static int change_monitor_exec(struct ast_channel *chan, void *data)
00583 {
00584 return ast_monitor_change_fname(chan, (const char*)data, 1);
00585 }
00586
00587 static char start_monitor_action_help[] =
00588 "Description: The 'Monitor' action may be used to record the audio on a\n"
00589 " specified channel. The following parameters may be used to control\n"
00590 " this:\n"
00591 " Channel - Required. Used to specify the channel to record.\n"
00592 " File - Optional. Is the name of the file created in the\n"
00593 " monitor spool directory. Defaults to the same name\n"
00594 " as the channel (with slashes replaced with dashes).\n"
00595 " Format - Optional. Is the audio recording format. Defaults\n"
00596 " to \"wav\".\n"
00597 " Mix - Optional. Boolean parameter as to whether to mix\n"
00598 " the input and output channels together after the\n"
00599 " recording is finished.\n";
00600
00601
00602 static int start_monitor_action(struct mansession *s, const struct message *m)
00603 {
00604 struct ast_channel *c = NULL;
00605 const char *name = astman_get_header(m, "Channel");
00606 const char *fname = astman_get_header(m, "File");
00607 const char *format = astman_get_header(m, "Format");
00608 const char *mix = astman_get_header(m, "Mix");
00609 char *d;
00610
00611 if (ast_strlen_zero(name)) {
00612 astman_send_error(s, m, "No channel specified");
00613 return 0;
00614 }
00615 c = ast_get_channel_by_name_locked(name);
00616 if (!c) {
00617 astman_send_error(s, m, "No such channel");
00618 return 0;
00619 }
00620
00621 if (ast_strlen_zero(fname)) {
00622
00623 fname = ast_strdupa(c->name);
00624
00625 if ((d = strchr(fname, '/')))
00626 *d = '-';
00627 }
00628
00629 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
00630 if (ast_monitor_change_fname(c, fname, 1)) {
00631 astman_send_error(s, m, "Could not start monitoring channel");
00632 ast_channel_unlock(c);
00633 return 0;
00634 }
00635 }
00636
00637 if (ast_true(mix)) {
00638 ast_monitor_setjoinfiles(c, 1);
00639 }
00640
00641 ast_channel_unlock(c);
00642 astman_send_ack(s, m, "Started monitoring channel");
00643 return 0;
00644 }
00645
00646 static char stop_monitor_action_help[] =
00647 "Description: The 'StopMonitor' action may be used to end a previously\n"
00648 " started 'Monitor' action. The only parameter is 'Channel', the name\n"
00649 " of the channel monitored.\n";
00650
00651
00652 static int stop_monitor_action(struct mansession *s, const struct message *m)
00653 {
00654 struct ast_channel *c = NULL;
00655 const char *name = astman_get_header(m, "Channel");
00656 int res;
00657 if (ast_strlen_zero(name)) {
00658 astman_send_error(s, m, "No channel specified");
00659 return 0;
00660 }
00661 c = ast_get_channel_by_name_locked(name);
00662 if (!c) {
00663 astman_send_error(s, m, "No such channel");
00664 return 0;
00665 }
00666 res = ast_monitor_stop(c, 1);
00667 ast_channel_unlock(c);
00668 if (res) {
00669 astman_send_error(s, m, "Could not stop monitoring channel");
00670 return 0;
00671 }
00672 astman_send_ack(s, m, "Stopped monitoring channel");
00673 return 0;
00674 }
00675
00676 static char change_monitor_action_help[] =
00677 "Description: The 'ChangeMonitor' action may be used to change the file\n"
00678 " started by a previous 'Monitor' action. The following parameters may\n"
00679 " be used to control this:\n"
00680 " Channel - Required. Used to specify the channel to record.\n"
00681 " File - Required. Is the new name of the file created in the\n"
00682 " monitor spool directory.\n";
00683
00684
00685 static int change_monitor_action(struct mansession *s, const struct message *m)
00686 {
00687 struct ast_channel *c = NULL;
00688 const char *name = astman_get_header(m, "Channel");
00689 const char *fname = astman_get_header(m, "File");
00690 if (ast_strlen_zero(name)) {
00691 astman_send_error(s, m, "No channel specified");
00692 return 0;
00693 }
00694 if (ast_strlen_zero(fname)) {
00695 astman_send_error(s, m, "No filename specified");
00696 return 0;
00697 }
00698 c = ast_get_channel_by_name_locked(name);
00699 if (!c) {
00700 astman_send_error(s, m, "No such channel");
00701 return 0;
00702 }
00703 if (ast_monitor_change_fname(c, fname, 1)) {
00704 astman_send_error(s, m, "Could not change monitored filename of channel");
00705 ast_channel_unlock(c);
00706 return 0;
00707 }
00708 ast_channel_unlock(c);
00709 astman_send_ack(s, m, "Changed monitor filename");
00710 return 0;
00711 }
00712
00713 void ast_monitor_setjoinfiles(struct ast_channel *chan, int turnon)
00714 {
00715 if (chan->monitor)
00716 chan->monitor->joinfiles = turnon;
00717 }
00718
00719 enum MONITOR_PAUSING_ACTION
00720 {
00721 MONITOR_ACTION_PAUSE,
00722 MONITOR_ACTION_UNPAUSE
00723 };
00724
00725 static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
00726 {
00727 struct ast_channel *c = NULL;
00728 const char *name = astman_get_header(m, "Channel");
00729
00730 if (ast_strlen_zero(name)) {
00731 astman_send_error(s, m, "No channel specified");
00732 return -1;
00733 }
00734
00735 c = ast_get_channel_by_name_locked(name);
00736 if (!c) {
00737 astman_send_error(s, m, "No such channel");
00738 return -1;
00739 }
00740
00741 if (action == MONITOR_ACTION_PAUSE)
00742 ast_monitor_pause(c);
00743 else
00744 ast_monitor_unpause(c);
00745
00746 ast_channel_unlock(c);
00747 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00748 return 0;
00749 }
00750
00751 static char pause_monitor_action_help[] =
00752 "Description: The 'PauseMonitor' action may be used to temporarily stop the\n"
00753 " recording of a channel. The following parameters may\n"
00754 " be used to control this:\n"
00755 " Channel - Required. Used to specify the channel to record.\n";
00756
00757 static int pause_monitor_action(struct mansession *s, const struct message *m)
00758 {
00759 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00760 }
00761
00762 static char unpause_monitor_action_help[] =
00763 "Description: The 'UnpauseMonitor' action may be used to re-enable recording\n"
00764 " of a channel after calling PauseMonitor. The following parameters may\n"
00765 " be used to control this:\n"
00766 " Channel - Required. Used to specify the channel to record.\n";
00767
00768 static int unpause_monitor_action(struct mansession *s, const struct message *m)
00769 {
00770 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00771 }
00772
00773
00774 static int load_module(void)
00775 {
00776 ast_register_application("Monitor", start_monitor_exec, monitor_synopsis, monitor_descrip);
00777 ast_register_application("StopMonitor", stop_monitor_exec, stopmonitor_synopsis, stopmonitor_descrip);
00778 ast_register_application("ChangeMonitor", change_monitor_exec, changemonitor_synopsis, changemonitor_descrip);
00779 ast_register_application("PauseMonitor", pause_monitor_exec, pausemonitor_synopsis, pausemonitor_descrip);
00780 ast_register_application("UnpauseMonitor", unpause_monitor_exec, unpausemonitor_synopsis, unpausemonitor_descrip);
00781 ast_manager_register2("Monitor", EVENT_FLAG_CALL, start_monitor_action, monitor_synopsis, start_monitor_action_help);
00782 ast_manager_register2("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action, stopmonitor_synopsis, stop_monitor_action_help);
00783 ast_manager_register2("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action, changemonitor_synopsis, change_monitor_action_help);
00784 ast_manager_register2("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action, pausemonitor_synopsis, pause_monitor_action_help);
00785 ast_manager_register2("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action, unpausemonitor_synopsis, unpause_monitor_action_help);
00786
00787 return AST_MODULE_LOAD_SUCCESS;
00788 }
00789
00790 static int unload_module(void)
00791 {
00792 ast_unregister_application("Monitor");
00793 ast_unregister_application("StopMonitor");
00794 ast_unregister_application("ChangeMonitor");
00795 ast_unregister_application("PauseMonitor");
00796 ast_unregister_application("UnpauseMonitor");
00797 ast_manager_unregister("Monitor");
00798 ast_manager_unregister("StopMonitor");
00799 ast_manager_unregister("ChangeMonitor");
00800 ast_manager_unregister("PauseMonitor");
00801 ast_manager_unregister("UnpauseMonitor");
00802
00803 return 0;
00804 }
00805
00806
00807 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Call Monitoring Resource",
00808 .load = load_module,
00809 .unload = unload_module,
00810 );