Asterisk - The Open Source Telephony Project  GIT-master-9ed6387
Data Structures | Macros | Enumerations | Functions | Variables
app_mixmonitor.c File Reference

MixMonitor() - Record a call and mix the audio during the recording. More...

#include "asterisk.h"
#include "asterisk/paths.h"
#include "asterisk/stringfields.h"
#include "asterisk/file.h"
#include "asterisk/audiohook.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/autochan.h"
#include "asterisk/manager.h"
#include "asterisk/callerid.h"
#include "asterisk/mod_format.h"
#include "asterisk/linkedlists.h"
#include "asterisk/test.h"
#include "asterisk/mixmonitor.h"
#include "asterisk/format_cache.h"
#include "asterisk/beep.h"

Go to the source code of this file.

Data Structures

struct  mixmonitor
 
struct  mixmonitor_ds
 
struct  vm_recipient
 

Macros

#define get_volfactor(x)   x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0
 
#define SAMPLES_PER_FRAME   160
 

Enumerations

enum  mixmonitor_args {
  OPT_ARG_READVOLUME = 0, OPT_ARG_WRITEVOLUME, OPT_ARG_VOLUME, OPT_ARG_WRITENAME,
  OPT_ARG_READNAME, OPT_ARG_UID, OPT_ARG_VMRECIPIENTS, OPT_ARG_BEEP_INTERVAL,
  OPT_ARG_DEPRECATED_RWSYNC, OPT_ARG_NO_RWSYNC, OPT_ARG_ARRAY_SIZE
}
 
