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