summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES19
-rw-r--r--include/asterisk/app.h8
-rw-r--r--main/app.c137
-rw-r--r--res/ari/resource_bridges.h2
-rw-r--r--res/ari/resource_channels.h2
-rw-r--r--res/res_stasis_playback.c5
-rw-r--r--rest-api/api-docs/bridges.json2
-rw-r--r--rest-api/api-docs/channels.json2
8 files changed, 172 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index dc261055e..f8712b38c 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,23 @@
--- Functionality changes from Asterisk 12 to Asterisk 13 --------------------
------------------------------------------------------------------------------
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 12.2.0 to Asterisk 12.3.0 ------------
+------------------------------------------------------------------------------
+
+ARI
+------------------
+ * A new Playback URI 'tone' has been added. Tones are specified either as
+ an indication name (e.g. 'tone:busy') from indications.conf or as a tone
+ pattern (e.g. 'tone:240/250,0/250'). Tones differ from normal playback
+ URIs in that they must be stopped manually and will continue to occupy
+ a channel's ARI control queue until they are stopped. They also can not
+ be rewound or fastforwarded.
+
+------------------------------------------------------------------------------
+--- Functionality changes from Asterisk 12.1.0 to Asterisk 12.2.0 ------------
+------------------------------------------------------------------------------
+
Applications
--------------------------
* Record application now has an option 'o' which allows 0 to act as an exit
@@ -143,7 +160,7 @@ AMI
used to set the UniqueId on creation. The other id is assigned to the
second channel when dialing LOCAL, or defaults to appending ;2 if only
the single Id is given.
-
+
* The Mixmonitor action now has a "Command" header that can be used to
indicate a post-process command to run once recording finishes.
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index 70cf75270..65d74dcd1 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -880,6 +880,14 @@ int ast_control_streamfile_lang(struct ast_channel *chan, const char *file,
const char *restart, int skipms, const char *lang, long *offsetms);
/*!
+ * \brief Controls playback of a tone
+ *
+ * \retval 0 on success
+ * \retval Non-zero on failure
+ */
+int ast_control_tone(struct ast_channel *chan, const char *tone);
+
+/*!
* \brief Stream a file with fast forward, pause, reverse, restart.
* \param chan
* \param file filename
diff --git a/main/app.c b/main/app.c
index b6c988258..f7bb0048c 100644
--- a/main/app.c
+++ b/main/app.c
@@ -1070,6 +1070,143 @@ int ast_control_streamfile_lang(struct ast_channel *chan, const char *file,
return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, lang, NULL);
}
+enum control_tone_frame_response_result {
+ CONTROL_TONE_RESPONSE_FAILED = -1,
+ CONTROL_TONE_RESPONSE_NORMAL = 0,
+ CONTROL_TONE_RESPONSE_FINISHED = 1,
+};
+
+static enum control_tone_frame_response_result control_tone_frame_response(struct ast_channel *chan, struct ast_frame *fr, struct ast_tone_zone_sound *ts, const char *tone, int *paused)
+{
+ switch (fr->subclass.integer) {
+ case AST_CONTROL_STREAM_STOP:
+ ast_playtones_stop(chan);
+ return CONTROL_TONE_RESPONSE_FINISHED;
+ case AST_CONTROL_STREAM_SUSPEND:
+ if (*paused) {
+ *paused = 0;
+ if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
+ return CONTROL_TONE_RESPONSE_FAILED;
+ }
+ } else {
+ *paused = 1;
+ ast_playtones_stop(chan);
+ }
+ return CONTROL_TONE_RESPONSE_NORMAL;
+ case AST_CONTROL_STREAM_RESTART:
+ ast_playtones_stop(chan);
+ if (ast_playtones_start(chan, 0, ts ? ts->data : tone, 0)) {
+ return CONTROL_TONE_RESPONSE_FAILED;
+ }
+ return CONTROL_TONE_RESPONSE_NORMAL;
+ case AST_CONTROL_STREAM_REVERSE:
+ ast_log(LOG_NOTICE, "Media control operation 'reverse' not supported for media type 'tone'\n");
+ return CONTROL_TONE_RESPONSE_NORMAL;
+ case AST_CONTROL_STREAM_FORWARD:
+ ast_log(LOG_NOTICE, "Media control operation 'forward' not supported for media type 'tone'\n");
+ return CONTROL_TONE_RESPONSE_NORMAL;
+ case AST_CONTROL_HANGUP:
+ case AST_CONTROL_BUSY:
+ case AST_CONTROL_CONGESTION:
+ return CONTROL_TONE_RESPONSE_FINISHED;
+ }
+
+ return CONTROL_TONE_RESPONSE_NORMAL;
+}
+
+static int parse_tone_uri(char *tone_parser,
+ const char **tone_indication,
+ const char **tone_zone)
+{
+ *tone_indication = strsep(&tone_parser, ";");
+
+ if (ast_strlen_zero(tone_parser)) {
+ /* Only the indication is included */
+ return 0;
+ }
+
+ if (!(strncmp(tone_parser, "tonezone=", 9))) {
+ *tone_zone = tone_parser + 9;
+ } else {
+ ast_log(LOG_ERROR, "Unexpected Tone URI component: %s\n", tone_parser);
+ return -1;
+ }
+
+ return 0;
+}
+
+int ast_control_tone(struct ast_channel *chan, const char *tone)
+{
+ struct ast_tone_zone *zone = NULL;
+ struct ast_tone_zone_sound *ts;
+ int paused = 0;
+ int res;
+
+ const char *tone_indication = NULL;
+ const char *tone_zone = NULL;
+ char *tone_uri_parser;
+
+ if (ast_strlen_zero(tone)) {
+ return -1;
+ }
+
+ tone_uri_parser = ast_strdupa(tone);
+
+ if (parse_tone_uri(tone_uri_parser, &tone_indication, &tone_zone)) {
+ return -1;
+ }
+
+ if (tone_zone) {
+ zone = ast_get_indication_zone(tone_zone);
+ }
+
+ ts = ast_get_indication_tone(zone ? zone : ast_channel_zone(chan), tone_indication);
+
+ if (ast_playtones_start(chan, 0, ts ? ts->data : tone_indication, 0)) {
+ return -1;
+ }
+
+ for (;;) {
+ struct ast_frame *fr;
+ int res;
+
+ if (ast_waitfor(chan, -1) < 0) {
+ res = -1;
+ break;
+ }
+
+ fr = ast_read_noaudio(chan);
+
+ if (!fr) {
+ res = -1;
+ break;
+ }
+
+ if (fr->frametype != AST_FRAME_CONTROL) {
+ continue;
+ }
+
+ res = control_tone_frame_response(chan, fr, ts, tone_indication, &paused);
+ if (res == CONTROL_TONE_RESPONSE_FINISHED) {
+ res = 0;
+ break;
+ } else if (res == CONTROL_TONE_RESPONSE_FAILED) {
+ res = -1;
+ break;
+ }
+ }
+
+ if (ts) {
+ ast_tone_zone_sound_unref(ts);
+ }
+
+ if (zone) {
+ ast_tone_zone_unref(zone);
+ }
+
+ return res;
+}
+
int ast_play_and_wait(struct ast_channel *chan, const char *fn)
{
int d = 0;
diff --git a/res/ari/resource_bridges.h b/res/ari/resource_bridges.h
index 5dca82781..404760c91 100644
--- a/res/ari/resource_bridges.h
+++ b/res/ari/resource_bridges.h
@@ -268,7 +268,7 @@ int ast_ari_bridges_play_parse_body(
/*!
* \brief Start playback of media on a bridge.
*
- * The media URI may be any of a number of URI's. Currently sound: and recording: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)
+ * The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)
*
* \param headers HTTP headers
* \param args Swagger parameters
diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h
index cf48cee75..bc50c3da4 100644
--- a/res/ari/resource_channels.h
+++ b/res/ari/resource_channels.h
@@ -460,7 +460,7 @@ int ast_ari_channels_play_parse_body(
/*!
* \brief Start playback of media.
*
- * The media URI may be any of a number of URI's. Currently sound: and recording: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)
+ * The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)
*
* \param headers HTTP headers
* \param args Swagger parameters
diff --git a/res/res_stasis_playback.c b/res/res_stasis_playback.c
index 79c2bab9c..960f2e334 100644
--- a/res/res_stasis_playback.c
+++ b/res/res_stasis_playback.c
@@ -48,6 +48,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stringfields.h"
#include "asterisk/uuid.h"
#include "asterisk/say.h"
+#include "asterisk/indications.h"
/*! Number of hash buckets for playback container. Keep it prime! */
#define PLAYBACK_BUCKETS 127
@@ -60,6 +61,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define NUMBER_URI_SCHEME "number:"
#define DIGITS_URI_SCHEME "digits:"
#define CHARACTERS_URI_SCHEME "characters:"
+#define TONE_URI_SCHEME "tone:"
/*! Container of all current playbacks */
static struct ao2_container *playbacks;
@@ -323,6 +325,9 @@ static void play_on_channel(struct stasis_app_playback *playback,
} else if (ast_begins_with(playback->media, CHARACTERS_URI_SCHEME)) {
res = ast_say_character_str(chan, playback->media + strlen(CHARACTERS_URI_SCHEME),
stop, playback->language, AST_SAY_CASE_NONE);
+ } else if (ast_begins_with(playback->media, TONE_URI_SCHEME)) {
+ playback->controllable = 1;
+ res = ast_control_tone(chan, playback->media + strlen(TONE_URI_SCHEME));
} else {
/* Play URL */
ast_log(LOG_ERROR, "Attempted to play URI '%s' on channel '%s' but scheme is unsupported",
diff --git a/rest-api/api-docs/bridges.json b/rest-api/api-docs/bridges.json
index 56a7a941e..4d2c77cea 100644
--- a/rest-api/api-docs/bridges.json
+++ b/rest-api/api-docs/bridges.json
@@ -314,7 +314,7 @@
{
"httpMethod": "POST",
"summary": "Start playback of media on a bridge.",
- "notes": "The media URI may be any of a number of URI's. Currently sound: and recording: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)",
+ "notes": "The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)",
"nickname": "play",
"responseClass": "Playback",
"parameters": [
diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json
index d940f4383..cc7feb6a9 100644
--- a/rest-api/api-docs/channels.json
+++ b/rest-api/api-docs/channels.json
@@ -808,7 +808,7 @@
{
"httpMethod": "POST",
"summary": "Start playback of media.",
- "notes": "The media URI may be any of a number of URI's. Currently sound: and recording: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)",
+ "notes": "The media URI may be any of a number of URI's. Currently sound:, recording:, number:, digits:, characters:, and tone: URI's are supported. This operation creates a playback resource that can be used to control the playback of media (pause, rewind, fast forward, etc.)",
"nickname": "play",
"responseClass": "Playback",
"parameters": [