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
00027
00028
00029
00030 #include "asterisk.h"
00031
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 413586 $")
00033
00034 #include <sys/stat.h>
00035 #include <libgen.h>
00036
00037 #include "asterisk/paths.h"
00038 #include "asterisk/lock.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/file.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/manager.h"
00044 #include "asterisk/cli.h"
00045 #define AST_API_MODULE
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
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 AST_MUTEX_DEFINE_STATIC(monitorlock);
00247
00248 #define LOCK_IF_NEEDED(lock, needed) do { \
00249 if (needed) \
00250 ast_channel_lock(lock); \
00251 } while(0)
00252
00253 #define UNLOCK_IF_NEEDED(lock, needed) do { \
00254 if (needed) \
00255 ast_channel_unlock(lock); \
00256 } while (0)
00257
00258 static unsigned long seq = 0;
00259
00260
00261
00262
00263
00264
00265
00266
00267 static int ast_monitor_set_state(struct ast_channel *chan, int state)
00268 {
00269 LOCK_IF_NEEDED(chan, 1);
00270 if (!chan->monitor) {
00271 UNLOCK_IF_NEEDED(chan, 1);
00272 return -1;
00273 }
00274 chan->monitor->state = state;
00275 UNLOCK_IF_NEEDED(chan, 1);
00276 return 0;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const char *format_spec,
00291 const char *fname_base, int need_lock, int stream_action)
00292 {
00293 int res = 0;
00294
00295 LOCK_IF_NEEDED(chan, need_lock);
00296
00297 if (!(chan->monitor)) {
00298 struct ast_channel_monitor *monitor;
00299 char *channel_name, *p;
00300
00301
00302 ast_mkdir(ast_config_AST_MONITOR_DIR, 0777);
00303
00304 if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
00305 UNLOCK_IF_NEEDED(chan, need_lock);
00306 return -1;
00307 }
00308
00309
00310 if (!ast_strlen_zero(fname_base)) {
00311 int directory = strchr(fname_base, '/') ? 1 : 0;
00312 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;
00313 const char *absolute_suffix = *fname_base == '/' ? "" : "/";
00314
00315 snprintf(monitor->read_filename, FILENAME_MAX, "%s%s%s-in",
00316 absolute, absolute_suffix, fname_base);
00317 snprintf(monitor->write_filename, FILENAME_MAX, "%s%s%s-out",
00318 absolute, absolute_suffix, fname_base);
00319 snprintf(monitor->filename_base, FILENAME_MAX, "%s%s%s",
00320 absolute, absolute_suffix, fname_base);
00321
00322
00323 if (directory) {
00324 char *name = ast_strdupa(monitor->filename_base);
00325 ast_mkdir(dirname(name), 0777);
00326 }
00327 } else {
00328 ast_mutex_lock(&monitorlock);
00329 snprintf(monitor->read_filename, FILENAME_MAX, "%s/audio-in-%lu",
00330 ast_config_AST_MONITOR_DIR, seq);
00331 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%lu",
00332 ast_config_AST_MONITOR_DIR, seq);
00333 seq++;
00334 ast_mutex_unlock(&monitorlock);
00335
00336
00337 channel_name = ast_strdupa(chan->name);
00338 for (p = channel_name; (p = strchr(p, '/')); ) {
00339 *p = '-';
00340 }
00341
00342 snprintf(monitor->filename_base, FILENAME_MAX, "%s/%d-%s",
00343 ast_config_AST_MONITOR_DIR, (int)time(NULL), channel_name);
00344 monitor->filename_changed = 1;
00345 }
00346
00347 monitor->stop = ast_monitor_stop;
00348
00349
00350 if (!ast_strlen_zero(format_spec)) {
00351 monitor->format = ast_strdup(format_spec);
00352 } else {
00353 monitor->format = ast_strdup("wav");
00354 }
00355
00356
00357 if (stream_action & X_REC_IN) {
00358 if (ast_fileexists(monitor->read_filename, NULL, NULL) > 0)
00359 ast_filedelete(monitor->read_filename, NULL);
00360 if (!(monitor->read_stream = ast_writefile(monitor->read_filename,
00361 monitor->format, NULL,
00362 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00363 ast_log(LOG_WARNING, "Could not create file %s\n",
00364 monitor->read_filename);
00365 ast_free(monitor);
00366 UNLOCK_IF_NEEDED(chan, need_lock);
00367 return -1;
00368 }
00369 } else
00370 monitor->read_stream = NULL;
00371
00372 if (stream_action & X_REC_OUT) {
00373 if (ast_fileexists(monitor->write_filename, NULL, NULL) > 0) {
00374 ast_filedelete(monitor->write_filename, NULL);
00375 }
00376 if (!(monitor->write_stream = ast_writefile(monitor->write_filename,
00377 monitor->format, NULL,
00378 O_CREAT|O_TRUNC|O_WRONLY, 0, AST_FILE_MODE))) {
00379 ast_log(LOG_WARNING, "Could not create file %s\n",
00380 monitor->write_filename);
00381 if (monitor->read_stream) {
00382 ast_closestream(monitor->read_stream);
00383 }
00384 ast_free(monitor);
00385 UNLOCK_IF_NEEDED(chan, need_lock);
00386 return -1;
00387 }
00388 } else
00389 monitor->write_stream = NULL;
00390
00391 chan->monitor = monitor;
00392 ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00393
00394 pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00395
00396 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStart",
00397 "Channel: %s\r\n"
00398 "Uniqueid: %s\r\n",
00399 chan->name,
00400 chan->uniqueid);
00401 } else {
00402 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name);
00403 res = -1;
00404 }
00405
00406 UNLOCK_IF_NEEDED(chan, need_lock);
00407
00408 return res;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418 static const char *get_soxmix_format(const char *format)
00419 {
00420 const char *res = format;
00421
00422 if (!strcasecmp(format,"ulaw"))
00423 res = "ul";
00424 if (!strcasecmp(format,"alaw"))
00425 res = "al";
00426
00427 return res;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436
00437 int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock)
00438 {
00439 int delfiles = 0;
00440
00441 LOCK_IF_NEEDED(chan, need_lock);
00442
00443 if (chan->monitor) {
00444 char filename[ FILENAME_MAX ];
00445
00446 if (chan->monitor->read_stream) {
00447 ast_closestream(chan->monitor->read_stream);
00448 }
00449 if (chan->monitor->write_stream) {
00450 ast_closestream(chan->monitor->write_stream);
00451 }
00452
00453 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00454 if (chan->monitor->read_stream) {
00455 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00456 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00457 if (ast_fileexists(filename, NULL, NULL) > 0) {
00458 ast_filedelete(filename, NULL);
00459 }
00460 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00461 } else {
00462 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00463 }
00464 }
00465
00466 if (chan->monitor->write_stream) {
00467 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00468 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00469 if (ast_fileexists(filename, NULL, NULL) > 0) {
00470 ast_filedelete(filename, NULL);
00471 }
00472 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00473 } else {
00474 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00475 }
00476 }
00477 }
00478
00479 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00480 char tmp[1024];
00481 char tmp2[1024];
00482 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00483 char *fname_base = chan->monitor->filename_base;
00484 const char *execute, *execute_args;
00485
00486
00487
00488 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00489 if (ast_strlen_zero(execute)) {
00490 #ifdef HAVE_SOXMIX
00491 execute = "nice -n 19 soxmix";
00492 #else
00493 execute = "nice -n 19 sox -m";
00494 #endif
00495 format = get_soxmix_format(format);
00496 delfiles = 1;
00497 }
00498 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00499 if (ast_strlen_zero(execute_args)) {
00500 execute_args = "";
00501 }
00502
00503 snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &",
00504 execute, fname_base, format, fname_base, format, fname_base, format,execute_args);
00505 if (delfiles) {
00506 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base);
00507 ast_copy_string(tmp, tmp2, sizeof(tmp));
00508 }
00509 ast_debug(1,"monitor executing %s\n",tmp);
00510 if (ast_safe_system(tmp) == -1)
00511 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00512 }
00513
00514 ast_free(chan->monitor->format);
00515 ast_free(chan->monitor);
00516 chan->monitor = NULL;
00517
00518 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop",
00519 "Channel: %s\r\n"
00520 "Uniqueid: %s\r\n",
00521 chan->name,
00522 chan->uniqueid
00523 );
00524 pbx_builtin_setvar_helper(chan, "MONITORED", NULL);
00525 }
00526 pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL);
00527
00528 UNLOCK_IF_NEEDED(chan, need_lock);
00529
00530 return 0;
00531 }
00532
00533
00534
00535 int AST_OPTIONAL_API_NAME(ast_monitor_pause)(struct ast_channel *chan)
00536 {
00537 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00538 }
00539
00540
00541 int AST_OPTIONAL_API_NAME(ast_monitor_unpause)(struct ast_channel *chan)
00542 {
00543 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00544 }
00545
00546
00547 static int pause_monitor_exec(struct ast_channel *chan, const char *data)
00548 {
00549 return ast_monitor_pause(chan);
00550 }
00551
00552
00553 static int unpause_monitor_exec(struct ast_channel *chan, const char *data)
00554 {
00555 return ast_monitor_unpause(chan);
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 int AST_OPTIONAL_API_NAME(ast_monitor_change_fname)(struct ast_channel *chan, const char *fname_base, int need_lock)
00567 {
00568 if (ast_strlen_zero(fname_base)) {
00569 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00570 return -1;
00571 }
00572
00573 LOCK_IF_NEEDED(chan, need_lock);
00574
00575 if (chan->monitor) {
00576 int directory = strchr(fname_base, '/') ? 1 : 0;
00577 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;
00578 const char *absolute_suffix = *fname_base == '/' ? "" : "/";
00579 char tmpstring[sizeof(chan->monitor->filename_base)] = "";
00580 int i, fd[2] = { -1, -1 }, doexit = 0;
00581
00582
00583 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base);
00584
00585
00586 if (directory) {
00587 char *name = ast_strdupa(tmpstring);
00588 ast_mkdir(dirname(name), 0777);
00589 }
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base);
00604
00605 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
00606 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
00607 if (fd[0] < 0) {
00608 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));
00609 } else {
00610 ast_debug(2, "No need to rename monitor filename to itself\n");
00611 }
00612 doexit = 1;
00613 }
00614
00615
00616 for (i = 0; i < 2; i++) {
00617 if (fd[i] >= 0) {
00618 while (close(fd[i]) < 0 && errno == EINTR);
00619 }
00620 }
00621 unlink(tmpstring);
00622
00623 unlink(chan->monitor->filename_base);
00624
00625 if (doexit) {
00626 UNLOCK_IF_NEEDED(chan, need_lock);
00627 return 0;
00628 }
00629
00630 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base));
00631 chan->monitor->filename_changed = 1;
00632 } else {
00633 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00634 }
00635
00636 UNLOCK_IF_NEEDED(chan, need_lock);
00637
00638 return 0;
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 static int start_monitor_exec(struct ast_channel *chan, const char *data)
00650 {
00651 char *arg;
00652 char *options;
00653 char *delay;
00654 char *urlprefix = NULL;
00655 char tmp[256];
00656 int stream_action = X_REC_IN | X_REC_OUT;
00657 int joinfiles = 0;
00658 int waitforbridge = 0;
00659 int res = 0;
00660 char *parse;
00661 AST_DECLARE_APP_ARGS(args,
00662 AST_APP_ARG(format);
00663 AST_APP_ARG(fname_base);
00664 AST_APP_ARG(options);
00665 );
00666
00667
00668 if (ast_strlen_zero(data)) {
00669 ast_log(LOG_ERROR, "Monitor requires an argument\n");
00670 return 0;
00671 }
00672
00673 parse = ast_strdupa(data);
00674 AST_STANDARD_APP_ARGS(args, parse);
00675
00676 if (!ast_strlen_zero(args.options)) {
00677 if (strchr(args.options, 'm'))
00678 stream_action |= X_JOIN;
00679 if (strchr(args.options, 'b'))
00680 waitforbridge = 1;
00681 if (strchr(args.options, 'i'))
00682 stream_action &= ~X_REC_IN;
00683 if (strchr(args.options, 'o'))
00684 stream_action &= ~X_REC_OUT;
00685 }
00686
00687 arg = strchr(args.format, ':');
00688 if (arg) {
00689 *arg++ = 0;
00690 urlprefix = arg;
00691 }
00692
00693 if (!ast_strlen_zero(urlprefix) && !ast_strlen_zero(args.fname_base)) {
00694 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base,
00695 ((strcmp(args.format, "gsm")) ? "wav" : "gsm"));
00696 ast_channel_lock(chan);
00697 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) {
00698 ast_channel_unlock(chan);
00699 return -1;
00700 }
00701 ast_cdr_setuserfield(chan, tmp);
00702 ast_channel_unlock(chan);
00703 }
00704 if (waitforbridge) {
00705
00706
00707
00708
00709 delay = ast_strdupa(data);
00710 options = strrchr(delay, ',');
00711 if (options) {
00712 arg = strchr(options, 'b');
00713 if (arg) {
00714 *arg = 'X';
00715 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);
00716 }
00717 }
00718 return 0;
00719 }
00720
00721 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action);
00722 if (res < 0)
00723 res = ast_monitor_change_fname(chan, args.fname_base, 1);
00724
00725 if (stream_action & X_JOIN) {
00726 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))
00727 joinfiles = 1;
00728 else
00729 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");
00730 }
00731 ast_monitor_setjoinfiles(chan, joinfiles);
00732
00733 return res;
00734 }
00735
00736
00737 static int stop_monitor_exec(struct ast_channel *chan, const char *data)
00738 {
00739 return ast_monitor_stop(chan, 1);
00740 }
00741
00742
00743 static int change_monitor_exec(struct ast_channel *chan, const char *data)
00744 {
00745 return ast_monitor_change_fname(chan, data, 1);
00746 }
00747
00748
00749 static int start_monitor_action(struct mansession *s, const struct message *m)
00750 {
00751 struct ast_channel *c = NULL;
00752 const char *name = astman_get_header(m, "Channel");
00753 const char *fname = astman_get_header(m, "File");
00754 const char *format = astman_get_header(m, "Format");
00755 const char *mix = astman_get_header(m, "Mix");
00756 char *d;
00757
00758 if (ast_strlen_zero(name)) {
00759 astman_send_error(s, m, "No channel specified");
00760 return AMI_SUCCESS;
00761 }
00762
00763 if (!(c = ast_channel_get_by_name(name))) {
00764 astman_send_error(s, m, "No such channel");
00765 return AMI_SUCCESS;
00766 }
00767
00768 if (ast_strlen_zero(fname)) {
00769
00770 ast_channel_lock(c);
00771 fname = ast_strdupa(c->name);
00772 ast_channel_unlock(c);
00773
00774
00775 for (d = (char *) fname; (d = strchr(d, '/')); ) {
00776 *d = '-';
00777 }
00778 }
00779
00780 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
00781 if (ast_monitor_change_fname(c, fname, 1)) {
00782 astman_send_error(s, m, "Could not start monitoring channel");
00783 c = ast_channel_unref(c);
00784 return AMI_SUCCESS;
00785 }
00786 }
00787
00788 if (ast_true(mix)) {
00789 ast_channel_lock(c);
00790 ast_monitor_setjoinfiles(c, 1);
00791 ast_channel_unlock(c);
00792 }
00793
00794 c = ast_channel_unref(c);
00795
00796 astman_send_ack(s, m, "Started monitoring channel");
00797
00798 return AMI_SUCCESS;
00799 }
00800
00801
00802 static int stop_monitor_action(struct mansession *s, const struct message *m)
00803 {
00804 struct ast_channel *c = NULL;
00805 const char *name = astman_get_header(m, "Channel");
00806 int res;
00807
00808 if (ast_strlen_zero(name)) {
00809 astman_send_error(s, m, "No channel specified");
00810 return AMI_SUCCESS;
00811 }
00812
00813 if (!(c = ast_channel_get_by_name(name))) {
00814 astman_send_error(s, m, "No such channel");
00815 return AMI_SUCCESS;
00816 }
00817
00818 res = ast_monitor_stop(c, 1);
00819
00820 c = ast_channel_unref(c);
00821
00822 if (res) {
00823 astman_send_error(s, m, "Could not stop monitoring channel");
00824 return AMI_SUCCESS;
00825 }
00826
00827 astman_send_ack(s, m, "Stopped monitoring channel");
00828
00829 return AMI_SUCCESS;
00830 }
00831
00832
00833 static int change_monitor_action(struct mansession *s, const struct message *m)
00834 {
00835 struct ast_channel *c = NULL;
00836 const char *name = astman_get_header(m, "Channel");
00837 const char *fname = astman_get_header(m, "File");
00838
00839 if (ast_strlen_zero(name)) {
00840 astman_send_error(s, m, "No channel specified");
00841 return AMI_SUCCESS;
00842 }
00843
00844 if (ast_strlen_zero(fname)) {
00845 astman_send_error(s, m, "No filename specified");
00846 return AMI_SUCCESS;
00847 }
00848
00849 if (!(c = ast_channel_get_by_name(name))) {
00850 astman_send_error(s, m, "No such channel");
00851 return AMI_SUCCESS;
00852 }
00853
00854 if (ast_monitor_change_fname(c, fname, 1)) {
00855 c = ast_channel_unref(c);
00856 astman_send_error(s, m, "Could not change monitored filename of channel");
00857 return AMI_SUCCESS;
00858 }
00859
00860 c = ast_channel_unref(c);
00861
00862 astman_send_ack(s, m, "Changed monitor filename");
00863
00864 return AMI_SUCCESS;
00865 }
00866
00867 void AST_OPTIONAL_API_NAME(ast_monitor_setjoinfiles)(struct ast_channel *chan, int turnon)
00868 {
00869 if (chan->monitor)
00870 chan->monitor->joinfiles = turnon;
00871 }
00872
00873 enum MONITOR_PAUSING_ACTION
00874 {
00875 MONITOR_ACTION_PAUSE,
00876 MONITOR_ACTION_UNPAUSE
00877 };
00878
00879 static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
00880 {
00881 struct ast_channel *c = NULL;
00882 const char *name = astman_get_header(m, "Channel");
00883
00884 if (ast_strlen_zero(name)) {
00885 astman_send_error(s, m, "No channel specified");
00886 return AMI_SUCCESS;
00887 }
00888
00889 if (!(c = ast_channel_get_by_name(name))) {
00890 astman_send_error(s, m, "No such channel");
00891 return AMI_SUCCESS;
00892 }
00893
00894 if (action == MONITOR_ACTION_PAUSE) {
00895 ast_monitor_pause(c);
00896 } else {
00897 ast_monitor_unpause(c);
00898 }
00899
00900 c = ast_channel_unref(c);
00901
00902 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00903
00904 return AMI_SUCCESS;
00905 }
00906
00907 static int pause_monitor_action(struct mansession *s, const struct message *m)
00908 {
00909 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00910 }
00911
00912 static int unpause_monitor_action(struct mansession *s, const struct message *m)
00913 {
00914 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00915 }
00916
00917 static int load_module(void)
00918 {
00919 ast_register_application_xml("Monitor", start_monitor_exec);
00920 ast_register_application_xml("StopMonitor", stop_monitor_exec);
00921 ast_register_application_xml("ChangeMonitor", change_monitor_exec);
00922 ast_register_application_xml("PauseMonitor", pause_monitor_exec);
00923 ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec);
00924 ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action);
00925 ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action);
00926 ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action);
00927 ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action);
00928 ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action);
00929
00930 return AST_MODULE_LOAD_SUCCESS;
00931 }
00932
00933 static int unload_module(void)
00934 {
00935 ast_unregister_application("Monitor");
00936 ast_unregister_application("StopMonitor");
00937 ast_unregister_application("ChangeMonitor");
00938 ast_unregister_application("PauseMonitor");
00939 ast_unregister_application("UnpauseMonitor");
00940 ast_manager_unregister("Monitor");
00941 ast_manager_unregister("StopMonitor");
00942 ast_manager_unregister("ChangeMonitor");
00943 ast_manager_unregister("PauseMonitor");
00944 ast_manager_unregister("UnpauseMonitor");
00945
00946 return 0;
00947 }
00948
00949
00950 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Call Monitoring Resource",
00951 .load = load_module,
00952 .unload = unload_module,
00953 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00954 );