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: 355574 $")
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-%ld",
00330 ast_config_AST_MONITOR_DIR, seq);
00331 snprintf(monitor->write_filename, FILENAME_MAX, "%s/audio-out-%ld",
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 ast_closestream(monitor->read_stream);
00382 ast_free(monitor);
00383 UNLOCK_IF_NEEDED(chan, need_lock);
00384 return -1;
00385 }
00386 } else
00387 monitor->write_stream = NULL;
00388
00389 chan->monitor = monitor;
00390 ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00391
00392 pbx_builtin_setvar_helper(chan, "__MONITORED","true");
00393
00394 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStart",
00395 "Channel: %s\r\n"
00396 "Uniqueid: %s\r\n",
00397 chan->name,
00398 chan->uniqueid);
00399 } else {
00400 ast_debug(1,"Cannot start monitoring %s, already monitored\n", chan->name);
00401 res = -1;
00402 }
00403
00404 UNLOCK_IF_NEEDED(chan, need_lock);
00405
00406 return res;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416 static const char *get_soxmix_format(const char *format)
00417 {
00418 const char *res = format;
00419
00420 if (!strcasecmp(format,"ulaw"))
00421 res = "ul";
00422 if (!strcasecmp(format,"alaw"))
00423 res = "al";
00424
00425 return res;
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435 int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_lock)
00436 {
00437 int delfiles = 0;
00438
00439 LOCK_IF_NEEDED(chan, need_lock);
00440
00441 if (chan->monitor) {
00442 char filename[ FILENAME_MAX ];
00443
00444 if (chan->monitor->read_stream) {
00445 ast_closestream(chan->monitor->read_stream);
00446 }
00447 if (chan->monitor->write_stream) {
00448 ast_closestream(chan->monitor->write_stream);
00449 }
00450
00451 if (chan->monitor->filename_changed && !ast_strlen_zero(chan->monitor->filename_base)) {
00452 if (ast_fileexists(chan->monitor->read_filename,NULL,NULL) > 0) {
00453 snprintf(filename, FILENAME_MAX, "%s-in", chan->monitor->filename_base);
00454 if (ast_fileexists(filename, NULL, NULL) > 0) {
00455 ast_filedelete(filename, NULL);
00456 }
00457 ast_filerename(chan->monitor->read_filename, filename, chan->monitor->format);
00458 } else {
00459 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->read_filename);
00460 }
00461
00462 if (ast_fileexists(chan->monitor->write_filename,NULL,NULL) > 0) {
00463 snprintf(filename, FILENAME_MAX, "%s-out", chan->monitor->filename_base);
00464 if (ast_fileexists(filename, NULL, NULL) > 0) {
00465 ast_filedelete(filename, NULL);
00466 }
00467 ast_filerename(chan->monitor->write_filename, filename, chan->monitor->format);
00468 } else {
00469 ast_log(LOG_WARNING, "File %s not found\n", chan->monitor->write_filename);
00470 }
00471 }
00472
00473 if (chan->monitor->joinfiles && !ast_strlen_zero(chan->monitor->filename_base)) {
00474 char tmp[1024];
00475 char tmp2[1024];
00476 const char *format = !strcasecmp(chan->monitor->format,"wav49") ? "WAV" : chan->monitor->format;
00477 char *fname_base = chan->monitor->filename_base;
00478 const char *execute, *execute_args;
00479
00480
00481
00482 execute = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC");
00483 if (ast_strlen_zero(execute)) {
00484 #ifdef HAVE_SOXMIX
00485 execute = "nice -n 19 soxmix";
00486 #else
00487 execute = "nice -n 19 sox -m";
00488 #endif
00489 format = get_soxmix_format(format);
00490 delfiles = 1;
00491 }
00492 execute_args = pbx_builtin_getvar_helper(chan, "MONITOR_EXEC_ARGS");
00493 if (ast_strlen_zero(execute_args)) {
00494 execute_args = "";
00495 }
00496
00497 snprintf(tmp, sizeof(tmp), "%s \"%s-in.%s\" \"%s-out.%s\" \"%s.%s\" %s &",
00498 execute, fname_base, format, fname_base, format, fname_base, format,execute_args);
00499 if (delfiles) {
00500 snprintf(tmp2,sizeof(tmp2), "( %s& rm -f \"%s-\"* ) &",tmp, fname_base);
00501 ast_copy_string(tmp, tmp2, sizeof(tmp));
00502 }
00503 ast_debug(1,"monitor executing %s\n",tmp);
00504 if (ast_safe_system(tmp) == -1)
00505 ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
00506 }
00507
00508 ast_free(chan->monitor->format);
00509 ast_free(chan->monitor);
00510 chan->monitor = NULL;
00511
00512 ast_manager_event(chan, EVENT_FLAG_CALL, "MonitorStop",
00513 "Channel: %s\r\n"
00514 "Uniqueid: %s\r\n",
00515 chan->name,
00516 chan->uniqueid
00517 );
00518 pbx_builtin_setvar_helper(chan, "MONITORED", NULL);
00519 }
00520 pbx_builtin_setvar_helper(chan, "AUTO_MONITOR", NULL);
00521
00522 UNLOCK_IF_NEEDED(chan, need_lock);
00523
00524 return 0;
00525 }
00526
00527
00528
00529 int AST_OPTIONAL_API_NAME(ast_monitor_pause)(struct ast_channel *chan)
00530 {
00531 return ast_monitor_set_state(chan, AST_MONITOR_PAUSED);
00532 }
00533
00534
00535 int AST_OPTIONAL_API_NAME(ast_monitor_unpause)(struct ast_channel *chan)
00536 {
00537 return ast_monitor_set_state(chan, AST_MONITOR_RUNNING);
00538 }
00539
00540
00541 static int pause_monitor_exec(struct ast_channel *chan, const char *data)
00542 {
00543 return ast_monitor_pause(chan);
00544 }
00545
00546
00547 static int unpause_monitor_exec(struct ast_channel *chan, const char *data)
00548 {
00549 return ast_monitor_unpause(chan);
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 int AST_OPTIONAL_API_NAME(ast_monitor_change_fname)(struct ast_channel *chan, const char *fname_base, int need_lock)
00561 {
00562 if (ast_strlen_zero(fname_base)) {
00563 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name);
00564 return -1;
00565 }
00566
00567 LOCK_IF_NEEDED(chan, need_lock);
00568
00569 if (chan->monitor) {
00570 int directory = strchr(fname_base, '/') ? 1 : 0;
00571 const char *absolute = *fname_base == '/' ? "" : ast_config_AST_MONITOR_DIR;
00572 const char *absolute_suffix = *fname_base == '/' ? "" : "/";
00573 char tmpstring[sizeof(chan->monitor->filename_base)] = "";
00574 int i, fd[2] = { -1, -1 }, doexit = 0;
00575
00576
00577 snprintf(tmpstring, sizeof(tmpstring), "%s%s%s", absolute, absolute_suffix, fname_base);
00578
00579
00580 if (directory) {
00581 char *name = ast_strdupa(tmpstring);
00582 ast_mkdir(dirname(name), 0777);
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597 ast_debug(2, "comparing tmpstring %s to filename_base %s\n", tmpstring, chan->monitor->filename_base);
00598
00599 if ((fd[0] = open(tmpstring, O_CREAT | O_WRONLY, 0644)) < 0 ||
00600 (fd[1] = open(chan->monitor->filename_base, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
00601 if (fd[0] < 0) {
00602 ast_log(LOG_ERROR, "Unable to compare filenames: %s\n", strerror(errno));
00603 } else {
00604 ast_debug(2, "No need to rename monitor filename to itself\n");
00605 }
00606 doexit = 1;
00607 }
00608
00609
00610 for (i = 0; i < 2; i++) {
00611 if (fd[i] >= 0) {
00612 while (close(fd[i]) < 0 && errno == EINTR);
00613 }
00614 }
00615 unlink(tmpstring);
00616
00617 unlink(chan->monitor->filename_base);
00618
00619 if (doexit) {
00620 UNLOCK_IF_NEEDED(chan, need_lock);
00621 return 0;
00622 }
00623
00624 ast_copy_string(chan->monitor->filename_base, tmpstring, sizeof(chan->monitor->filename_base));
00625 chan->monitor->filename_changed = 1;
00626 } else {
00627 ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to %s, monitoring not started\n", chan->name, fname_base);
00628 }
00629
00630 UNLOCK_IF_NEEDED(chan, need_lock);
00631
00632 return 0;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 static int start_monitor_exec(struct ast_channel *chan, const char *data)
00644 {
00645 char *arg;
00646 char *options;
00647 char *delay;
00648 char *urlprefix = NULL;
00649 char tmp[256];
00650 int stream_action = X_REC_IN | X_REC_OUT;
00651 int joinfiles = 0;
00652 int waitforbridge = 0;
00653 int res = 0;
00654 char *parse;
00655 AST_DECLARE_APP_ARGS(args,
00656 AST_APP_ARG(format);
00657 AST_APP_ARG(fname_base);
00658 AST_APP_ARG(options);
00659 );
00660
00661
00662 if (ast_strlen_zero(data)) {
00663 ast_log(LOG_ERROR, "Monitor requires an argument\n");
00664 return 0;
00665 }
00666
00667 parse = ast_strdupa(data);
00668 AST_STANDARD_APP_ARGS(args, parse);
00669
00670 if (!ast_strlen_zero(args.options)) {
00671 if (strchr(args.options, 'm'))
00672 stream_action |= X_JOIN;
00673 if (strchr(args.options, 'b'))
00674 waitforbridge = 1;
00675 if (strchr(args.options, 'i'))
00676 stream_action &= ~X_REC_IN;
00677 if (strchr(args.options, 'o'))
00678 stream_action &= ~X_REC_OUT;
00679 }
00680
00681 arg = strchr(args.format, ':');
00682 if (arg) {
00683 *arg++ = 0;
00684 urlprefix = arg;
00685 }
00686
00687 if (!ast_strlen_zero(urlprefix) && !ast_strlen_zero(args.fname_base)) {
00688 snprintf(tmp, sizeof(tmp), "%s/%s.%s", urlprefix, args.fname_base,
00689 ((strcmp(args.format, "gsm")) ? "wav" : "gsm"));
00690 ast_channel_lock(chan);
00691 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc())) {
00692 ast_channel_unlock(chan);
00693 return -1;
00694 }
00695 ast_cdr_setuserfield(chan, tmp);
00696 ast_channel_unlock(chan);
00697 }
00698 if (waitforbridge) {
00699
00700
00701
00702
00703 delay = ast_strdupa(data);
00704 options = strrchr(delay, ',');
00705 if (options) {
00706 arg = strchr(options, 'b');
00707 if (arg) {
00708 *arg = 'X';
00709 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);
00710 }
00711 }
00712 return 0;
00713 }
00714
00715 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action);
00716 if (res < 0)
00717 res = ast_monitor_change_fname(chan, args.fname_base, 1);
00718
00719 if (stream_action & X_JOIN) {
00720 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))
00721 joinfiles = 1;
00722 else
00723 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");
00724 }
00725 ast_monitor_setjoinfiles(chan, joinfiles);
00726
00727 return res;
00728 }
00729
00730
00731 static int stop_monitor_exec(struct ast_channel *chan, const char *data)
00732 {
00733 return ast_monitor_stop(chan, 1);
00734 }
00735
00736
00737 static int change_monitor_exec(struct ast_channel *chan, const char *data)
00738 {
00739 return ast_monitor_change_fname(chan, data, 1);
00740 }
00741
00742
00743 static int start_monitor_action(struct mansession *s, const struct message *m)
00744 {
00745 struct ast_channel *c = NULL;
00746 const char *name = astman_get_header(m, "Channel");
00747 const char *fname = astman_get_header(m, "File");
00748 const char *format = astman_get_header(m, "Format");
00749 const char *mix = astman_get_header(m, "Mix");
00750 char *d;
00751
00752 if (ast_strlen_zero(name)) {
00753 astman_send_error(s, m, "No channel specified");
00754 return AMI_SUCCESS;
00755 }
00756
00757 if (!(c = ast_channel_get_by_name(name))) {
00758 astman_send_error(s, m, "No such channel");
00759 return AMI_SUCCESS;
00760 }
00761
00762 if (ast_strlen_zero(fname)) {
00763
00764 ast_channel_lock(c);
00765 fname = ast_strdupa(c->name);
00766 ast_channel_unlock(c);
00767
00768
00769 for (d = (char *) fname; (d = strchr(d, '/')); ) {
00770 *d = '-';
00771 }
00772 }
00773
00774 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
00775 if (ast_monitor_change_fname(c, fname, 1)) {
00776 astman_send_error(s, m, "Could not start monitoring channel");
00777 c = ast_channel_unref(c);
00778 return AMI_SUCCESS;
00779 }
00780 }
00781
00782 if (ast_true(mix)) {
00783 ast_channel_lock(c);
00784 ast_monitor_setjoinfiles(c, 1);
00785 ast_channel_unlock(c);
00786 }
00787
00788 c = ast_channel_unref(c);
00789
00790 astman_send_ack(s, m, "Started monitoring channel");
00791
00792 return AMI_SUCCESS;
00793 }
00794
00795
00796 static int stop_monitor_action(struct mansession *s, const struct message *m)
00797 {
00798 struct ast_channel *c = NULL;
00799 const char *name = astman_get_header(m, "Channel");
00800 int res;
00801
00802 if (ast_strlen_zero(name)) {
00803 astman_send_error(s, m, "No channel specified");
00804 return AMI_SUCCESS;
00805 }
00806
00807 if (!(c = ast_channel_get_by_name(name))) {
00808 astman_send_error(s, m, "No such channel");
00809 return AMI_SUCCESS;
00810 }
00811
00812 res = ast_monitor_stop(c, 1);
00813
00814 c = ast_channel_unref(c);
00815
00816 if (res) {
00817 astman_send_error(s, m, "Could not stop monitoring channel");
00818 return AMI_SUCCESS;
00819 }
00820
00821 astman_send_ack(s, m, "Stopped monitoring channel");
00822
00823 return AMI_SUCCESS;
00824 }
00825
00826
00827 static int change_monitor_action(struct mansession *s, const struct message *m)
00828 {
00829 struct ast_channel *c = NULL;
00830 const char *name = astman_get_header(m, "Channel");
00831 const char *fname = astman_get_header(m, "File");
00832
00833 if (ast_strlen_zero(name)) {
00834 astman_send_error(s, m, "No channel specified");
00835 return AMI_SUCCESS;
00836 }
00837
00838 if (ast_strlen_zero(fname)) {
00839 astman_send_error(s, m, "No filename specified");
00840 return AMI_SUCCESS;
00841 }
00842
00843 if (!(c = ast_channel_get_by_name(name))) {
00844 astman_send_error(s, m, "No such channel");
00845 return AMI_SUCCESS;
00846 }
00847
00848 if (ast_monitor_change_fname(c, fname, 1)) {
00849 c = ast_channel_unref(c);
00850 astman_send_error(s, m, "Could not change monitored filename of channel");
00851 return AMI_SUCCESS;
00852 }
00853
00854 c = ast_channel_unref(c);
00855
00856 astman_send_ack(s, m, "Changed monitor filename");
00857
00858 return AMI_SUCCESS;
00859 }
00860
00861 void AST_OPTIONAL_API_NAME(ast_monitor_setjoinfiles)(struct ast_channel *chan, int turnon)
00862 {
00863 if (chan->monitor)
00864 chan->monitor->joinfiles = turnon;
00865 }
00866
00867 enum MONITOR_PAUSING_ACTION
00868 {
00869 MONITOR_ACTION_PAUSE,
00870 MONITOR_ACTION_UNPAUSE
00871 };
00872
00873 static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
00874 {
00875 struct ast_channel *c = NULL;
00876 const char *name = astman_get_header(m, "Channel");
00877
00878 if (ast_strlen_zero(name)) {
00879 astman_send_error(s, m, "No channel specified");
00880 return AMI_SUCCESS;
00881 }
00882
00883 if (!(c = ast_channel_get_by_name(name))) {
00884 astman_send_error(s, m, "No such channel");
00885 return AMI_SUCCESS;
00886 }
00887
00888 if (action == MONITOR_ACTION_PAUSE) {
00889 ast_monitor_pause(c);
00890 } else {
00891 ast_monitor_unpause(c);
00892 }
00893
00894 c = ast_channel_unref(c);
00895
00896 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00897
00898 return AMI_SUCCESS;
00899 }
00900
00901 static int pause_monitor_action(struct mansession *s, const struct message *m)
00902 {
00903 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00904 }
00905
00906 static int unpause_monitor_action(struct mansession *s, const struct message *m)
00907 {
00908 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00909 }
00910
00911 static int load_module(void)
00912 {
00913 ast_register_application_xml("Monitor", start_monitor_exec);
00914 ast_register_application_xml("StopMonitor", stop_monitor_exec);
00915 ast_register_application_xml("ChangeMonitor", change_monitor_exec);
00916 ast_register_application_xml("PauseMonitor", pause_monitor_exec);
00917 ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec);
00918 ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action);
00919 ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action);
00920 ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action);
00921 ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action);
00922 ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action);
00923
00924 return AST_MODULE_LOAD_SUCCESS;
00925 }
00926
00927 static int unload_module(void)
00928 {
00929 ast_unregister_application("Monitor");
00930 ast_unregister_application("StopMonitor");
00931 ast_unregister_application("ChangeMonitor");
00932 ast_unregister_application("PauseMonitor");
00933 ast_unregister_application("UnpauseMonitor");
00934 ast_manager_unregister("Monitor");
00935 ast_manager_unregister("StopMonitor");
00936 ast_manager_unregister("ChangeMonitor");
00937 ast_manager_unregister("PauseMonitor");
00938 ast_manager_unregister("UnpauseMonitor");
00939
00940 return 0;
00941 }
00942
00943
00944 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Call Monitoring Resource",
00945 .load = load_module,
00946 .unload = unload_module,
00947 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00948 );