summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/res_stasis_playback.c94
1 files changed, 77 insertions, 17 deletions
diff --git a/res/res_stasis_playback.c b/res/res_stasis_playback.c
index f78ccf0ba..ce29de12c 100644
--- a/res/res_stasis_playback.c
+++ b/res/res_stasis_playback.c
@@ -47,6 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_channels.h"
#include "asterisk/stringfields.h"
#include "asterisk/uuid.h"
+#include "asterisk/say.h"
/*! Number of hash buckets for playback container. Keep it prime! */
#define PLAYBACK_BUCKETS 127
@@ -56,6 +57,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define SOUND_URI_SCHEME "sound:"
#define RECORDING_URI_SCHEME "recording:"
+#define NUMBER_URI_SCHEME "number:"
+#define DIGITS_URI_SCHEME "digits:"
+#define CHARACTERS_URI_SCHEME "characters:"
/*! Container of all current playbacks */
static struct ao2_container *playbacks;
@@ -74,15 +78,16 @@ struct stasis_app_playback {
long offsetms;
/*! Number of milliseconds to skip for forward/reverse operations */
int skipms;
-
- /*! Set when playback has been completed */
- int done;
/*! Condition for waiting on done to be set */
ast_cond_t done_cond;
/*! Number of milliseconds of media that has been played */
long playedms;
/*! Current playback state */
enum stasis_app_playback_state state;
+ /*! Set when playback has been completed */
+ unsigned int done:1;
+ /*! Set when the playback can be controlled */
+ unsigned int controllable:1;
};
static struct ast_json *playback_to_json(struct stasis_message *message,
@@ -272,8 +277,6 @@ static void play_on_channel(struct stasis_app_playback *playback,
{
RAII_VAR(struct stasis_app_playback *, mark_when_done, playback,
mark_as_done);
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
- RAII_VAR(char *, file, NULL, ast_free);
int res;
long offsetms;
@@ -301,8 +304,12 @@ static void play_on_channel(struct stasis_app_playback *playback,
}
if (ast_begins_with(playback->media, SOUND_URI_SCHEME)) {
+ playback->controllable = 1;
+
/* Play sound */
- file = ast_strdup(playback->media + strlen(SOUND_URI_SCHEME));
+ res = ast_control_streamfile_lang(chan, playback->media + strlen(SOUND_URI_SCHEME),
+ fwd, rev, stop, pause, restart, playback->skipms, playback->language,
+ &offsetms);
} else if (ast_begins_with(playback->media, RECORDING_URI_SCHEME)) {
/* Play recording */
RAII_VAR(struct stasis_app_stored_recording *, recording, NULL,
@@ -310,23 +317,41 @@ static void play_on_channel(struct stasis_app_playback *playback,
const char *relname =
playback->media + strlen(RECORDING_URI_SCHEME);
recording = stasis_app_stored_recording_find_by_name(relname);
- if (recording) {
- file = ast_strdup(stasis_app_stored_recording_get_file(
- recording));
+
+ if (!recording) {
+ ast_log(LOG_ERROR, "Attempted to play recording '%s' on channel '%s' but recording does not exist",
+ ast_channel_name(chan), relname);
+ return;
}
+
+ playback->controllable = 1;
+
+ res = ast_control_streamfile_lang(chan,
+ stasis_app_stored_recording_get_file(recording), fwd, rev, stop, pause,
+ restart, playback->skipms, playback->language, &offsetms);
+ } else if (ast_begins_with(playback->media, NUMBER_URI_SCHEME)) {
+ int number;
+
+ if (sscanf(playback->media + strlen(NUMBER_URI_SCHEME), "%30d", &number) != 1) {
+ ast_log(LOG_ERROR, "Attempted to play number '%s' on channel '%s' but number is invalid",
+ ast_channel_name(chan), playback->media + strlen(NUMBER_URI_SCHEME));
+ return;
+ }
+
+ res = ast_say_number(chan, number, stop, playback->language, NULL);
+ } else if (ast_begins_with(playback->media, DIGITS_URI_SCHEME)) {
+ res = ast_say_digit_str(chan, playback->media + strlen(DIGITS_URI_SCHEME),
+ stop, playback->language);
+ } 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 {
/* Play URL */
- ast_log(LOG_ERROR, "Unimplemented\n");
+ ast_log(LOG_ERROR, "Attempted to play URI '%s' on channel '%s' but scheme is unsupported",
+ ast_channel_name(chan), playback->media);
return;
}
- if (!file) {
- return;
- }
-
- res = ast_control_streamfile_lang(chan, file, fwd, rev, stop, pause,
- restart, playback->skipms, playback->language, &offsetms);
-
playback_final_update(playback, offsetms, res,
ast_channel_uniqueid(chan));
@@ -527,6 +552,11 @@ static int playback_cancel(struct stasis_app_playback *playback)
static int playback_stop(struct stasis_app_playback *playback)
{
SCOPED_AO2LOCK(lock, playback);
+
+ if (!playback->controllable) {
+ return -1;
+ }
+
playback->state = STASIS_PLAYBACK_STATE_STOPPED;
return stasis_app_control_queue_control(playback->control,
AST_CONTROL_STREAM_STOP);
@@ -534,6 +564,12 @@ static int playback_stop(struct stasis_app_playback *playback)
static int playback_restart(struct stasis_app_playback *playback)
{
+ SCOPED_AO2LOCK(lock, playback);
+
+ if (!playback->controllable) {
+ return -1;
+ }
+
return stasis_app_control_queue_control(playback->control,
AST_CONTROL_STREAM_RESTART);
}
@@ -541,8 +577,14 @@ static int playback_restart(struct stasis_app_playback *playback)
static int playback_pause(struct stasis_app_playback *playback)
{
SCOPED_AO2LOCK(lock, playback);
+
+ if (!playback->controllable) {
+ return -1;
+ }
+
playback->state = STASIS_PLAYBACK_STATE_PAUSED;
playback_publish(playback);
+
return stasis_app_control_queue_control(playback->control,
AST_CONTROL_STREAM_SUSPEND);
}
@@ -550,20 +592,38 @@ static int playback_pause(struct stasis_app_playback *playback)
static int playback_unpause(struct stasis_app_playback *playback)
{
SCOPED_AO2LOCK(lock, playback);
+
+ if (!playback->controllable) {
+ return -1;
+ }
+
playback->state = STASIS_PLAYBACK_STATE_PLAYING;
playback_publish(playback);
+
return stasis_app_control_queue_control(playback->control,
AST_CONTROL_STREAM_SUSPEND);
}
static int playback_reverse(struct stasis_app_playback *playback)
{
+ SCOPED_AO2LOCK(lock, playback);
+
+ if (!playback->controllable) {
+ return -1;
+ }
+
return stasis_app_control_queue_control(playback->control,
AST_CONTROL_STREAM_REVERSE);
}
static int playback_forward(struct stasis_app_playback *playback)
{
+ SCOPED_AO2LOCK(lock, playback);
+
+ if (!playback->controllable) {
+ return -1;
+ }
+
return stasis_app_control_queue_control(playback->control,
AST_CONTROL_STREAM_FORWARD);
}