enum  mixmonitor_flags {
  MUXFLAG_APPEND = (1 << 1), MUXFLAG_BRIDGED = (1 << 2), MUXFLAG_VOLUME = (1 << 3), MUXFLAG_READVOLUME = (1 << 4),
  MUXFLAG_WRITEVOLUME = (1 << 5), MUXFLAG_READ = (1 << 6), MUXFLAG_WRITE = (1 << 7), MUXFLAG_COMBINED = (1 << 8),
  MUXFLAG_UID = (1 << 9), MUXFLAG_VMRECIPIENTS = (1 << 10), MUXFLAG_BEEP = (1 << 11), MUXFLAG_BEEP_START = (1 << 12),
  MUXFLAG_BEEP_STOP = (1 << 13), MUXFLAG_DEPRECATED_RWSYNC = (1 << 14), MUXFLAG_NO_RWSYNC = (1 << 15)
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static void add_vm_recipients_from_string (struct mixmonitor *mixmonitor, const char *vm_recipients)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int clear_mixmonitor_methods (void)
 
static void clear_mixmonitor_recipient_list (struct mixmonitor *mixmonitor)
 
static void copy_to_voicemail (struct mixmonitor *mixmonitor, const char *ext, const char *filename)
 
static void destroy_monitor_audiohook (struct mixmonitor *mixmonitor)
 
static char * filename_parse (char *filename, char *buffer, size_t len)
 
static int func_mixmonitor_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static char * handle_cli_mixmonitor (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int launch_monitor_thread (struct ast_channel *chan, const char *filename, unsigned int flags, int readvol, int writevol, const char *post_process, const char *filename_write, char *filename_read, const char *uid_channel_var, const char *recipients, const char *beep_id)
 
static int load_module (void)
 
static int manager_mixmonitor (struct mansession *s, const struct message *m)
 
static int manager_mute_mixmonitor (struct mansession *s, const struct message *m)
 Mute / unmute a MixMonitor channel. More...
 
static int manager_stop_mixmonitor (struct mansession *s, const struct message *m)
 
static int mixmonitor_autochan_is_bridged (struct ast_autochan *autochan)
 
static void mixmonitor_ds_close_fs (struct mixmonitor_ds *mixmonitor_ds)
 
static void mixmonitor_ds_destroy (void *data)
 
static int mixmonitor_exec (struct ast_channel *chan, const char *data)
 
static void mixmonitor_free (struct mixmonitor *mixmonitor)
 
static void mixmonitor_save_prep (struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag, char **ext)
 
static void * mixmonitor_thread (void *obj)
 
static int set_mixmonitor_methods (void)
 
static int setup_mixmonitor_ds (struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id, const char *beep_id)
 
static int start_mixmonitor_callback (struct ast_channel *chan, const char *filename, const char *options)
 
static int startmon (struct ast_channel *chan, struct ast_audiohook *audiohook)
 
static int stop_mixmonitor_callback (struct ast_channel *chan, const char *mixmonitor_id)
 
static int stop_mixmonitor_exec (struct ast_channel *chan, const char *data)
 
static int stop_mixmonitor_full (struct ast_channel *chan, const char *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mixed Audio Monitoring Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .optional_modules = "func_periodic_hook", }
 
static const char *const app = "MixMonitor"
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_cli_entry cli_mixmonitor []
 
static const struct ast_datastore_info mixmonitor_ds_info
 
static struct ast_custom_function mixmonitor_function
 
static const struct ast_app_option mixmonitor_opts [128] = { [ 'a' ] = { .flag = MUXFLAG_APPEND }, [ 'b' ] = { .flag = MUXFLAG_BRIDGED }, [ 'B' ] = { .flag = MUXFLAG_BEEP , .arg_index = OPT_ARG_BEEP_INTERVAL + 1 }, [ 'p' ] = { .flag = MUXFLAG_BEEP_START }, [ 'P' ] = { .flag = MUXFLAG_BEEP_STOP }, [ 'v' ] = { .flag = MUXFLAG_READVOLUME , .arg_index = OPT_ARG_READVOLUME + 1 }, [ 'V' ] = { .flag = MUXFLAG_WRITEVOLUME , .arg_index = OPT_ARG_WRITEVOLUME + 1 }, [ 'W' ] = { .flag = MUXFLAG_VOLUME , .arg_index = OPT_ARG_VOLUME + 1 }, [ 'r' ] = { .flag = MUXFLAG_READ , .arg_index = OPT_ARG_READNAME + 1 }, [ 't' ] = { .flag = MUXFLAG_WRITE , .arg_index = OPT_ARG_WRITENAME + 1 }, [ 'i' ] = { .flag = MUXFLAG_UID , .arg_index = OPT_ARG_UID + 1 }, [ 'm' ] = { .flag = MUXFLAG_VMRECIPIENTS , .arg_index = OPT_ARG_VMRECIPIENTS + 1 }, [ 'S' ] = { .flag = MUXFLAG_DEPRECATED_RWSYNC , .arg_index = OPT_ARG_DEPRECATED_RWSYNC + 1 }, [ 'n' ] = { .flag = MUXFLAG_NO_RWSYNC , .arg_index = OPT_ARG_NO_RWSYNC + 1 }, }
 
static const char *const mixmonitor_spy_type = "MixMonitor"
 
static const char *const stop_app = "StopMixMonitor"
 

Detailed Description

MixMonitor() - Record a call and mix the audio during the recording.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Kevin P. Fleming kpfle.nosp@m.ming.nosp@m.@digi.nosp@m.um.c.nosp@m.om
Note
Based on app_muxmon.c provided by Anthony Minessale II anthm.nosp@m.ct@y.nosp@m.ahoo..nosp@m.com

Definition in file app_mixmonitor.c.

Macro Definition Documentation

◆ get_volfactor

#define get_volfactor (   x)    x ? ((x > 0) ? (1 << x) : ((1 << abs(x)) * -1)) : 0

Definition at line 301 of file app_mixmonitor.c.

Referenced by mixmonitor_exec().

◆ SAMPLES_PER_FRAME

#define SAMPLES_PER_FRAME   160

Definition at line 555 of file app_mixmonitor.c.

Referenced by mixmonitor_thread().

Enumeration Type Documentation

◆ mixmonitor_args

Enumerator
OPT_ARG_READVOLUME 
OPT_ARG_WRITEVOLUME 
OPT_ARG_VOLUME 
OPT_ARG_WRITENAME 
OPT_ARG_READNAME 
OPT_ARG_UID 
OPT_ARG_VMRECIPIENTS 
OPT_ARG_BEEP_INTERVAL 
OPT_ARG_DEPRECATED_RWSYNC 
OPT_ARG_NO_RWSYNC 
OPT_ARG_ARRAY_SIZE 

Definition at line 365 of file app_mixmonitor.c.

◆ mixmonitor_flags

Enumerator
MUXFLAG_APPEND 
MUXFLAG_BRIDGED 
MUXFLAG_VOLUME 
MUXFLAG_READVOLUME 
MUXFLAG_WRITEVOLUME 
MUXFLAG_READ 
MUXFLAG_WRITE 
MUXFLAG_COMBINED 
MUXFLAG_UID 
MUXFLAG_VMRECIPIENTS 
MUXFLAG_BEEP 
MUXFLAG_BEEP_START 
MUXFLAG_BEEP_STOP 
MUXFLAG_DEPRECATED_RWSYNC 
MUXFLAG_NO_RWSYNC 

Definition at line 347 of file app_mixmonitor.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 1607 of file app_mixmonitor.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 1607 of file app_mixmonitor.c.

◆ add_vm_recipients_from_string()

static void add_vm_recipients_from_string ( struct mixmonitor mixmonitor,
const char *  vm_recipients 
)
static

Definition at line 497 of file app_mixmonitor.c.

References ast_copy_string(), ast_debug, AST_LIST_INSERT_HEAD, ast_log, ast_malloc, ast_strdupa, ast_strlen_zero, ast_verb, vm_recipient::context, vm_recipient::folder, vm_recipient::list, LOG_ERROR, vm_recipient::mailbox, vm_recipient::next, and mixmonitor::recipient_list.

Referenced by launch_monitor_thread().

498 {
499  /* recipients are in a single string with a format format resembling "mailbox@context/INBOX,mailbox2@context2,mailbox3@context3/Work" */
500  char *cur_mailbox = ast_strdupa(vm_recipients);
501  char *cur_context;
502  char *cur_folder;
503  char *next;
504  int elements_processed = 0;
505 
506  while (!ast_strlen_zero(cur_mailbox)) {
507  ast_debug(3, "attempting to add next element %d from %s\n", elements_processed, cur_mailbox);
508  if ((next = strchr(cur_mailbox, ',')) || (next = strchr(cur_mailbox, '&'))) {
509  *(next++) = '\0';
510  }
511 
512  if ((cur_folder = strchr(cur_mailbox, '/'))) {
513  *(cur_folder++) = '\0';
514  } else {
515  cur_folder = "INBOX";
516  }
517 
518  if ((cur_context = strchr(cur_mailbox, '@'))) {
519  *(cur_context++) = '\0';
520  } else {
521  cur_context = "default";
522  }
523 
524  if (!ast_strlen_zero(cur_mailbox) && !ast_strlen_zero(cur_context)) {
525  struct vm_recipient *recipient;
526  if (!(recipient = ast_malloc(sizeof(*recipient)))) {
527  ast_log(LOG_ERROR, "Failed to allocate recipient. Aborting function.\n");
528  return;
529  }
530  ast_copy_string(recipient->context, cur_context, sizeof(recipient->context));
531  ast_copy_string(recipient->mailbox, cur_mailbox, sizeof(recipient->mailbox));
532  ast_copy_string(recipient->folder, cur_folder, sizeof(recipient->folder));
533 
534  /* Add to list */
535  ast_verb(4, "Adding %s@%s to recipient list\n", recipient->mailbox, recipient->context);
536  AST_LIST_INSERT_HEAD(&mixmonitor->recipient_list, recipient, list);
537  } else {
538  ast_log(LOG_ERROR, "Failed to properly parse extension and/or context from element %d of recipient string: %s\n", elements_processed, vm_recipients);
539  }
540 
541  cur_mailbox = next;
542  elements_processed++;
543  }
544 }
char mailbox[AST_MAX_CONTEXT]
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:193
#define LOG_ERROR
Definition: logger.h:285
#define ast_strlen_zero(a)
Definition: muted.c:73
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:710
struct vm_recipient::@57 list
char folder[80]
struct vm_recipient * next
struct minivm_account * next
Definition: app_minivm.c:621
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
char context[AST_MAX_EXTENSION]
struct mixmonitor::@58 recipient_list

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 1607 of file app_mixmonitor.c.

◆ clear_mixmonitor_methods()

static int clear_mixmonitor_methods ( void  )
static

Definition at line 1565 of file app_mixmonitor.c.

References ast_clear_mixmonitor_methods().

Referenced by unload_module().

1566 {
1568 }
int ast_clear_mixmonitor_methods(void)
Clear the MixMonitor virtual methods table. Use this to cleanup function pointers provided by a modul...
Definition: mixmonitor.c:59

◆ clear_mixmonitor_recipient_list()

static void clear_mixmonitor_recipient_list ( struct mixmonitor mixmonitor)
static

Definition at line 546 of file app_mixmonitor.c.

References ast_free, AST_LIST_REMOVE_HEAD, vm_recipient::list, and mixmonitor::recipient_list.

Referenced by mixmonitor_free().

547 {
548  struct vm_recipient *current;
549  while ((current = AST_LIST_REMOVE_HEAD(&mixmonitor->recipient_list, list))) {
550  /* Clear list element data */
551  ast_free(current);
552  }
553 }
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:832
#define ast_free(a)
Definition: astmm.h:182
struct vm_recipient::@57 list
struct mixmonitor::@58 recipient_list

◆ copy_to_voicemail()

static void copy_to_voicemail ( struct mixmonitor mixmonitor,
const char *  ext,
const char *  filename 
)
static

Definition at line 588 of file app_mixmonitor.c.

References ast_app_copy_recording_to_vm(), AST_LIST_TRAVERSE, ast_log, ast_string_field_free_memory, ast_string_field_init, ast_string_field_set, ast_verb, ast_vm_recording_data::call_callerchan, mixmonitor::call_callerchan, ast_vm_recording_data::call_callerid, mixmonitor::call_callerid, ast_vm_recording_data::call_context, mixmonitor::call_context, ast_vm_recording_data::call_extension, mixmonitor::call_extension, ast_vm_recording_data::call_macrocontext, mixmonitor::call_macrocontext, ast_vm_recording_data::call_priority, mixmonitor::call_priority, ast_vm_recording_data::context, vm_recipient::context, vm_recipient::folder, vm_recipient::list, LOG_ERROR, ast_vm_recording_data::mailbox, vm_recipient::mailbox, NULL, mixmonitor::recipient_list, ast_vm_recording_data::recording_ext, and ast_vm_recording_data::recording_file.

Referenced by mixmonitor_thread().

589 {
590  struct vm_recipient *recipient = NULL;
591  struct ast_vm_recording_data recording_data;
592  if (ast_string_field_init(&recording_data, 512)) {
593  ast_log(LOG_ERROR, "Failed to string_field_init, skipping copy_to_voicemail\n");
594  return;
595  }
596 
597  /* Copy strings to stringfields that will be used for all recipients */
598  ast_string_field_set(&recording_data, recording_file, filename);
599  ast_string_field_set(&recording_data, recording_ext, ext);
600  ast_string_field_set(&recording_data, call_context, mixmonitor->call_context);
601  ast_string_field_set(&recording_data, call_macrocontext, mixmonitor->call_macrocontext);
602  ast_string_field_set(&recording_data, call_extension, mixmonitor->call_extension);
603  ast_string_field_set(&recording_data, call_callerchan, mixmonitor->call_callerchan);
604  ast_string_field_set(&recording_data, call_callerid, mixmonitor->call_callerid);
605  /* and call_priority gets copied too */
606  recording_data.call_priority = mixmonitor->call_priority;
607 
608  AST_LIST_TRAVERSE(&mixmonitor->recipient_list, recipient, list) {
609  /* context, mailbox, and folder need to be set per recipient */
610  ast_string_field_set(&recording_data, context, recipient->context);
611  ast_string_field_set(&recording_data, mailbox, recipient->mailbox);
612  ast_string_field_set(&recording_data, folder, recipient->folder);
613 
614  ast_verb(4, "MixMonitor attempting to send voicemail copy to %s@%s\n", recording_data.mailbox,
615  recording_data.context);
616  ast_app_copy_recording_to_vm(&recording_data);
617  }
618 
619  /* Free the string fields for recording_data before exiting the function. */
620  ast_string_field_free_memory(&recording_data);
621 }
const ast_string_field recording_file
char mailbox[AST_MAX_CONTEXT]
#define NULL
Definition: resample.c:96
const ast_string_field call_callerchan
const char * ext
Definition: http.c:147
const ast_string_field folder
#define ast_verb(level,...)
Definition: logger.h:455
const ast_string_field recording_ext
static char mailbox[AST_MAX_MAILBOX_UNIQUEID]
Definition: chan_mgcp.c:204
#define ast_log
Definition: astobj2.c:42
const ast_string_field call_macrocontext
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
const ast_string_field call_callerid
#define LOG_ERROR
Definition: logger.h:285
const ast_string_field call_callerid
const ast_string_field call_macrocontext
const ast_string_field call_callerchan
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
char folder[80]
Structure used for ast_copy_recording_to_vm in order to cleanly supply data needed for making the rec...
const ast_string_field call_context
const ast_string_field call_context
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368
char context[AST_MAX_EXTENSION]
int ast_app_copy_recording_to_vm(struct ast_vm_recording_data *vm_rec_data)
param[in] vm_rec_data Contains data needed to make the recording. retval 0 voicemail successfully cre...
Definition: main/app.c:669
const ast_string_field call_extension
const ast_string_field call_extension
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
struct mixmonitor::@58 recipient_list

◆ destroy_monitor_audiohook()

static void destroy_monitor_audiohook ( struct mixmonitor mixmonitor)
static

Definition at line 468 of file app_mixmonitor.c.

References ast_audiohook_destroy(), ast_audiohook_detach(), ast_audiohook_lock, ast_audiohook_unlock, ast_mutex_lock, ast_mutex_unlock, mixmonitor::audiohook, mixmonitor_ds::audiohook, mixmonitor_ds::lock, mixmonitor::mixmonitor_ds, and NULL.

Referenced by mixmonitor_thread().

469 {
470  if (mixmonitor->mixmonitor_ds) {
471  ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
472  mixmonitor->mixmonitor_ds->audiohook = NULL;
473  ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
474  }
475  /* kill the audiohook.*/
476  ast_audiohook_lock(&mixmonitor->audiohook);
477  ast_audiohook_detach(&mixmonitor->audiohook);
478  ast_audiohook_unlock(&mixmonitor->audiohook);
479  ast_audiohook_destroy(&mixmonitor->audiohook);
480 }
#define ast_mutex_lock(a)
Definition: lock.h:187
struct mixmonitor_ds * mixmonitor_ds
#define NULL
Definition: resample.c:96
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:133
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:579
ast_mutex_t lock
struct ast_audiohook * audiohook
struct ast_audiohook audiohook
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ filename_parse()

static char* filename_parse ( char *  filename,
char *  buffer,
size_t  len 
)
static

Definition at line 1007 of file app_mixmonitor.c.

References ast_alloca, ast_assert, ast_config_AST_MONITOR_DIR, ast_copy_string(), ast_log, ast_mkdir(), ast_strlen_zero, ext, and LOG_WARNING.

Referenced by mixmonitor_exec().

1008 {
1009  char *slash;
1010  char *ext;
1011 
1012  ast_assert(len > 0);
1013 
1014  if (ast_strlen_zero(filename)) {
1015  ast_log(LOG_WARNING, "No file name was provided for a file save option.\n");
1016  buffer[0] = 0;
1017  return buffer;
1018  }
1019 
1020  /* If we don't have an absolute path, make one */
1021  if (*filename != '/') {
1022  char *build = ast_alloca(strlen(ast_config_AST_MONITOR_DIR) + strlen(filename) + 3);
1023  sprintf(build, "%s/%s", ast_config_AST_MONITOR_DIR, filename);
1024  filename = build;
1025  }
1026 
1027  ast_copy_string(buffer, filename, len);
1028 
1029  /* If the provided filename has a .wav49 extension, we need to convert it to .WAV to
1030  match the behavior of build_filename in main/file.c. Otherwise MIXMONITOR_FILENAME
1031  ends up referring to a file that does not/will not exist */
1032  ext = strrchr(buffer, '.');
1033  if (ext && !strcmp(ext, ".wav49")) {
1034  /* Change to WAV - we know we have at least 6 writeable bytes where 'ext' points,
1035  * so this is safe */
1036  memcpy(ext, ".WAV", sizeof(".WAV"));
1037  }
1038 
1039  if ((slash = strrchr(filename, '/'))) {
1040  *slash = '\0';
1041  }
1042  ast_mkdir(filename, 0777);
1043 
1044  return buffer;
1045 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_assert(a)
Definition: utils.h:650
const char * ext
Definition: http.c:147
#define ast_log
Definition: astobj2.c:42
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:290
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_strlen_zero(a)
Definition: muted.c:73
const char * ast_config_AST_MONITOR_DIR
Definition: options.c:152
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2102

◆ func_mixmonitor_read()

static int func_mixmonitor_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 1508 of file app_mixmonitor.c.

References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strlen_zero, ast_datastore::data, mixmonitor_ds::filename, and LOG_WARNING.

1510 {
1511  struct ast_datastore *datastore;
1512  struct mixmonitor_ds *ds_data;
1514  AST_APP_ARG(id);
1515  AST_APP_ARG(key);
1516  );
1517 
1518  AST_STANDARD_APP_ARGS(args, data);
1519 
1520  if (ast_strlen_zero(args.id) || ast_strlen_zero(args.key)) {
1521  ast_log(LOG_WARNING, "Not enough arguments provided to %s. "
1522  "An ID and key must be provided\n", cmd);
1523  return -1;
1524  }
1525 
1526  ast_channel_lock(chan);
1527  datastore = ast_channel_datastore_find(chan, &mixmonitor_ds_info, args.id);
1528  ast_channel_unlock(chan);
1529 
1530  if (!datastore) {
1531  ast_log(LOG_WARNING, "Could not find MixMonitor with ID %s\n", args.id);
1532  return -1;
1533  }
1534 
1535  ds_data = datastore->data;
1536 
1537  if (!strcasecmp(args.key, "filename")) {
1538  ast_copy_string(buf, ds_data->filename, len);
1539  } else {
1540  ast_log(LOG_WARNING, "Unrecognized %s option %s\n", cmd, args.key);
1541  return -1;
1542  }
1543  return 0;
1544 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2379
const char * args
static const struct ast_datastore_info mixmonitor_ds_info
#define ast_log
Definition: astobj2.c:42
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
void * data
Definition: datastore.h:70
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ handle_cli_mixmonitor()

static char* handle_cli_mixmonitor ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1254 of file app_mixmonitor.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_channel_datastores(), ast_channel_get_by_name_prefix(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_cli(), ast_complete_channels(), AST_LIST_TRAVERSE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_datastore::data, ast_cli_args::fd, ast_filestream::filename, mixmonitor_ds::fs, mixmonitor_ds::fs_read, mixmonitor_ds::fs_write, ast_datastore::info, ast_cli_args::line, mixmonitor_exec(), ast_cli_args::n, NULL, ast_cli_args::pos, stop_mixmonitor_exec(), ast_cli_entry::usage, and ast_cli_args::word.

1255 {
1256  struct ast_channel *chan;
1257  struct ast_datastore *datastore = NULL;
1258  struct mixmonitor_ds *mixmonitor_ds = NULL;
1259 
1260  switch (cmd) {
1261  case CLI_INIT:
1262  e->command = "mixmonitor {start|stop|list}";
1263  e->usage =
1264  "Usage: mixmonitor start <chan_name> [args]\n"
1265  " The optional arguments are passed to the MixMonitor application.\n"
1266  " mixmonitor stop <chan_name> [args]\n"
1267  " The optional arguments are passed to the StopMixMonitor application.\n"
1268  " mixmonitor list <chan_name>\n";
1269  return NULL;
1270  case CLI_GENERATE:
1271  return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
1272  }
1273 
1274  if (a->argc < 3) {
1275  return CLI_SHOWUSAGE;
1276  }
1277 
1278  if (!(chan = ast_channel_get_by_name_prefix(a->argv[2], strlen(a->argv[2])))) {
1279  ast_cli(a->fd, "No channel matching '%s' found.\n", a->argv[2]);
1280  /* Technically this is a failure, but we don't want 2 errors printing out */
1281  return CLI_SUCCESS;
1282  }
1283 
1284  if (!strcasecmp(a->argv[1], "start")) {
1285  mixmonitor_exec(chan, (a->argc >= 4) ? a->argv[3] : "");
1286  } else if (!strcasecmp(a->argv[1], "stop")){
1287  stop_mixmonitor_exec(chan, (a->argc >= 4) ? a->argv[3] : "");
1288  } else if (!strcasecmp(a->argv[1], "list")) {
1289  ast_cli(a->fd, "MixMonitor ID\tFile\tReceive File\tTransmit File\n");
1290  ast_cli(a->fd, "=========================================================================\n");
1291  ast_channel_lock(chan);
1292  AST_LIST_TRAVERSE(ast_channel_datastores(chan), datastore, entry) {
1293  if (datastore->info == &mixmonitor_ds_info) {
1294  char *filename = "";
1295  char *filename_read = "";
1296  char *filename_write = "";
1297 
1298  mixmonitor_ds = datastore->data;
1299  if (mixmonitor_ds->fs) {
1300  filename = mixmonitor_ds->fs->filename;
1301  }
1302  if (mixmonitor_ds->fs_read) {
1303  filename_read = mixmonitor_ds->fs_read->filename;
1304  }
1305  if (mixmonitor_ds->fs_write) {
1306  filename_write = mixmonitor_ds->fs_write->filename;
1307  }
1308  ast_cli(a->fd, "%p\t%s\t%s\t%s\n", mixmonitor_ds, filename, filename_read, filename_write);
1309  }
1310  }
1311  ast_channel_unlock(chan);
1312  } else {
1313  chan = ast_channel_unref(chan);
1314  return CLI_SHOWUSAGE;
1315  }
1316 
1317  chan = ast_channel_unref(chan);
1318 
1319  return CLI_SUCCESS;
1320 }
static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data)
#define ast_channel_lock(chan)
Definition: channel.h:2837
Main Channel structure associated with a channel.
struct ast_filestream * fs_read
struct ast_filestream * fs
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
const int argc
Definition: cli.h:160
Definition: cli.h:152
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info mixmonitor_ds_info
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
const char * line
Definition: cli.h:162
static int mixmonitor_exec(struct ast_channel *chan, const char *data)
struct ast_channel * ast_channel_get_by_name_prefix(const char *name, size_t name_len)
Find a channel by a name prefix.
Definition: channel.c:1419
const int fd
Definition: cli.h:159
const int n
Definition: cli.h:165
struct ast_datastore_list * ast_channel_datastores(struct ast_channel *chan)
const struct ast_datastore_info * info
Definition: datastore.h:71
const char *const * argv
Definition: cli.h:161
#define CLI_SHOWUSAGE
Definition: cli.h:45
struct ast_filestream * fs_write
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define ast_channel_unlock(chan)
Definition: channel.h:2838
char * command
Definition: cli.h:186
const char * word
Definition: cli.h:163
const char * usage
Definition: cli.h:177
#define CLI_SUCCESS
Definition: cli.h:44
void * data
Definition: datastore.h:70
char * filename
Definition: mod_format.h:107
const int pos
Definition: cli.h:164
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: main/cli.c:1783
Definition: search.h:40

◆ launch_monitor_thread()

static int launch_monitor_thread ( struct ast_channel chan,
const char *  filename,
unsigned int  flags,
int  readvol,
int  writevol,
const char *  post_process,
const char *  filename_write,
char *  filename_read,
const char *  uid_channel_var,
const char *  recipients,
const char *  beep_id 
)
static

Definition at line 868 of file app_mixmonitor.c.

References add_vm_recipients_from_string(), ast_audiohook_destroy(), ast_audiohook_init(), AST_AUDIOHOOK_SUBSTITUTE_SILENCE, AST_AUDIOHOOK_TRIGGER_SYNC, AST_AUDIOHOOK_TYPE_SPY, ast_autochan_destroy(), ast_autochan_setup(), ast_callerid_merge(), ast_calloc, ast_channel_connected(), ast_channel_context(), ast_channel_exten(), ast_channel_lock, ast_channel_macrocontext(), ast_channel_name(), ast_channel_priority(), ast_channel_unlock, ast_debug, ast_free, ast_log, ast_pthread_create_detached_background, ast_read_threadstorage_callid(), ast_set_flag, ast_strdup, ast_strdupa, ast_string_field_init, ast_string_field_set, ast_strlen_zero, ast_test_flag, mixmonitor::audiohook, mixmonitor::autochan, mixmonitor::call_priority, mixmonitor::callid, connected, mixmonitor::filename, mixmonitor::filename_read, mixmonitor::filename_write, mixmonitor::flags, ast_party_connected_line::id, LOG_WARNING, mixmonitor_free(), mixmonitor_spy_type, mixmonitor_thread(), MUXFLAG_NO_RWSYNC, mixmonitor::name, ast_party_id::name, NULL, ast_party_id::number, ast_audiohook::options, pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), mixmonitor::post_process, ast_audiohook_options::read_volume, S_COR, setup_mixmonitor_ds(), startmon(), ast_party_name::str, ast_party_number::str, thread, ast_party_name::valid, ast_party_number::valid, and ast_audiohook_options::write_volume.

Referenced by mixmonitor_exec().

873 {
874  pthread_t thread;
875  struct mixmonitor *mixmonitor;
876  char postprocess2[1024] = "";
877  char *datastore_id = NULL;
878 
879  postprocess2[0] = 0;
880  /* If a post process system command is given attach it to the structure */
882  char *p1, *p2;
883 
885  for (p2 = p1; *p2; p2++) {
886  if (*p2 == '^' && *(p2+1) == '{') {
887  *p2 = '$';
888  }
889  }
890  ast_channel_lock(chan);
891  pbx_substitute_variables_helper(chan, p1, postprocess2, sizeof(postprocess2) - 1);
892  ast_channel_unlock(chan);
893  }
894 
895  /* Pre-allocate mixmonitor structure and spy */
896  if (!(mixmonitor = ast_calloc(1, sizeof(*mixmonitor)))) {
897  return -1;
898  }
899 
900  /* Now that the struct has been calloced, go ahead and initialize the string fields. */
901  if (ast_string_field_init(mixmonitor, 512)) {
902  mixmonitor_free(mixmonitor);
903  return -1;
904  }
905 
906  /* Setup the actual spy before creating our thread */
908  mixmonitor_free(mixmonitor);
909  return -1;
910  }
911 
912  /* Copy over flags and channel name */
913  mixmonitor->flags = flags;
914  if (!(mixmonitor->autochan = ast_autochan_setup(chan))) {
915  mixmonitor_free(mixmonitor);
916  return -1;
917  }
918 
919  if (!ast_strlen_zero(filename)) {
920  mixmonitor->filename = ast_strdup(filename);
921  }
922 
925  }
926 
928  mixmonitor->filename_read = ast_strdup(filename_read);
929  }
930 
931  if (setup_mixmonitor_ds(mixmonitor, chan, &datastore_id, beep_id)) {
932  ast_autochan_destroy(mixmonitor->autochan);
933  mixmonitor_free(mixmonitor);
934  ast_free(datastore_id);
935  return -1;
936  }
937 
938  if (!ast_strlen_zero(uid_channel_var)) {
939  if (datastore_id) {
940  pbx_builtin_setvar_helper(chan, uid_channel_var, datastore_id);
941  }
942  }
943  ast_free(datastore_id);
944 
945  mixmonitor->name = ast_strdup(ast_channel_name(chan));
946 
947  if (!ast_strlen_zero(postprocess2)) {
948  mixmonitor->post_process = ast_strdup(postprocess2);
949  }
950 
951  if (!ast_strlen_zero(recipients)) {
952  char callerid[256];
954 
955  ast_channel_lock(chan);
956 
957  /* We use the connected line of the invoking channel for caller ID. */
958 
959  connected = ast_channel_connected(chan);
960  ast_debug(3, "Connected Line CID = %d - %s : %d - %s\n", connected->id.name.valid,
961  connected->id.name.str, connected->id.number.valid,
962  connected->id.number.str);
963  ast_callerid_merge(callerid, sizeof(callerid),
964  S_COR(connected->id.name.valid, connected->id.name.str, NULL),
965  S_COR(connected->id.number.valid, connected->id.number.str, NULL),
966  "Unknown");
967 
968  ast_string_field_set(mixmonitor, call_context, ast_channel_context(chan));
969  ast_string_field_set(mixmonitor, call_macrocontext, ast_channel_macrocontext(chan));
970  ast_string_field_set(mixmonitor, call_extension, ast_channel_exten(chan));
971  ast_string_field_set(mixmonitor, call_callerchan, ast_channel_name(chan));
972  ast_string_field_set(mixmonitor, call_callerid, callerid);
973  mixmonitor->call_priority = ast_channel_priority(chan);
974 
975  ast_channel_unlock(chan);
976 
977  add_vm_recipients_from_string(mixmonitor, recipients);
978  }
979 
981  if (!ast_test_flag(mixmonitor, MUXFLAG_NO_RWSYNC)) {
983  }
984 
985  if (readvol)
986  mixmonitor->audiohook.options.read_volume = readvol;
987  if (writevol)
988  mixmonitor->audiohook.options.write_volume = writevol;
989 
990  if (startmon(chan, &mixmonitor->audiohook)) {
991  ast_log(LOG_WARNING, "Unable to add '%s' spy to channel '%s'\n",
993  ast_autochan_destroy(mixmonitor->autochan);
994  ast_audiohook_destroy(&mixmonitor->audiohook);
995  mixmonitor_free(mixmonitor);
996  return -1;
997  }
998 
999  /* reference be released at mixmonitor destruction */
1000  mixmonitor->callid = ast_read_threadstorage_callid();
1001 
1002  return ast_pthread_create_detached_background(&thread, NULL, mixmonitor_thread, mixmonitor);
1003 }
pthread_t thread
Definition: app_meetme.c:1089
#define ast_channel_lock(chan)
Definition: channel.h:2837
char * str
Subscriber phone number (Malloced)
Definition: channel.h:292
char * filename_read
struct ast_party_id id
Connected party ID.
Definition: channel.h:459
ast_callid callid
#define ast_test_flag(p, flag)
Definition: utils.h:63
struct ast_party_name name
Subscriber name.
Definition: channel.h:341
static void add_vm_recipients_from_string(struct mixmonitor *mixmonitor, const char *vm_recipients)
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
static int startmon(struct ast_channel *chan, struct ast_audiohook *audiohook)
char * str
Subscriber name (Malloced)
Definition: channel.h:265
char * post_process
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
#define NULL
Definition: resample.c:96
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:133
int ast_channel_priority(const struct ast_channel *chan)
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:512
ast_callid ast_read_threadstorage_callid(void)
extracts the callerid from the thread
Definition: logger.c:1870
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
Definition: audiohook.c:108
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static void mixmonitor_free(struct mixmonitor *mixmonitor)
char * ast_callerid_merge(char *buf, int bufsiz, const char *name, const char *num, const char *unknown)
Definition: callerid.c:1073
static const char *const mixmonitor_spy_type
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:353
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:85
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
const char * ast_channel_exten(const struct ast_channel *chan)
char * filename_write
Connected Line/Party information.
Definition: channel.h:457
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char * filename
void ast_autochan_destroy(struct ast_autochan *autochan)
destroy an ast_autochan structure
Definition: autochan.c:64
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
struct ast_autochan * ast_autochan_setup(struct ast_channel *chan)
set up a new ast_autochan structure
Definition: autochan.c:38
struct ast_audiohook_options options
Definition: audiohook.h:118
static void * mixmonitor_thread(void *obj)
unsigned int flags
const char * ast_channel_name(const struct ast_channel *chan)
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id, const char *beep_id)
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
const char * ast_channel_context(const struct ast_channel *chan)
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:280
const char * ast_channel_macrocontext(const struct ast_channel *chan)
struct ast_audiohook audiohook
char connected
Definition: eagi_proxy.c:82
struct ast_autochan * autochan
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:298
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:343

