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: 328209 $")
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 if (!chan->cdr && !(chan->cdr = ast_cdr_alloc()))
00688 return -1;
00689 ast_cdr_setuserfield(chan, tmp);
00690 }
00691 if (waitforbridge) {
00692
00693
00694
00695
00696 delay = ast_strdupa(data);
00697 options = strrchr(delay, ',');
00698 if (options) {
00699 arg = strchr(options, 'b');
00700 if (arg) {
00701 *arg = 'X';
00702 pbx_builtin_setvar_helper(chan,"AUTO_MONITOR", delay);
00703 }
00704 }
00705 return 0;
00706 }
00707
00708 res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action);
00709 if (res < 0)
00710 res = ast_monitor_change_fname(chan, args.fname_base, 1);
00711
00712 if (stream_action & X_JOIN) {
00713 if ((stream_action & X_REC_IN) && (stream_action & X_REC_OUT))
00714 joinfiles = 1;
00715 else
00716 ast_log(LOG_WARNING, "Won't mix streams unless both input and output streams are recorded\n");
00717 }
00718 ast_monitor_setjoinfiles(chan, joinfiles);
00719
00720 return res;
00721 }
00722
00723
00724 static int stop_monitor_exec(struct ast_channel *chan, const char *data)
00725 {
00726 return ast_monitor_stop(chan, 1);
00727 }
00728
00729
00730 static int change_monitor_exec(struct ast_channel *chan, const char *data)
00731 {
00732 return ast_monitor_change_fname(chan, data, 1);
00733 }
00734
00735
00736 static int start_monitor_action(struct mansession *s, const struct message *m)
00737 {
00738 struct ast_channel *c = NULL;
00739 const char *name = astman_get_header(m, "Channel");
00740 const char *fname = astman_get_header(m, "File");
00741 const char *format = astman_get_header(m, "Format");
00742 const char *mix = astman_get_header(m, "Mix");
00743 char *d;
00744
00745 if (ast_strlen_zero(name)) {
00746 astman_send_error(s, m, "No channel specified");
00747 return 0;
00748 }
00749
00750 if (!(c = ast_channel_get_by_name(name))) {
00751 astman_send_error(s, m, "No such channel");
00752 return 0;
00753 }
00754
00755 if (ast_strlen_zero(fname)) {
00756
00757 ast_channel_lock(c);
00758 fname = ast_strdupa(c->name);
00759 ast_channel_unlock(c);
00760
00761 if ((d = strchr(fname, '/'))) {
00762 *d = '-';
00763 }
00764 }
00765
00766 if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
00767 if (ast_monitor_change_fname(c, fname, 1)) {
00768 astman_send_error(s, m, "Could not start monitoring channel");
00769 c = ast_channel_unref(c);
00770 return 0;
00771 }
00772 }
00773
00774 if (ast_true(mix)) {
00775 ast_channel_lock(c);
00776 ast_monitor_setjoinfiles(c, 1);
00777 ast_channel_unlock(c);
00778 }
00779
00780 c = ast_channel_unref(c);
00781
00782 astman_send_ack(s, m, "Started monitoring channel");
00783
00784 return 0;
00785 }
00786
00787
00788 static int stop_monitor_action(struct mansession *s, const struct message *m)
00789 {
00790 struct ast_channel *c = NULL;
00791 const char *name = astman_get_header(m, "Channel");
00792 int res;
00793
00794 if (ast_strlen_zero(name)) {
00795 astman_send_error(s, m, "No channel specified");
00796 return 0;
00797 }
00798
00799 if (!(c = ast_channel_get_by_name(name))) {
00800 astman_send_error(s, m, "No such channel");
00801 return 0;
00802 }
00803
00804 res = ast_monitor_stop(c, 1);
00805
00806 c = ast_channel_unref(c);
00807
00808 if (res) {
00809 astman_send_error(s, m, "Could not stop monitoring channel");
00810 return 0;
00811 }
00812
00813 astman_send_ack(s, m, "Stopped monitoring channel");
00814
00815 return 0;
00816 }
00817
00818
00819 static int change_monitor_action(struct mansession *s, const struct message *m)
00820 {
00821 struct ast_channel *c = NULL;
00822 const char *name = astman_get_header(m, "Channel");
00823 const char *fname = astman_get_header(m, "File");
00824
00825 if (ast_strlen_zero(name)) {
00826 astman_send_error(s, m, "No channel specified");
00827 return 0;
00828 }
00829
00830 if (ast_strlen_zero(fname)) {
00831 astman_send_error(s, m, "No filename specified");
00832 return 0;
00833 }
00834
00835 if (!(c = ast_channel_get_by_name(name))) {
00836 astman_send_error(s, m, "No such channel");
00837 return 0;
00838 }
00839
00840 if (ast_monitor_change_fname(c, fname, 1)) {
00841 c = ast_channel_unref(c);
00842 astman_send_error(s, m, "Could not change monitored filename of channel");
00843 return 0;
00844 }
00845
00846 c = ast_channel_unref(c);
00847
00848 astman_send_ack(s, m, "Changed monitor filename");
00849
00850 return 0;
00851 }
00852
00853 void AST_OPTIONAL_API_NAME(ast_monitor_setjoinfiles)(struct ast_channel *chan, int turnon)
00854 {
00855 if (chan->monitor)
00856 chan->monitor->joinfiles = turnon;
00857 }
00858
00859 enum MONITOR_PAUSING_ACTION
00860 {
00861 MONITOR_ACTION_PAUSE,
00862 MONITOR_ACTION_UNPAUSE
00863 };
00864
00865 static int do_pause_or_unpause(struct mansession *s, const struct message *m, int action)
00866 {
00867 struct ast_channel *c = NULL;
00868 const char *name = astman_get_header(m, "Channel");
00869
00870 if (ast_strlen_zero(name)) {
00871 astman_send_error(s, m, "No channel specified");
00872 return -1;
00873 }
00874
00875 if (!(c = ast_channel_get_by_name(name))) {
00876 astman_send_error(s, m, "No such channel");
00877 return -1;
00878 }
00879
00880 if (action == MONITOR_ACTION_PAUSE) {
00881 ast_monitor_pause(c);
00882 } else {
00883 ast_monitor_unpause(c);
00884 }
00885
00886 c = ast_channel_unref(c);
00887
00888 astman_send_ack(s, m, (action == MONITOR_ACTION_PAUSE ? "Paused monitoring of the channel" : "Unpaused monitoring of the channel"));
00889
00890 return 0;
00891 }
00892
00893 static int pause_monitor_action(struct mansession *s, const struct message *m)
00894 {
00895 return do_pause_or_unpause(s, m, MONITOR_ACTION_PAUSE);
00896 }
00897
00898 static int unpause_monitor_action(struct mansession *s, const struct message *m)
00899 {
00900 return do_pause_or_unpause(s, m, MONITOR_ACTION_UNPAUSE);
00901 }
00902
00903
00904 static int load_module(void)
00905 {
00906 ast_register_application_xml("Monitor", start_monitor_exec);
00907 ast_register_application_xml("StopMonitor", stop_monitor_exec);
00908 ast_register_application_xml("ChangeMonitor", change_monitor_exec);
00909 ast_register_application_xml("PauseMonitor", pause_monitor_exec);
00910 ast_register_application_xml("UnpauseMonitor", unpause_monitor_exec);
00911 ast_manager_register_xml("Monitor", EVENT_FLAG_CALL, start_monitor_action);
00912 ast_manager_register_xml("StopMonitor", EVENT_FLAG_CALL, stop_monitor_action);
00913 ast_manager_register_xml("ChangeMonitor", EVENT_FLAG_CALL, change_monitor_action);
00914 ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action);
00915 ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action);
00916
00917 return AST_MODULE_LOAD_SUCCESS;
00918 }
00919
00920 static int unload_module(void)
00921 {
00922 ast_unregister_application("Monitor");
00923 ast_unregister_application("StopMonitor");
00924 ast_unregister_application("ChangeMonitor");
00925 ast_unregister_application("PauseMonitor");
00926 ast_unregister_application("UnpauseMonitor");
00927 ast_manager_unregister("Monitor");
00928 ast_manager_unregister("StopMonitor");
00929 ast_manager_unregister("ChangeMonitor");
00930 ast_manager_unregister("PauseMonitor");
00931 ast_manager_unregister("UnpauseMonitor");
00932
00933 return 0;
00934 }
00935
00936
00937 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Call Monitoring Resource",
00938 .load = load_module,
00939 .unload = unload_module,
00940 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
00941 );