res_stasis_playback: Add 'number', 'digits', and 'characters' URI scheme implementations.
authorJoshua Colp <jcolp@digium.com>
Thu, 28 Nov 2013 00:54:37 +0000 (00:54 +0000)
committerJoshua Colp <jcolp@digium.com>
Thu, 28 Nov 2013 00:54:37 +0000 (00:54 +0000)
This change adds new URI scheme implementations for playing numbers, digits,
and characters. This is done as part of the normal playback mechanism and can
be used with queueing to create a combined sentence.

Review: https://reviewboard.asterisk.org/r/3028/
........

Merged revisions 403209 from http://svn.asterisk.org/svn/asterisk/branches/12

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@403210 65c4cc65-6c06-0410-ace0-fbb531ad65f3

res/res_stasis_playback.c

index f78ccf0..ce29de1 100644 (file)
@@ -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);
 }