◆ load_module()

static int load_module ( void  )
static

Definition at line 1586 of file app_mixmonitor.c.

References app, ARRAY_LEN, ast_cli_register_multiple, ast_custom_function_register, ast_manager_register_xml, AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_register_application_xml, ASTERISK_GPL_KEY, EVENT_FLAG_CALL, EVENT_FLAG_SYSTEM, manager_mixmonitor(), manager_mute_mixmonitor(), manager_stop_mixmonitor(), mixmonitor_exec(), set_mixmonitor_methods(), stop_app, stop_mixmonitor_exec(), and unload_module().

1587 {
1588  int res;
1589 
1597  res |= set_mixmonitor_methods();
1598 
1599  return res;
1600 }
static int set_mixmonitor_methods(void)
static int stop_mixmonitor_exec(struct ast_channel *chan, const char *data)
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static int manager_stop_mixmonitor(struct mansession *s, const struct message *m)
#define EVENT_FLAG_CALL
Definition: manager.h:72
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static int manager_mute_mixmonitor(struct mansession *s, const struct message *m)
Mute / unmute a MixMonitor channel.
static int mixmonitor_exec(struct ast_channel *chan, const char *data)
#define EVENT_FLAG_SYSTEM
Definition: manager.h:71
static const char *const stop_app
static const char *const app
static int manager_mixmonitor(struct mansession *s, const struct message *m)
static struct ast_custom_function mixmonitor_function
static struct ast_cli_entry cli_mixmonitor[]
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1504
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ manager_mixmonitor()

