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