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