static int manager_mixmonitor ( struct mansession s,
const struct message m 
)
static

Definition at line 1404 of file app_mixmonitor.c.

References AMI_SUCCESS, args, ast_app_parse_options(), ast_channel_get_by_name(), ast_channel_lock, ast_channel_unlock, ast_channel_unref, ast_strdupa, ast_strlen_zero, ast_test_flag, astman_append(), astman_get_header(), astman_send_error(), c, make_ari_stubs::file, mixmonitor_exec(), mixmonitor_opts, MUXFLAG_UID, NULL, OPT_ARG_ARRAY_SIZE, OPT_ARG_UID, options, PATH_MAX, pbx_builtin_getvar_helper(), and S_OR.

Referenced by load_module().

1405 {
1406  struct ast_channel *c;
1407  const char *name = astman_get_header(m, "Channel");
1408  const char *id = astman_get_header(m, "ActionID");
1409  const char *file = astman_get_header(m, "File");
1410  const char *options = astman_get_header(m, "Options");
1411  const char *command = astman_get_header(m, "Command");
1412  char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
1413  struct ast_flags flags = { 0 };
1414  char *uid_channel_var = NULL;
1415  const char *mixmonitor_id = NULL;
1416  int res;
1417  char args[PATH_MAX];
1418 
1419  if (ast_strlen_zero(name)) {
1420  astman_send_error(s, m, "No channel specified");
1421  return AMI_SUCCESS;
1422  }
1423 
1424  c = ast_channel_get_by_name(name);
1425  if (!c) {
1426  astman_send_error(s, m, "No such channel");
1427  return AMI_SUCCESS;
1428  }
1429 
1430  if (!ast_strlen_zero(options)) {
1431  ast_app_parse_options(mixmonitor_opts, &flags, opts, ast_strdupa(options));
1432  }
1433 
1434  snprintf(args, sizeof(args), "%s,%s,%s", file, options, command);
1435 
1436  res = mixmonitor_exec(c, args);
1437 
1438  if (ast_test_flag(&flags, MUXFLAG_UID)) {
1439  uid_channel_var = opts[OPT_ARG_UID];
1440  ast_channel_lock(c);
1441  mixmonitor_id = pbx_builtin_getvar_helper(c, uid_channel_var);
1442  mixmonitor_id = ast_strdupa(S_OR(mixmonitor_id, ""));
1443  ast_channel_unlock(c);
1444  }
1445 
1446  if (res) {
1447  ast_channel_unref(c);
1448  astman_send_error(s, m, "Could not start monitoring channel");
1449  return AMI_SUCCESS;
1450  }
1451 
1452  astman_append(s, "Response: Success\r\n");
1453 
1454  if (!ast_strlen_zero(id)) {
1455  astman_append(s, "ActionID: %s\r\n", id);
1456  }
1457 
1458  if (!ast_strlen_zero(mixmonitor_id)) {
1459  astman_append(s, "MixMonitorID: %s\r\n", mixmonitor_id);
1460  }
1461 
1462  astman_append(s, "\r\n");
1463 
1464  ast_channel_unref(c);
1465 
1466  return AMI_SUCCESS;
1467 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
Main Channel structure associated with a channel.
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
#define ast_test_flag(p, flag)
Definition: utils.h:63
unsigned int flags
Definition: utils.h:200
static struct test_val c
const char * args
#define NULL
Definition: resample.c:96
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
static int mixmonitor_exec(struct ast_channel *chan, const char *data)
static const struct ast_app_option mixmonitor_opts[128]
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2829
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
static const char name[]
Definition: cdr_mysql.c:74
Structure used to handle boolean flags.
Definition: utils.h:199
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
#define PATH_MAX
Definition: asterisk.h:40
static struct test_options options
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1439
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define AMI_SUCCESS
Definition: manager.h:65

◆ manager_mute_mixmonitor()

static int manager_mute_mixmonitor ( struct mansession s,
const struct message m 
)
static

Mute / unmute a MixMonitor channel.

Definition at line 1323 of file app_mixmonitor.c.

References AMI_SUCCESS, AST_AUDIOHOOK_MUTE_READ, AST_AUDIOHOOK_MUTE_WRITE, ast_audiohook_set_mute(), ast_channel_get_by_name(), ast_channel_unref, ast_false(), ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), c, and mixmonitor_spy_type.

Referenced by load_module().

1324 {
1325  struct ast_channel *c;
1326  const char *name = astman_get_header(m, "Channel");
1327  const char *id = astman_get_header(m, "ActionID");
1328  const char *state = astman_get_header(m, "State");
1329  const char *direction = astman_get_header(m,"Direction");
1330  int clearmute = 1;
1332 
1333  if (ast_strlen_zero(direction)) {
1334  astman_send_error(s, m, "No direction specified. Must be read, write or both");
1335  return AMI_SUCCESS;
1336  }
1337 
1338  if (!strcasecmp(direction, "read")) {
1339  flag = AST_AUDIOHOOK_MUTE_READ;
1340  } else if (!strcasecmp(direction, "write")) {
1341  flag = AST_AUDIOHOOK_MUTE_WRITE;
1342  } else if (!strcasecmp(direction, "both")) {
1344  } else {
1345  astman_send_error(s, m, "Invalid direction specified. Must be read, write or both");
1346  return AMI_SUCCESS;
1347  }
1348 
1349  if (ast_strlen_zero(name)) {
1350  astman_send_error(s, m, "No channel specified");
1351  return AMI_SUCCESS;
1352  }
1353 
1354  if (ast_strlen_zero(state)) {
1355  astman_send_error(s, m, "No state specified");
1356  return AMI_SUCCESS;
1357  }
1358 
1359  clearmute = ast_false(state);
1360 
1361  c = ast_channel_get_by_name(name);
1362  if (!c) {
1363  astman_send_error(s, m, "No such channel");
1364  return AMI_SUCCESS;
1365  }
1366 
1367  if (ast_audiohook_set_mute(c, mixmonitor_spy_type, flag, clearmute)) {
1368  ast_channel_unref(c);
1369  astman_send_error(s, m, "Cannot set mute flag");
1370  return AMI_SUCCESS;
1371  }
1372 
1373  astman_append(s, "Response: Success\r\n");
1374 
1375  if (!ast_strlen_zero(id)) {
1376  astman_append(s, "ActionID: %s\r\n", id);
1377  }
1378 
1379  astman_append(s, "\r\n");
1380 
1381  ast_channel_unref(c);
1382 
1383  return AMI_SUCCESS;
1384 }
Main Channel structure associated with a channel.
ast_audiohook_flags
Definition: audiohook.h:54
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
int ast_audiohook_set_mute(struct ast_channel *chan, const char *source, enum ast_audiohook_flags flag, int clear)
Mute frames read from or written to a channel.
Definition: audiohook.c:1424
static struct test_val c
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
static const char *const mixmonitor_spy_type
long int flag
Definition: f2c.h:83
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1839
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1439
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define AMI_SUCCESS
Definition: manager.h:65

