![]() |
Home page |
Mailing list |
Docs
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 );