summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES4
-rw-r--r--apps/app_mixmonitor.c47
-rw-r--r--apps/app_queue.c6
-rw-r--r--bridges/bridge_builtin_features.c2
-rw-r--r--funcs/func_periodic_hook.c30
-rw-r--r--include/asterisk/beep.h45
-rw-r--r--include/asterisk/monitor.h4
-rw-r--r--res/res_monitor.c47
8 files changed, 171 insertions, 14 deletions
diff --git a/CHANGES b/CHANGES
index 8c3a25347..b4e0d4e91 100644
--- a/CHANGES
+++ b/CHANGES
@@ -16,6 +16,8 @@ Applications
--------------------------
* Record application now has an option 'o' which allows 0 to act as an exit
key setting the RECORD_STATUS variable to 'OPERATOR' instead of 'DTMF'
+ * Monitor() - A new option, B(), has been added that will turn on a periodic
+ beep while the call is being recorded.
Functions
--------------------------
@@ -85,6 +87,8 @@ MixMonitor
-------------------------
* A new function, MIXMONITOR, has been added to allow access to individual
instances of MixMonitor on a channel.
+ * A new option, B(), has been added that will turn on a periodic beep while the
+ call is being recorded.
Channel Drivers
diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c
index a5d383cbc..6a2a0fcec 100644
--- a/apps/app_mixmonitor.c
+++ b/apps/app_mixmonitor.c
@@ -57,6 +57,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/test.h"
#include "asterisk/mixmonitor.h"
+#include "asterisk/beep.h"
/*** DOCUMENTATION
<application name="MixMonitor" language="en_US">
@@ -83,6 +84,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
channel is not optimized away. To do this, be sure to call your Local channel with the
<literal>/n</literal> option. For example: Dial(Local/start@mycontext/n)</para></note>
</option>
+ <option name="B">
+ <para>Play a periodic beep while this call is being recorded.</para>
+ <argument name="interval"><para>Interval, in seconds. Default is 15.</para></argument>
+ </option>
<option name="v">
<para>Adjust the <emphasis>heard</emphasis> volume by a factor of <replaceable>x</replaceable>
(range <literal>-4</literal> to <literal>4</literal>)</para>
@@ -319,6 +324,7 @@ enum mixmonitor_flags {
MUXFLAG_COMBINED = (1 << 8),
MUXFLAG_UID = (1 << 9),
MUXFLAG_VMRECIPIENTS = (1 << 10),
+ MUXFLAG_BEEP = (1 << 11),
};
enum mixmonitor_args {
@@ -329,12 +335,14 @@ enum mixmonitor_args {
OPT_ARG_READNAME,
OPT_ARG_UID,
OPT_ARG_VMRECIPIENTS,
+ OPT_ARG_BEEP_INTERVAL,
OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
};
AST_APP_OPTIONS(mixmonitor_opts, {
AST_APP_OPTION('a', MUXFLAG_APPEND),
AST_APP_OPTION('b', MUXFLAG_BRIDGED),
+ AST_APP_OPTION_ARG('B', MUXFLAG_BEEP, OPT_ARG_BEEP_INTERVAL),
AST_APP_OPTION_ARG('v', MUXFLAG_READVOLUME, OPT_ARG_READVOLUME),
AST_APP_OPTION_ARG('V', MUXFLAG_WRITEVOLUME, OPT_ARG_WRITEVOLUME),
AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME),
@@ -361,6 +369,7 @@ struct mixmonitor_ds {
unsigned int samp_rate;
char *filename;
+ char *beep_id;
};
/*!
@@ -405,6 +414,7 @@ static void mixmonitor_ds_destroy(void *data)
mixmonitor_ds->audiohook = NULL;
mixmonitor_ds->destruction_ok = 1;
ast_free(mixmonitor_ds->filename);
+ ast_free(mixmonitor_ds->beep_id);
ast_cond_signal(&mixmonitor_ds->destruction_condition);
ast_mutex_unlock(&mixmonitor_ds->lock);
}
@@ -772,7 +782,7 @@ static void *mixmonitor_thread(void *obj)
return NULL;
}
-static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id)
+static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id, const char *beep_id)
{
struct ast_datastore *datastore = NULL;
struct mixmonitor_ds *mixmonitor_ds;
@@ -799,6 +809,9 @@ static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel
mixmonitor_ds->samp_rate = 8000;
mixmonitor_ds->audiohook = &mixmonitor->audiohook;
mixmonitor_ds->filename = ast_strdup(mixmonitor->filename);
+ if (!ast_strlen_zero(beep_id)) {
+ mixmonitor_ds->beep_id = ast_strdup(beep_id);
+ }
datastore->data = mixmonitor_ds;
ast_channel_lock(chan);
@@ -813,7 +826,7 @@ 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 *recipients, const char *beep_id)
{
pthread_t thread;
struct mixmonitor *mixmonitor;
@@ -872,7 +885,7 @@ static int launch_monitor_thread(struct ast_channel *chan, const char *filename,
mixmonitor->filename_read = ast_strdup(filename_read);
}
- if (setup_mixmonitor_ds(mixmonitor, chan, &datastore_id)) {
+ if (setup_mixmonitor_ds(mixmonitor, chan, &datastore_id, beep_id)) {
ast_autochan_destroy(mixmonitor->autochan);
mixmonitor_free(mixmonitor);
ast_free(datastore_id);
@@ -973,6 +986,7 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
char *filename_write = NULL;
char filename_buffer[1024] = "";
char *uid_channel_var = NULL;
+ char beep_id[64] = "";
struct ast_flags flags = { 0 };
char *recipients = NULL;
@@ -1046,6 +1060,21 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
if (ast_test_flag(&flags, MUXFLAG_UID)) {
uid_channel_var = opts[OPT_ARG_UID];
}
+
+ if (ast_test_flag(&flags, MUXFLAG_BEEP)) {
+ const char *interval_str = S_OR(opts[OPT_ARG_BEEP_INTERVAL], "15");
+ unsigned int interval = 15;
+
+ if (sscanf(interval_str, "%30u", &interval) != 1) {
+ ast_log(LOG_WARNING, "Invalid interval '%s' for periodic beep. Using default of %u\n",
+ interval_str, interval);
+ }
+
+ if (ast_beep_start(chan, interval, beep_id, sizeof(beep_id))) {
+ ast_log(LOG_WARNING, "Unable to enable periodic beep, please ensure func_periodic_hook is loaded.\n");
+ return -1;
+ }
+ }
}
/* If there are no file writing arguments/options for the mix monitor, send a warning message and return -1 */
@@ -1072,7 +1101,8 @@ static int mixmonitor_exec(struct ast_channel *chan, const char *data)
filename_write,
filename_read,
uid_channel_var,
- recipients)) {
+ recipients,
+ beep_id)) {
ast_module_unref(ast_module_info->self);
}
@@ -1084,6 +1114,7 @@ static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)
struct ast_datastore *datastore = NULL;
char *parse = "";
struct mixmonitor_ds *mixmonitor_ds;
+ const char *beep_id = NULL;
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(mixmonid);
@@ -1123,6 +1154,10 @@ static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)
mixmonitor_ds->audiohook = NULL;
}
+ if (!ast_strlen_zero(mixmonitor_ds->beep_id)) {
+ beep_id = ast_strdupa(mixmonitor_ds->beep_id);
+ }
+
ast_mutex_unlock(&mixmonitor_ds->lock);
/* Remove the datastore so the monitor thread can exit */
@@ -1131,6 +1166,10 @@ static int stop_mixmonitor_full(struct ast_channel *chan, const char *data)
}
ast_channel_unlock(chan);
+ if (!ast_strlen_zero(beep_id)) {
+ ast_beep_stop(chan, beep_id);
+ }
+
return 0;
}
diff --git a/apps/app_queue.c b/apps/app_queue.c
index a2b3b762d..4d97db405 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -6562,13 +6562,13 @@ static int try_calling(struct queue_ent *qe, struct ast_flags opts, char **opt_a
}
ast_channel_unlock(qe->chan);
if (monitorfilename) {
- ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
+ ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT, NULL);
} else if (qe->chan) {
- ast_monitor_start(which, qe->parent->monfmt, ast_channel_uniqueid(qe->chan), 1, X_REC_IN | X_REC_OUT);
+ ast_monitor_start(which, qe->parent->monfmt, ast_channel_uniqueid(qe->chan), 1, X_REC_IN | X_REC_OUT, NULL);
} else {
/* Last ditch effort -- no channel, make up something */
snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
- ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
+ ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT, NULL);
}
if (!ast_strlen_zero(monexec)) {
ast_monitor_setjoinfiles(which, 1);
diff --git a/bridges/bridge_builtin_features.c b/bridges/bridge_builtin_features.c
index ee4a69682..b30005257 100644
--- a/bridges/bridge_builtin_features.c
+++ b/bridges/bridge_builtin_features.c
@@ -196,7 +196,7 @@ static void start_automonitor(struct ast_bridge_channel *bridge_channel, struct
ast_verb(3, "AutoMonitor used to record call. Filename: %s\n", touch_filename);
- if (ast_monitor_start(peer_chan, touch_format, touch_filename, 1, X_REC_IN | X_REC_OUT)) {
+ if (ast_monitor_start(peer_chan, touch_format, touch_filename, 1, X_REC_IN | X_REC_OUT, NULL)) {
ast_verb(3, "automon feature was tried by '%s' but monitor failed to start.\n",
ast_channel_name(bridge_channel->chan));
return;
diff --git a/funcs/func_periodic_hook.c b/funcs/func_periodic_hook.c
index 661ebcbed..39dfab396 100644
--- a/funcs/func_periodic_hook.c
+++ b/funcs/func_periodic_hook.c
@@ -42,6 +42,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/app.h"
#include "asterisk/audiohook.h"
+#define AST_API_MODULE
+#include "asterisk/beep.h"
/*** DOCUMENTATION
<function name="PERIODIC_HOOK" language="en_US">
@@ -93,6 +95,8 @@ static const char context_name[] = "__func_periodic_hook_context__";
static const char exten_name[] = "hook";
static const char full_exten_name[] = "hook@__func_periodic_hook_context__";
+static const char beep_exten[] = "beep";
+
/*!
* \brief Last used hook ID
*
@@ -485,9 +489,35 @@ static int load_module(void)
ast_add_extension(context_name, 1, exten_name, 6, "", "",
"ChanSpy", "${ChannelToSpy},qEB", NULL, AST_MODULE);
+ res = ast_add_extension(context_name, 1, beep_exten, 1, "", "",
+ "Answer", "", NULL, AST_MODULE);
+ res |= ast_add_extension(context_name, 1, beep_exten, 2, "", "",
+ "Playback", "beep", NULL, AST_MODULE);
+
res = ast_custom_function_register_escalating(&hook_function, AST_CFE_BOTH);
return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
}
+int AST_OPTIONAL_API_NAME(ast_beep_start)(struct ast_channel *chan,
+ unsigned int interval, char *beep_id, size_t len)
+{
+ char args[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 32];
+
+ snprintf(args, sizeof(args), "%s,%s,%u",
+ context_name, beep_exten, interval);
+
+ if (hook_read(chan, NULL, args, beep_id, len)) {
+ ast_log(LOG_WARNING, "Failed to enable periodic beep.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int AST_OPTIONAL_API_NAME(ast_beep_stop)(struct ast_channel *chan, const char *beep_id)
+{
+ return hook_write(chan, NULL, (char *) beep_id, "off");
+}
+
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Periodic dialplan hooks.");
diff --git a/include/asterisk/beep.h b/include/asterisk/beep.h
new file mode 100644
index 000000000..f436e9cab
--- /dev/null
+++ b/include/asterisk/beep.h
@@ -0,0 +1,45 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2014, Russell Bryant
+ *
+ * Russell Bryant <russell@russellbryant.net>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Periodic beeps into the audio of a call
+ */
+
+#ifndef _ASTERISK_BEEP_H
+#define _ASTERISK_BEEP_H
+
+#include "asterisk/optional_api.h"
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+AST_OPTIONAL_API(int, ast_beep_start,
+ (struct ast_channel *chan, unsigned int interval, char *beep_id, size_t len),
+ { return -1; });
+
+AST_OPTIONAL_API(int, ast_beep_stop,
+ (struct ast_channel *chan, const char *beep_id),
+ { return -1; });
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif /* _ASTERISK_BEEP_H */
diff --git a/include/asterisk/monitor.h b/include/asterisk/monitor.h
index e29622ea8..6030221a2 100644
--- a/include/asterisk/monitor.h
+++ b/include/asterisk/monitor.h
@@ -43,6 +43,7 @@ struct ast_channel_monitor {
char read_filename[FILENAME_MAX];
char write_filename[FILENAME_MAX];
char filename_base[FILENAME_MAX];
+ char beep_id[64];
int filename_changed;
char *format;
int joinfiles;
@@ -53,7 +54,8 @@ struct ast_channel_monitor {
/* Start monitoring a channel */
AST_OPTIONAL_API(int, ast_monitor_start,
(struct ast_channel *chan, const char *format_spec,
- const char *fname_base, int need_lock, int stream_action),
+ const char *fname_base, int need_lock, int stream_action,
+ const char *beep_id),
{ return -1; });
/* Stop monitoring a channel */
diff --git a/res/res_monitor.c b/res/res_monitor.c
index 2eafcb238..f81507285 100644
--- a/res/res_monitor.c
+++ b/res/res_monitor.c
@@ -50,6 +50,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/config.h"
#include "asterisk/options.h"
+#include "asterisk/beep.h"
/*** DOCUMENTATION
<application name="Monitor" language="en_US">
@@ -84,6 +85,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<option name="b">
<para>Don't begin recording unless a call is bridged to another channel.</para>
</option>
+ <option name="B">
+ <para>Play a periodic beep while this call is being recorded.</para>
+ <argument name="interval"><para>Interval, in seconds. Default is 15.</para></argument>
+ </option>
<option name="i">
<para>Skip recording of input stream (disables <literal>m</literal> option).</para>
</option>
@@ -290,7 +295,8 @@ static int ast_monitor_set_state(struct ast_channel *chan, int state)
* \retval -1 on failure
*/
int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const char *format_spec,
- const char *fname_base, int need_lock, int stream_action)
+ const char *fname_base, int need_lock, int stream_action,
+ const char *beep_id)
{
int res = 0;
RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
@@ -309,6 +315,10 @@ int AST_OPTIONAL_API_NAME(ast_monitor_start)(struct ast_channel *chan, const cha
return -1;
}
+ if (!ast_strlen_zero(beep_id)) {
+ ast_copy_string(monitor->beep_id, beep_id, sizeof(monitor->beep_id));
+ }
+
/* Determine file names */
if (!ast_strlen_zero(fname_base)) {
int directory = strchr(fname_base, '/') ? 1 : 0;
@@ -511,7 +521,11 @@ int AST_OPTIONAL_API_NAME(ast_monitor_stop)(struct ast_channel *chan, int need_l
if (ast_safe_system(tmp) == -1)
ast_log(LOG_WARNING, "Execute of %s failed.\n",tmp);
}
-
+
+ if (!ast_strlen_zero(ast_channel_monitor(chan)->beep_id)) {
+ ast_beep_stop(chan, ast_channel_monitor(chan)->beep_id);
+ }
+
ast_free(ast_channel_monitor(chan)->format);
ast_free(ast_channel_monitor(chan));
ast_channel_monitor_set(chan, NULL);
@@ -644,6 +658,12 @@ enum {
MON_FLAG_MIX = (1 << 1),
MON_FLAG_DROP_IN = (1 << 2),
MON_FLAG_DROP_OUT = (1 << 3),
+ MON_FLAG_BEEP = (1 << 4),
+};
+
+enum {
+ OPT_ARG_BEEP_INTERVAL,
+ OPT_ARG_ARRAY_SIZE, /* Always last element of the enum */
};
AST_APP_OPTIONS(monitor_opts, {
@@ -651,6 +671,7 @@ AST_APP_OPTIONS(monitor_opts, {
AST_APP_OPTION('m', MON_FLAG_MIX),
AST_APP_OPTION('i', MON_FLAG_DROP_IN),
AST_APP_OPTION('o', MON_FLAG_DROP_OUT),
+ AST_APP_OPTION_ARG('B', MON_FLAG_BEEP, OPT_ARG_BEEP_INTERVAL),
});
/*!
@@ -672,6 +693,8 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data)
int res = 0;
char *parse;
struct ast_flags flags = { 0 };
+ char *opts[OPT_ARG_ARRAY_SIZE] = { NULL, };
+ char beep_id[64] = "";
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(format);
AST_APP_ARG(fname_base);
@@ -688,7 +711,7 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data)
AST_STANDARD_APP_ARGS(args, parse);
if (!ast_strlen_zero(args.options)) {
- ast_app_parse_options(monitor_opts, &flags, NULL, args.options);
+ ast_app_parse_options(monitor_opts, &flags, opts, args.options);
if (ast_test_flag(&flags, MON_FLAG_MIX)) {
stream_action |= X_JOIN;
@@ -699,6 +722,20 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data)
if (ast_test_flag(&flags, MON_FLAG_DROP_OUT)) {
stream_action &= ~X_REC_OUT;
}
+ if (ast_test_flag(&flags, MON_FLAG_BEEP)) {
+ const char *interval_str = S_OR(opts[OPT_ARG_BEEP_INTERVAL], "15");
+ unsigned int interval = 15;
+
+ if (sscanf(interval_str, "%30u", &interval) != 1) {
+ ast_log(LOG_WARNING, "Invalid interval '%s' for periodic beep. Using default of %u\n",
+ interval_str, interval);
+ }
+
+ if (ast_beep_start(chan, interval, beep_id, sizeof(beep_id))) {
+ ast_log(LOG_WARNING, "Unable to enable periodic beep, please ensure func_periodic_hook is loaded.\n");
+ return -1;
+ }
+ }
}
arg = strchr(args.format, ':');
@@ -731,7 +768,7 @@ static int start_monitor_exec(struct ast_channel *chan, const char *data)
return 0;
}
- res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action);
+ res = ast_monitor_start(chan, args.format, args.fname_base, 1, stream_action, beep_id);
if (res < 0)
res = ast_monitor_change_fname(chan, args.fname_base, 1);
@@ -790,7 +827,7 @@ static int start_monitor_action(struct mansession *s, const struct message *m)
}
}
- if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT)) {
+ if (ast_monitor_start(c, format, fname, 1, X_REC_IN | X_REC_OUT, NULL)) {
if (ast_monitor_change_fname(c, fname, 1)) {
astman_send_error(s, m, "Could not start monitoring channel");
c = ast_channel_unref(c);