◆ manager_stop_mixmonitor()

static int manager_stop_mixmonitor ( struct mansession s,
const struct message m 
)
static

Definition at line 1469 of file app_mixmonitor.c.

References AMI_SUCCESS, ast_channel_get_by_name(), ast_channel_unref, ast_strlen_zero, astman_append(), astman_get_header(), astman_send_error(), c, and stop_mixmonitor_full().

Referenced by load_module().

1470 {
1471  struct ast_channel *c;
1472  const char *name = astman_get_header(m, "Channel");
1473  const char *id = astman_get_header(m, "ActionID");
1474  const char *mixmonitor_id = astman_get_header(m, "MixMonitorID");
1475  int res;
1476 
1477  if (ast_strlen_zero(name)) {
1478  astman_send_error(s, m, "No channel specified");
1479  return AMI_SUCCESS;
1480  }
1481 
1482  c = ast_channel_get_by_name(name);
1483  if (!c) {
1484  astman_send_error(s, m, "No such channel");
1485  return AMI_SUCCESS;
1486  }
1487 
1488  res = stop_mixmonitor_full(c, mixmonitor_id);
1489  if (res) {
1490  ast_channel_unref(c);
1491  astman_send_error(s, m, "Could not stop monitoring channel");
1492  return AMI_SUCCESS;
1493  }
1494 
1495  astman_append(s, "Response: Success\r\n");
1496 
1497  if (!ast_strlen_zero(id)) {
1498  astman_append(s, "ActionID: %s\r\n", id);
1499  }
1500 
1501  astman_append(s, "\r\n");
1502 
1503  ast_channel_unref(c);
1504 
1505  return AMI_SUCCESS;
1506 }
Main Channel structure associated with a channel.
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:3080
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2873
static struct test_val c
static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(a)
Definition: muted.c:73
static const char name[]
Definition: cdr_mysql.c:74
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1439
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
#define AMI_SUCCESS
Definition: manager.h:65

◆ mixmonitor_autochan_is_bridged()

static int mixmonitor_autochan_is_bridged ( struct ast_autochan autochan)
static

Definition at line 652 of file app_mixmonitor.c.

References ast_autochan_channel_lock, ast_autochan_channel_unlock, ast_channel_is_bridged(), and ast_autochan::chan.

Referenced by mixmonitor_thread().

653 {
654  int is_bridged;
655 
656  ast_autochan_channel_lock(autochan);
657  is_bridged = ast_channel_is_bridged(autochan->chan);
658  ast_autochan_channel_unlock(autochan);
659  return is_bridged;
660 }
#define ast_autochan_channel_lock(autochan)
Lock the autochan&#39;s channel lock.
Definition: autochan.h:75
struct ast_channel * chan
Definition: autochan.h:33
int ast_channel_is_bridged(const struct ast_channel *chan)
Determine if a channel is in a bridge.
Definition: channel.c:10579
#define ast_autochan_channel_unlock(autochan)
Definition: autochan.h:84

◆ mixmonitor_ds_close_fs()

static void mixmonitor_ds_close_fs ( struct mixmonitor_ds mixmonitor_ds)
static

Definition at line 420 of file app_mixmonitor.c.

References ast_closestream(), ast_verb, mixmonitor_ds::fs, mixmonitor_ds::fs_quit, mixmonitor_ds::fs_read, mixmonitor_ds::fs_write, and NULL.

Referenced by mixmonitor_thread(), and stop_mixmonitor_full().

421 {
422  unsigned char quitting = 0;
423 
424  if (mixmonitor_ds->fs) {
425  quitting = 1;
426  ast_closestream(mixmonitor_ds->fs);
427  mixmonitor_ds->fs = NULL;
428  ast_verb(2, "MixMonitor close filestream (mixed)\n");
429  }
430 
431  if (mixmonitor_ds->fs_read) {
432  quitting = 1;
433  ast_closestream(mixmonitor_ds->fs_read);
434  mixmonitor_ds->fs_read = NULL;
435  ast_verb(2, "MixMonitor close filestream (read)\n");
436  }
437 
438  if (mixmonitor_ds->fs_write) {
439  quitting = 1;
440  ast_closestream(mixmonitor_ds->fs_write);
441  mixmonitor_ds->fs_write = NULL;
442  ast_verb(2, "MixMonitor close filestream (write)\n");
443  }
444 
445  if (quitting) {
446  mixmonitor_ds->fs_quit = 1;
447  }
448 }
struct ast_filestream * fs_read
struct ast_filestream * fs
#define NULL
Definition: resample.c:96
#define ast_verb(level,...)
Definition: logger.h:455
struct ast_filestream * fs_write
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1068

◆ mixmonitor_ds_destroy()

static void mixmonitor_ds_destroy ( void *  data)
static

Definition at line 450 of file app_mixmonitor.c.

References ast_cond_signal, ast_free, ast_mutex_lock, ast_mutex_unlock, mixmonitor_ds::audiohook, mixmonitor_ds::beep_id, mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, mixmonitor_ds::filename, mixmonitor_ds::lock, and NULL.

451 {
452  struct mixmonitor_ds *mixmonitor_ds = data;
453 
454  ast_mutex_lock(&mixmonitor_ds->lock);
455  mixmonitor_ds->audiohook = NULL;
456  mixmonitor_ds->destruction_ok = 1;
457  ast_free(mixmonitor_ds->filename);
458  ast_free(mixmonitor_ds->beep_id);
459  ast_cond_signal(&mixmonitor_ds->destruction_condition);
460  ast_mutex_unlock(&mixmonitor_ds->lock);
461 }
unsigned int destruction_ok
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
#define ast_cond_signal(cond)
Definition: lock.h:201
ast_cond_t destruction_condition
ast_mutex_t lock
#define ast_free(a)
Definition: astmm.h:182
struct ast_audiohook * audiohook
#define ast_mutex_unlock(a)
Definition: lock.h:188

◆ mixmonitor_exec()

static int mixmonitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1047 of file app_mixmonitor.c.

References args, AST_APP_ARG, ast_app_parse_options(), ast_beep_start(), AST_DECLARE_APP_ARGS, ast_log, ast_module_ref, ast_module_unref, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_test_flag, filename_parse(), ast_flags::flags, get_volfactor, launch_monitor_thread(), LOG_NOTICE, LOG_WARNING, mixmonitor_opts, MUXFLAG_BEEP, MUXFLAG_DEPRECATED_RWSYNC, MUXFLAG_READ, MUXFLAG_READVOLUME, MUXFLAG_UID, MUXFLAG_VMRECIPIENTS, MUXFLAG_VOLUME, MUXFLAG_WRITE, MUXFLAG_WRITEVOLUME, NULL, OPT_ARG_ARRAY_SIZE, OPT_ARG_BEEP_INTERVAL, OPT_ARG_READNAME, OPT_ARG_READVOLUME, OPT_ARG_UID, OPT_ARG_VMRECIPIENTS, OPT_ARG_VOLUME, OPT_ARG_WRITENAME, OPT_ARG_WRITEVOLUME, options, parse(), pbx_builtin_setvar_helper(), S_OR, and ast_module_info::self.

Referenced by handle_cli_mixmonitor(), load_module(), manager_mixmonitor(), and start_mixmonitor_callback().

