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