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