1048 {
1049  int x, readvol = 0, writevol = 0;
1050  char *filename_read = NULL;
1051  char *filename_write = NULL;
1052  char filename_buffer[1024] = "";
1053  char *uid_channel_var = NULL;
1054  char beep_id[64] = "";
1055 
1056  struct ast_flags flags = { 0 };
1057  char *recipients = NULL;
1058  char *parse;
1060  AST_APP_ARG(filename);
1062  AST_APP_ARG(post_process);
1063  );
1064 
1065  if (ast_strlen_zero(data)) {
1066  ast_log(LOG_WARNING, "MixMonitor requires an argument (filename or ,t(filename) and/or r(filename)\n");
1067  return -1;
1068  }
1069 
1070  parse = ast_strdupa(data);
1071 
1072  AST_STANDARD_APP_ARGS(args, parse);
1073 
1074  if (args.options) {
1075  char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
1076 
1077  ast_app_parse_options(mixmonitor_opts, &flags, opts, args.options);
1078 
1080  ast_log(LOG_NOTICE, "The synchronization behavior enabled by the 'S' option is now the default"
1081  " and does not need to be specified.\n");
1082  }
1083 
1084  if (ast_test_flag(&flags, MUXFLAG_READVOLUME)) {
1085  if (ast_strlen_zero(opts[OPT_ARG_READVOLUME])) {
1086  ast_log(LOG_WARNING, "No volume level was provided for the heard volume ('v') option.\n");
1087  } else if ((sscanf(opts[OPT_ARG_READVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
1088  ast_log(LOG_NOTICE, "Heard volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_READVOLUME]);
1089  } else {
1090  readvol = get_volfactor(x);
1091  }
1092  }
1093 
1094  if (ast_test_flag(&flags, MUXFLAG_WRITEVOLUME)) {
1095  if (ast_strlen_zero(opts[OPT_ARG_WRITEVOLUME])) {
1096  ast_log(LOG_WARNING, "No volume level was provided for the spoken volume ('V') option.\n");
1097  } else if ((sscanf(opts[OPT_ARG_WRITEVOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
1098  ast_log(LOG_NOTICE, "Spoken volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_WRITEVOLUME]);
1099  } else {
1100  writevol = get_volfactor(x);
1101  }
1102  }
1103 
1104  if (ast_test_flag(&flags, MUXFLAG_VOLUME)) {
1105  if (ast_strlen_zero(opts[OPT_ARG_VOLUME])) {
1106  ast_log(LOG_WARNING, "No volume level was provided for the combined volume ('W') option.\n");
1107  } else if ((sscanf(opts[OPT_ARG_VOLUME], "%2d", &x) != 1) || (x < -4) || (x > 4)) {
1108  ast_log(LOG_NOTICE, "Combined volume must be a number between -4 and 4, not '%s'\n", opts[OPT_ARG_VOLUME]);
1109  } else {
1110  readvol = writevol = get_volfactor(x);
1111  }
1112  }
1113 
1114  if (ast_test_flag(&flags, MUXFLAG_VMRECIPIENTS)) {
1116  ast_log(LOG_WARNING, "No voicemail recipients were specified for the vm copy ('m') option.\n");
1117  } else {
1118  recipients = ast_strdupa(opts[OPT_ARG_VMRECIPIENTS]);
1119  }
1120  }
1121 
1122  if (ast_test_flag(&flags, MUXFLAG_WRITE)) {
1123  filename_write = ast_strdupa(filename_parse(opts[OPT_ARG_WRITENAME], filename_buffer, sizeof(filename_buffer)));
1124  }
1125 
1126  if (ast_test_flag(&flags, MUXFLAG_READ)) {
1127  filename_read = ast_strdupa(filename_parse(opts[OPT_ARG_READNAME], filename_buffer, sizeof(filename_buffer)));
1128  }
1129 
1130  if (ast_test_flag(&flags, MUXFLAG_UID)) {
1131  uid_channel_var = opts[OPT_ARG_UID];
1132  }
1133 
1134  if (ast_test_flag(&flags, MUXFLAG_BEEP)) {
1135  const char *interval_str = S_OR(opts[OPT_ARG_BEEP_INTERVAL], "15");
1136  unsigned int interval = 15;
1137 
1138  if (sscanf(interval_str, "%30u", &interval) != 1) {
1139  ast_log(LOG_WARNING, "Invalid interval '%s' for periodic beep. Using default of %u\n",
1140  interval_str, interval);
1141  }
1142 
1143  if (ast_beep_start(chan, interval, beep_id, sizeof(beep_id))) {
1144  ast_log(LOG_WARNING, "Unable to enable periodic beep, please ensure func_periodic_hook is loaded.\n");
1145  return -1;
1146  }
1147  }
1148  }
1149  /* If there are no file writing arguments/options for the mix monitor, send a warning message and return -1 */
1150 
1151  if (!ast_test_flag(&flags, MUXFLAG_WRITE) && !ast_test_flag(&flags, MUXFLAG_READ) && ast_strlen_zero(args.filename)) {
1152  ast_log(LOG_WARNING, "MixMonitor requires an argument (filename)\n");
1153  return -1;
1154  }
1155 
1156  /* If filename exists, try to create directories for it */
1157  if (!(ast_strlen_zero(args.filename))) {
1158  args.filename = ast_strdupa(filename_parse(args.filename, filename_buffer, sizeof(filename_buffer)));
1159  }
1160 
1161  pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
1162 
1163  /* If launch_monitor_thread works, the module reference must not be released until it is finished. */
1165  if (launch_monitor_thread(chan,
1166  args.filename,
1167  flags.flags,
1168  readvol,
1169  writevol,
1170  args.post_process,
1171  filename_write,
1172  filename_read,
1173  uid_channel_var,
1174  recipients,
1175  beep_id)) {
1177  }
1178 
1179  return 0;
1180 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
static char * filename_parse(char *filename, char *buffer, size_t len)
unsigned int flags
Definition: utils.h:200
static int launch_monitor_thread(struct ast_channel *chan, const char *filename, unsigned int flags, int readvol, int writevol, const char *post_process, const char *filename_write, char *filename_read, const char *uid_channel_var, const char *recipients, const char *beep_id)
const char * args
#define NULL
Definition: resample.c:96
static const struct ast_app_option mixmonitor_opts[128]
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
#define get_volfactor(x)
#define ast_log
Definition: astobj2.c:42
struct ast_module * self
Definition: module.h:342
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2829
int AST_OPTIONAL_API_NAME() ast_beep_start(struct ast_channel *chan, unsigned int interval, char *beep_id, size_t len)
#define LOG_NOTICE
Definition: logger.h:263
#define ast_strlen_zero(a)
Definition: muted.c:73
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
Structure used to handle boolean flags.
Definition: utils.h:199
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443

◆ mixmonitor_free()

static void mixmonitor_free ( struct mixmonitor mixmonitor)
static

Definition at line 557 of file app_mixmonitor.c.

References ast_cond_destroy, ast_free, ast_mutex_destroy, ast_string_field_free_memory, clear_mixmonitor_recipient_list(), mixmonitor_ds::destruction_condition, mixmonitor::filename, mixmonitor::filename_read, mixmonitor::filename_write, mixmonitor_ds::lock, mixmonitor::mixmonitor_ds, mixmonitor::name, and mixmonitor::post_process.

Referenced by launch_monitor_thread(), and mixmonitor_thread().

558 {
559  if (mixmonitor) {
560  if (mixmonitor->mixmonitor_ds) {
561  ast_mutex_destroy(&mixmonitor->mixmonitor_ds->lock);
563  ast_free(mixmonitor->mixmonitor_ds);
564  }
565 
566  ast_free(mixmonitor->name);
567  ast_free(mixmonitor->post_process);
568  ast_free(mixmonitor->filename);
569  ast_free(mixmonitor->filename_write);
570  ast_free(mixmonitor->filename_read);
571 
572  /* Free everything in the recipient list */
574 
575  /* clean stringfields */
576  ast_string_field_free_memory(mixmonitor);
577 
578  ast_free(mixmonitor);
579  }
580 }
char * filename_read
char * post_process
struct mixmonitor_ds * mixmonitor_ds
ast_cond_t destruction_condition
char * filename_write
#define ast_cond_destroy(cond)
Definition: lock.h:200
ast_mutex_t lock
#define ast_free(a)
Definition: astmm.h:182
char * filename
static void clear_mixmonitor_recipient_list(struct mixmonitor *mixmonitor)
#define ast_mutex_destroy(a)
Definition: lock.h:186
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:368

◆ mixmonitor_save_prep()

static void mixmonitor_save_prep ( struct mixmonitor mixmonitor,
char *  filename,
struct ast_filestream **  fs,
unsigned int *  oflags,
int *  errflag,
char **  ext 
)
static

Definition at line 623 of file app_mixmonitor.c.

References ast_format_get_sample_rate(), ast_log, ast_strlen_zero, ast_test_flag, ast_writefile(), ast_filestream::fmt, ast_format_def::format, mixmonitor_ds::fs_quit, LOG_ERROR, MAX, mixmonitor::mixmonitor_ds, MUXFLAG_APPEND, NULL, mixmonitor_ds::samp_rate, and tmp().

Referenced by mixmonitor_thread().

624 {
625  /* Initialize the file if not already done so */
626  char *last_slash = NULL;
627  if (!ast_strlen_zero(filename)) {
628  if (!*fs && !*errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
629  *oflags = O_CREAT | O_WRONLY;
630  *oflags |= ast_test_flag(mixmonitor, MUXFLAG_APPEND) ? O_APPEND : O_TRUNC;
631 
632  last_slash = strrchr(filename, '/');
633 
634  if ((*ext = strrchr(filename, '.')) && (*ext > last_slash)) {
635  **ext = '\0';
636  *ext = *ext + 1;
637  } else {
638  *ext = "raw";
639  }
640 
641  if (!(*fs = ast_writefile(filename, *ext, NULL, *oflags, 0, 0666))) {
642  ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, *ext);
643  *errflag = 1;
644  } else {
645  struct ast_filestream *tmp = *fs;
647  }
648  }
649  }
650 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
static int tmp()
Definition: bt_open.c:389
struct mixmonitor_ds * mixmonitor_ds
#define NULL
Definition: resample.c:96
unsigned int samp_rate
const char * ext
Definition: http.c:147
#define ast_log
Definition: astobj2.c:42
#define MAX(a, b)
Definition: utils.h:228
struct ast_format_def * fmt
Definition: mod_format.h:103
struct ast_format * format
Definition: mod_format.h:48
#define LOG_ERROR
Definition: logger.h:285
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1361
#define ast_strlen_zero(a)
Definition: muted.c:73
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379

◆ mixmonitor_thread()

static void* mixmonitor_thread ( void *  obj)
static

Definition at line 662 of file app_mixmonitor.c.

References ast_audiohook_lock, ast_audiohook_read_frame_all(), AST_AUDIOHOOK_STATUS_RUNNING, ast_audiohook_trigger_wait(), ast_audiohook_unlock, ast_autochan_channel_lock, ast_autochan_channel_unlock, ast_autochan_destroy(), ast_callid_threadassoc_add(), ast_cond_wait, ast_debug, ast_format_cache_get_slin_by_rate(), ast_frame_free(), AST_LIST_EMPTY, AST_LIST_NEXT, ast_log, ast_module_unref, ast_mutex_lock, ast_mutex_unlock, ast_safe_system(), ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, ast_test_suite_event_notify, ast_verb, ast_writestream(), mixmonitor::audiohook, mixmonitor::autochan, mixmonitor::callid, ast_autochan::chan, copy_to_voicemail(), destroy_monitor_audiohook(), mixmonitor_ds::destruction_condition, mixmonitor_ds::destruction_ok, mixmonitor::filename, mixmonitor::filename_read, mixmonitor::filename_write, mixmonitor_ds::fs, mixmonitor_ds::fs_quit, mixmonitor_ds::fs_read, mixmonitor_ds::fs_write, mixmonitor_ds::lock, LOG_ERROR, mixmonitor_autochan_is_bridged(), mixmonitor::mixmonitor_ds, mixmonitor_ds_close_fs(), mixmonitor_free(), mixmonitor_save_prep(), MUXFLAG_BEEP_STOP, MUXFLAG_BRIDGED, mixmonitor::name, NULL, mixmonitor::post_process, mixmonitor::recipient_list, mixmonitor_ds::samp_rate, SAMPLES_PER_FRAME, ast_module_info::self, and ast_audiohook::status.

Referenced by launch_monitor_thread().

663 {
664  struct mixmonitor *mixmonitor = obj;
665  char *fs_ext = "";
666  char *fs_read_ext = "";
667  char *fs_write_ext = "";
668 
669  struct ast_filestream **fs = NULL;
670  struct ast_filestream **fs_read = NULL;
671  struct ast_filestream **fs_write = NULL;
672 
673  unsigned int oflags;
674  int errflag = 0;
675  struct ast_format *format_slin;
676 
677  /* Keep callid association before any log messages */
678  if (mixmonitor->callid) {
679  ast_callid_threadassoc_add(mixmonitor->callid);
680  }
681 
682  ast_verb(2, "Begin MixMonitor Recording %s\n", mixmonitor->name);
683 
684  fs = &mixmonitor->mixmonitor_ds->fs;
685  fs_read = &mixmonitor->mixmonitor_ds->fs_read;
686  fs_write = &mixmonitor->mixmonitor_ds->fs_write;
687 
688  ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
689  mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag, &fs_ext);
690  mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag, &fs_read_ext);
691  mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag, &fs_write_ext);
692 
693  format_slin = ast_format_cache_get_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate);
694 
695  ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
696 
697  /* The audiohook must enter and exit the loop locked */
698  ast_audiohook_lock(&mixmonitor->audiohook);
699  while (mixmonitor->audiohook.status == AST_AUDIOHOOK_STATUS_RUNNING && !mixmonitor->mixmonitor_ds->fs_quit) {
700  struct ast_frame *fr = NULL;
701  struct ast_frame *fr_read = NULL;
702  struct ast_frame *fr_write = NULL;
703 
704  if (!(fr = ast_audiohook_read_frame_all(&mixmonitor->audiohook, SAMPLES_PER_FRAME, format_slin,
705  &fr_read, &fr_write))) {
707 
708  if (mixmonitor->audiohook.status != AST_AUDIOHOOK_STATUS_RUNNING) {
709  break;
710  }
711  continue;
712  }
713 
714  /* audiohook lock is not required for the next block.
715  * Unlock it, but remember to lock it before looping or exiting */
716  ast_audiohook_unlock(&mixmonitor->audiohook);
717 
718  if (!ast_test_flag(mixmonitor, MUXFLAG_BRIDGED)
719  || mixmonitor_autochan_is_bridged(mixmonitor->autochan)) {
720  ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
721 
722  /* Write out the frame(s) */
723  if ((*fs_read) && (fr_read)) {
724  struct ast_frame *cur;
725 
726  for (cur = fr_read; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
727  ast_writestream(*fs_read, cur);
728  }
729  }
730 
731  if ((*fs_write) && (fr_write)) {
732  struct ast_frame *cur;
733 
734  for (cur = fr_write; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
735  ast_writestream(*fs_write, cur);
736  }
737  }
738 
739  if ((*fs) && (fr)) {
740  struct ast_frame *cur;
741 
742  for (cur = fr; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
743  ast_writestream(*fs, cur);
744  }
745  }
746  ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
747  }
748  /* All done! free it. */
749  if (fr) {
750  ast_frame_free(fr, 0);
751  }
752  if (fr_read) {
753  ast_frame_free(fr_read, 0);
754  }
755  if (fr_write) {
756  ast_frame_free(fr_write, 0);
757  }
758 
759  fr = NULL;
760  fr_write = NULL;
761  fr_read = NULL;
762 
763  ast_audiohook_lock(&mixmonitor->audiohook);
764  }
765 
766  ast_audiohook_unlock(&mixmonitor->audiohook);
767 
768  if (ast_test_flag(mixmonitor, MUXFLAG_BEEP_STOP)) {
769  ast_autochan_channel_lock(mixmonitor->autochan);
770  ast_stream_and_wait(mixmonitor->autochan->chan, "beep", "");
772  }
773 
774  ast_autochan_destroy(mixmonitor->autochan);
775 
776  /* Datastore cleanup. close the filestream and wait for ds destruction */
777  ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
779  if (!mixmonitor->mixmonitor_ds->destruction_ok) {
781  }
782  ast_mutex_unlock(&mixmonitor->mixmonitor_ds->lock);
783 
784  /* kill the audiohook */
785  destroy_monitor_audiohook(mixmonitor);
786 
787  if (mixmonitor->post_process) {
788  ast_verb(2, "Executing [%s]\n", mixmonitor->post_process);
789  ast_safe_system(mixmonitor->post_process);
790  }
791 
792  ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
793  ast_test_suite_event_notify("MIXMONITOR_END", "File: %s\r\n", mixmonitor->filename);
794 
795  if (!AST_LIST_EMPTY(&mixmonitor->recipient_list)) {
796  if (ast_strlen_zero(fs_ext)) {
797  ast_log(LOG_ERROR, "No file extension set for Mixmonitor %s. Skipping copy to voicemail.\n",
798  mixmonitor -> name);
799  } else {
800  ast_verb(3, "Copying recordings for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
801  copy_to_voicemail(mixmonitor, fs_ext, mixmonitor->filename);
802  }
803  if (!ast_strlen_zero(fs_read_ext)) {
804  ast_verb(3, "Copying read recording for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
805  copy_to_voicemail(mixmonitor, fs_read_ext, mixmonitor->filename_read);
806  }
807  if (!ast_strlen_zero(fs_write_ext)) {
808  ast_verb(3, "Copying write recording for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
809  copy_to_voicemail(mixmonitor, fs_write_ext, mixmonitor->filename_write);
810  }
811  } else {
812  ast_debug(3, "No recipients to forward monitor to, moving on.\n");
813  }
814 
815  mixmonitor_free(mixmonitor);
816 
818  return NULL;
819 }
struct ast_filestream * fs_read
char * filename_read
#define ast_autochan_channel_lock(autochan)
Lock the autochan&#39;s channel lock.
Definition: autochan.h:75
static void destroy_monitor_audiohook(struct mixmonitor *mixmonitor)
ast_callid callid
struct ast_filestream * fs
#define ast_test_flag(p, flag)
Definition: utils.h:63
unsigned int destruction_ok
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
Definition of a media format.
Definition: format.c:43
#define ast_cond_wait(cond, mutex)
Definition: lock.h:203
struct ast_channel * chan
Definition: autochan.h:33
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
char * post_process
#define ast_mutex_lock(a)
Definition: lock.h:187
struct mixmonitor_ds * mixmonitor_ds
void ast_frame_free(struct ast_frame *fr, int cache)
Requests a frame to be allocated.
Definition: main/frame.c:172
#define NULL
Definition: resample.c:96
unsigned int samp_rate
#define ast_verb(level,...)
Definition: logger.h:455
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
ast_cond_t destruction_condition
int ast_callid_threadassoc_add(ast_callid callid)
Adds a known callid to thread storage of the calling thread.
Definition: logger.c:1892
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:444
#define ast_log
Definition: astobj2.c:42
static void mixmonitor_free(struct mixmonitor *mixmonitor)
struct ast_module * self
Definition: module.h:342
static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag, char **ext)
char * filename_write
#define ast_test_suite_event_notify(s, f,...)
Definition: test.h:196
#define LOG_ERROR
Definition: logger.h:285
static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds)
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: extconf.c:829
struct ast_filestream * fs_write
static void copy_to_voicemail(struct mixmonitor *mixmonitor, const char *ext, const char *filename)
#define ast_strlen_zero(a)
Definition: muted.c:73
ast_mutex_t lock
static const char name[]
Definition: cdr_mysql.c:74
char * filename
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1813
#define SAMPLES_PER_FRAME
void ast_autochan_destroy(struct ast_autochan *autochan)
destroy an ast_autochan structure
Definition: autochan.c:64
struct ast_frame * ast_audiohook_read_frame_all(struct ast_audiohook *audiohook, size_t samples, struct ast_format *format, struct ast_frame **read_frame, struct ast_frame **write_frame)
Reads a frame in from the audiohook structure in mixed audio mode and copies read and write frame dat...
Definition: audiohook.c:463
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:209
Data structure associated with a single frame of data.
enum ast_audiohook_status status
Definition: audiohook.h:107
#define ast_autochan_channel_unlock(autochan)
Definition: autochan.h:84
static int mixmonitor_autochan_is_bridged(struct ast_autochan *autochan)
struct ast_audiohook audiohook
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295
struct ast_autochan * autochan
void ast_audiohook_trigger_wait(struct ast_audiohook *audiohook)
Wait for audiohook trigger to be triggered.
Definition: audiohook.c:1142
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:520
#define ast_mutex_unlock(a)
Definition: lock.h:188
struct mixmonitor::@58 recipient_list

◆ set_mixmonitor_methods()

static int set_mixmonitor_methods ( void  )
static

Definition at line 1555 of file app_mixmonitor.c.

References ast_set_mixmonitor_methods(), ast_mixmonitor_methods::start, start_mixmonitor_callback(), and stop_mixmonitor_callback().

Referenced by load_module().

1556 {
1559  .stop = stop_mixmonitor_callback,
1560  };
1561 
1562  return ast_set_mixmonitor_methods(&mixmonitor_methods);
1563 }
int ast_set_mixmonitor_methods(struct ast_mixmonitor_methods *vmethod_table)
Setup MixMonitor virtual methods table. Use this to provide the MixMonitor functionality from a loada...
Definition: mixmonitor.c:43
MixMonitor virtual methods table definition.
Definition: mixmonitor.h:58
static int start_mixmonitor_callback(struct ast_channel *chan, const char *filename, const char *options)
static int stop_mixmonitor_callback(struct ast_channel *chan, const char *mixmonitor_id)
static struct ast_mixmonitor_methods mixmonitor_methods
Definition: mixmonitor.c:40
ast_mixmonitor_start_fn start
Definition: mixmonitor.h:59

◆ setup_mixmonitor_ds()

static int setup_mixmonitor_ds ( struct mixmonitor mixmonitor,
struct ast_channel chan,
char **  datastore_id,
const char *  beep_id 
)
static

Definition at line 821 of file app_mixmonitor.c.

References ast_asprintf, ast_autochan_channel_lock, ast_autochan_channel_unlock, ast_calloc, ast_channel_datastore_add(), ast_channel_lock, ast_channel_unlock, ast_cond_destroy, ast_cond_init, ast_datastore_alloc, ast_free, ast_log, ast_mutex_destroy, ast_mutex_init, ast_strdup, ast_stream_and_wait(), ast_strlen_zero, ast_test_flag, mixmonitor::audiohook, mixmonitor_ds::audiohook, mixmonitor::autochan, mixmonitor_ds::beep_id, ast_autochan::chan, ast_datastore::data, mixmonitor_ds::destruction_condition, mixmonitor::filename, mixmonitor_ds::filename, mixmonitor_ds::lock, LOG_ERROR, mixmonitor::mixmonitor_ds, MUXFLAG_BEEP_START, NULL, and mixmonitor_ds::samp_rate.

Referenced by launch_monitor_thread().

822 {
823  struct ast_datastore *datastore = NULL;
825 
826  if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
827  return -1;
828  }
829 
830  if (ast_asprintf(datastore_id, "%p", mixmonitor_ds) == -1) {
831  ast_log(LOG_ERROR, "Failed to allocate memory for MixMonitor ID.\n");
832  ast_free(mixmonitor_ds);
833  return -1;
834  }
835 
836  ast_mutex_init(&mixmonitor_ds->lock);
837  ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);
838 
839  if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, *datastore_id))) {
840  ast_mutex_destroy(&mixmonitor_ds->lock);
841  ast_cond_destroy(&mixmonitor_ds->destruction_condition);
842  ast_free(mixmonitor_ds);
843  return -1;
844  }
845 
846  if (ast_test_flag(mixmonitor, MUXFLAG_BEEP_START)) {
847  ast_autochan_channel_lock(mixmonitor->autochan);
848  ast_stream_and_wait(mixmonitor->autochan->chan, "beep", "");
850  }
851 
852  mixmonitor_ds->samp_rate = 8000;
853  mixmonitor_ds->audiohook = &mixmonitor->audiohook;
854  mixmonitor_ds->filename = ast_strdup(mixmonitor->filename);
855  if (!ast_strlen_zero(beep_id)) {
856  mixmonitor_ds->beep_id = ast_strdup(beep_id);
857  }
858  datastore->data = mixmonitor_ds;
859 
860  ast_channel_lock(chan);
861  ast_channel_datastore_add(chan, datastore);
862  ast_channel_unlock(chan);
863 
864  mixmonitor->mixmonitor_ds = mixmonitor_ds;
865  return 0;
866 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
#define ast_autochan_channel_lock(autochan)
Lock the autochan&#39;s channel lock.
Definition: autochan.h:75
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_cond_init(cond, attr)
Definition: lock.h:199
struct ast_channel * chan
Definition: autochan.h:33
struct mixmonitor_ds * mixmonitor_ds
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:243
Structure for a data store object.
Definition: datastore.h:68
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info mixmonitor_ds_info
unsigned int samp_rate
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:269
ast_cond_t destruction_condition
#define ast_log
Definition: astobj2.c:42
#define LOG_ERROR
Definition: logger.h:285
#define ast_cond_destroy(cond)
Definition: lock.h:200
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
ast_mutex_t lock
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
char * filename
int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
stream file until digit If the file name is non-empty, try to play it.
Definition: file.c:1813
void * data
Definition: datastore.h:70
struct ast_audiohook * audiohook
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
#define ast_autochan_channel_unlock(autochan)
Definition: autochan.h:84
#define ast_mutex_init(pmutex)
Definition: lock.h:184
#define ast_mutex_destroy(a)
Definition: lock.h:186
struct ast_audiohook audiohook
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2365
struct ast_autochan * autochan

◆ start_mixmonitor_callback()

static int start_mixmonitor_callback ( struct ast_channel chan,
const char *  filename,
const char *  options 
)
static

Definition at line 1386 of file app_mixmonitor.c.

References args, ast_strlen_zero, mixmonitor_exec(), and PATH_MAX.

Referenced by set_mixmonitor_methods().

1387 {
1388  char args[PATH_MAX];
1389 
1390  if (ast_strlen_zero(options)) {
1391  snprintf(args, sizeof(args), "%s", filename);
1392  } else {
1393  snprintf(args, sizeof(args), "%s,%s", filename, options);
1394  }
1395 
1396  return mixmonitor_exec(chan, args);
1397 }
const char * args
static int mixmonitor_exec(struct ast_channel *chan, const char *data)
#define ast_strlen_zero(a)
Definition: muted.c:73
#define PATH_MAX
Definition: asterisk.h:40
static struct test_options options

◆ startmon()

static int startmon ( struct ast_channel chan,
struct ast_audiohook audiohook 
)
static

Definition at line 482 of file app_mixmonitor.c.

References ast_audiohook_attach().

Referenced by launch_monitor_thread().

483 {
484  if (!chan) {
485  return -1;
486  }
487 
488  return ast_audiohook_attach(chan, audiohook);
489 }
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:501

◆ stop_mixmonitor_callback()

static int stop_mixmonitor_callback ( struct ast_channel chan,
const char *  mixmonitor_id 
)
static

Definition at line 1399 of file app_mixmonitor.c.

References stop_mixmonitor_full().

Referenced by set_mixmonitor_methods().

1400 {
1401  return stop_mixmonitor_full(chan, mixmonitor_id);
1402 }
static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)

◆ stop_mixmonitor_exec()

static int stop_mixmonitor_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1248 of file app_mixmonitor.c.

References stop_mixmonitor_full().

Referenced by handle_cli_mixmonitor(), and load_module().

1249 {
1250  stop_mixmonitor_full(chan, data);
1251  return 0;
1252 }
static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)

◆ stop_mixmonitor_full()

static int stop_mixmonitor_full ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 1182 of file app_mixmonitor.c.

References args, AST_APP_ARG, ast_audiohook_lock, AST_AUDIOHOOK_STATUS_DONE, AST_AUDIOHOOK_STATUS_SHUTDOWN, ast_audiohook_unlock, ast_audiohook_update_status(), ast_beep_stop(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_cond_signal, ast_datastore_free(), AST_DECLARE_APP_ARGS, ast_mutex_lock, ast_mutex_unlock, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, mixmonitor_ds::audiohook, mixmonitor_ds::beep_id, ast_datastore::data, mixmonitor_ds::lock, mixmonitor_ds_close_fs(), NULL, parse(), S_OR, ast_audiohook::status, and ast_audiohook::trigger.

Referenced by manager_stop_mixmonitor(), stop_mixmonitor_callback(), and stop_mixmonitor_exec().

1183 {
1184  struct ast_datastore *datastore = NULL;
1185  char *parse = "";
1186  struct mixmonitor_ds *mixmonitor_ds;
1187  const char *beep_id = NULL;
1188 
1190  AST_APP_ARG(mixmonid);
1191  );
1192 
1193  if (!ast_strlen_zero(data)) {
1194  parse = ast_strdupa(data);
1195  }
1196 
1197  AST_STANDARD_APP_ARGS(args, parse);
1198 
1199  ast_channel_lock(chan);
1200 
1202  S_OR(args.mixmonid, NULL));
1203  if (!datastore) {
1204  ast_channel_unlock(chan);
1205  return -1;
1206  }
1207  mixmonitor_ds = datastore->data;
1208 
1209  ast_mutex_lock(&mixmonitor_ds->lock);
1210 
1211  /* closing the filestream here guarantees the file is available to the dialplan
1212  * after calling StopMixMonitor */
1213  mixmonitor_ds_close_fs(mixmonitor_ds);
1214 
1215  /* The mixmonitor thread may be waiting on the audiohook trigger.
1216  * In order to exit from the mixmonitor loop before waiting on channel
1217  * destruction, poke the audiohook trigger. */
1218  if (mixmonitor_ds->audiohook) {
1219  if (mixmonitor_ds->audiohook->status != AST_AUDIOHOOK_STATUS_DONE) {
1221  }
1222  ast_audiohook_lock(mixmonitor_ds->audiohook);
1223  ast_cond_signal(&mixmonitor_ds->audiohook->trigger);
1224  ast_audiohook_unlock(mixmonitor_ds->audiohook);
1225  mixmonitor_ds->audiohook = NULL;
1226  }
1227 
1228  if (!ast_strlen_zero(mixmonitor_ds->beep_id)) {
1229  beep_id = ast_strdupa(mixmonitor_ds->beep_id);
1230  }
1231 
1232  ast_mutex_unlock(&mixmonitor_ds->lock);
1233 
1234  /* Remove the datastore so the monitor thread can exit */
1235  if (!ast_channel_datastore_remove(chan, datastore)) {
1236  ast_datastore_free(datastore);
1237  }
1238 
1239  ast_channel_unlock(chan);
1240 
1241  if (!ast_strlen_zero(beep_id)) {
1242  ast_beep_stop(chan, beep_id);
1243  }
1244 
1245  return 0;
1246 }
#define ast_channel_lock(chan)
Definition: channel.h:2837
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
void ast_audiohook_update_status(struct ast_audiohook *audiohook, enum ast_audiohook_status status)
Update audiohook&#39;s status.
Definition: audiohook.c:565
int AST_OPTIONAL_API_NAME() ast_beep_stop(struct ast_channel *chan, const char *beep_id)
#define ast_mutex_lock(a)
Definition: lock.h:187
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2379
const char * args
#define NULL
Definition: resample.c:96
static const struct ast_datastore_info mixmonitor_ds_info
#define ast_cond_signal(cond)
Definition: lock.h:201
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
static void mixmonitor_ds_close_fs(struct mixmonitor_ds *mixmonitor_ds)
#define ast_strlen_zero(a)
Definition: muted.c:73
#define ast_channel_unlock(chan)
Definition: channel.h:2838
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
ast_mutex_t lock
ast_cond_t trigger
Definition: audiohook.h:105
void * data
Definition: datastore.h:70
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
struct ast_audiohook * audiohook
enum ast_audiohook_status status
Definition: audiohook.h:107
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2374
#define ast_mutex_unlock(a)
Definition: lock.h:188
#define AST_APP_ARG(name)
Define an application argument.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 1570 of file app_mixmonitor.c.

References app, ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_manager_unregister(), ast_unregister_application(), clear_mixmonitor_methods(), and stop_app.

Referenced by load_module().

1571 {
1572  int res;
1573 
1577  res |= ast_manager_unregister("MixMonitorMute");
1578  res |= ast_manager_unregister("MixMonitor");
1579  res |= ast_manager_unregister("StopMixMonitor");
1581  res |= clear_mixmonitor_methods();
1582 
1583  return res;
1584 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
static const char *const stop_app
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
static int clear_mixmonitor_methods(void)
static const char *const app
static struct ast_custom_function mixmonitor_function
static struct ast_cli_entry cli_mixmonitor[]

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Mixed Audio Monitoring Application" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .optional_modules = "func_periodic_hook", }
static

Definition at line 1607 of file app_mixmonitor.c.

◆ app

const char* const app = "MixMonitor"
static

Definition at line 303 of file app_mixmonitor.c.

Referenced by load_module(), and unload_module().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 1607 of file app_mixmonitor.c.

◆ cli_mixmonitor

struct ast_cli_entry cli_mixmonitor[]
static
Initial value:
= {
{ .handler = handle_cli_mixmonitor , .summary = "Execute a MixMonitor command" ,}
}
static char * handle_cli_mixmonitor(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 1551 of file app_mixmonitor.c.

◆ mixmonitor_ds_info

const struct ast_datastore_info mixmonitor_ds_info
static
Initial value:
= {
.type = "mixmonitor",
}
static void mixmonitor_ds_destroy(void *data)

Definition at line 463 of file app_mixmonitor.c.

◆ mixmonitor_function

struct ast_custom_function mixmonitor_function
static
Initial value:
= {
.name = "MIXMONITOR",
}
static int func_mixmonitor_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)

Definition at line 1546 of file app_mixmonitor.c.

◆ mixmonitor_opts

const struct ast_app_option mixmonitor_opts[128] = { [ 'a' ] = { .flag = MUXFLAG_APPEND }, [ 'b' ] = { .flag = MUXFLAG_BRIDGED }, [ 'B' ] = { .flag = MUXFLAG_BEEP , .arg_index = OPT_ARG_BEEP_INTERVAL + 1 }, [ 'p' ] = { .flag = MUXFLAG_BEEP_START }, [ 'P' ] = { .flag = MUXFLAG_BEEP_STOP }, [ 'v' ] = { .flag = MUXFLAG_READVOLUME , .arg_index = OPT_ARG_READVOLUME + 1 }, [ 'V' ] = { .flag = MUXFLAG_WRITEVOLUME , .arg_index = OPT_ARG_WRITEVOLUME + 1 }, [ 'W' ] = { .flag = MUXFLAG_VOLUME , .arg_index = OPT_ARG_VOLUME + 1 }, [ 'r' ] = { .flag = MUXFLAG_READ , .arg_index = OPT_ARG_READNAME + 1 }, [ 't' ] = { .flag = MUXFLAG_WRITE , .arg_index = OPT_ARG_WRITENAME + 1 }, [ 'i' ] = { .flag = MUXFLAG_UID , .arg_index = OPT_ARG_UID + 1 }, [ 'm' ] = { .flag = MUXFLAG_VMRECIPIENTS , .arg_index = OPT_ARG_VMRECIPIENTS + 1 }, [ 'S' ] = { .flag = MUXFLAG_DEPRECATED_RWSYNC , .arg_index = OPT_ARG_DEPRECATED_RWSYNC + 1 }, [ 'n' ] = { .flag = MUXFLAG_NO_RWSYNC , .arg_index = OPT_ARG_NO_RWSYNC + 1 }, }
static

Definition at line 394 of file app_mixmonitor.c.

Referenced by manager_mixmonitor(), and mixmonitor_exec().

◆ mixmonitor_spy_type

const char* const mixmonitor_spy_type = "MixMonitor"
static

◆ stop_app

const char* const stop_app = "StopMixMonitor"
static

Definition at line 305 of file app_mixmonitor.c.

Referenced by load_module(), and unload_module().