[asterisk-commits] dlee: branch dlee/playback-controls r388577 - in /team/dlee/playback-controls...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon May 13 14:24:02 CDT 2013
Author: dlee
Date: Mon May 13 14:24:00 2013
New Revision: 388577
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388577
Log:
Playback control operations
Modified:
team/dlee/playback-controls/include/asterisk/channel.h
team/dlee/playback-controls/include/asterisk/stasis_app.h
team/dlee/playback-controls/include/asterisk/stasis_app_playback.h
team/dlee/playback-controls/res/res_stasis_playback.c
team/dlee/playback-controls/res/stasis/control.c
team/dlee/playback-controls/res/stasis_http/resource_playback.c
team/dlee/playback-controls/rest-api/api-docs/playback.json
Modified: team/dlee/playback-controls/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/include/asterisk/channel.h?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/include/asterisk/channel.h (original)
+++ team/dlee/playback-controls/include/asterisk/channel.h Mon May 13 14:24:00 2013
@@ -1205,7 +1205,7 @@
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause);
/*!
- * \brief Queue a control frame with payload
+ * \brief Queue a control frame without payload
*
* \param chan channel to queue frame onto
* \param control type of control frame
Modified: team/dlee/playback-controls/include/asterisk/stasis_app.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/include/asterisk/stasis_app.h?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/include/asterisk/stasis_app.h (original)
+++ team/dlee/playback-controls/include/asterisk/stasis_app.h Mon May 13 14:24:00 2013
@@ -170,6 +170,18 @@
void stasis_app_control_publish(
struct stasis_app_control *control, struct stasis_message *message);
+/*!
+ * \brief Queue a control frame without payload.
+ *
+ * \param control Control to publish to.
+ * \param frame_type type of control frame.
+ *
+ * \return zero on success
+ * \return non-zero on failure
+ */
+int stasis_app_control_queue_control(struct stasis_app_control *control,
+ enum ast_control_frame_type frame_type);
+
/*! @} */
#endif /* _ASTERISK_STASIS_APP_H */
Modified: team/dlee/playback-controls/include/asterisk/stasis_app_playback.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/include/asterisk/stasis_app_playback.h?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/include/asterisk/stasis_app_playback.h (original)
+++ team/dlee/playback-controls/include/asterisk/stasis_app_playback.h Mon May 13 14:24:00 2013
@@ -41,16 +41,16 @@
STASIS_PLAYBACK_STATE_PLAYING,
/*! The media has stopped playing */
STASIS_PLAYBACK_STATE_COMPLETE,
+ /*! The media was cancelled before playback could start */
+ STASIS_PLAYBACK_STATE_CANCELLED,
};
-enum stasis_app_playback_media_control {
+enum stasis_app_playback_media_operation {
STASIS_PLAYBACK_STOP,
STASIS_PLAYBACK_PAUSE,
STASIS_PLAYBACK_PLAY,
STASIS_PLAYBACK_REWIND,
STASIS_PLAYBACK_FAST_FORWARD,
- STASIS_PLAYBACK_SPEED_UP,
- STASIS_PLAYBACK_SLOW_DOWN,
};
/*!
@@ -95,18 +95,27 @@
* \return Associated \ref stasis_app_playback object.
* \return \c NULL if \a id not found.
*/
-struct ast_json *stasis_app_playback_find_by_id(const char *id);
+struct stasis_app_playback *stasis_app_playback_find_by_id(const char *id);
+struct ast_json *stasis_app_playback_to_json(
+ const struct stasis_app_playback *playback);
+
+enum stasis_playback_oper_results {
+ STASIS_PLAYBACK_OPER_OK,
+ STASIS_PLAYBACK_OPER_FAILED,
+ STASIS_PLAYBACK_OPER_NOT_PLAYING,
+};
/*!
* \brief Controls the media for a given playback operation.
*
* \param playback Playback control object.
* \param control Media control operation.
- * \return 0 on success
- * \return non-zero on error.
+ * \return 0 on success.
+ * \return -1 Playback isn't in a valid state for the operation.
+ * \return -2 Operation failed.
*/
-int stasis_app_playback_control(struct stasis_app_playback *playback,
- enum stasis_app_playback_media_control control);
+int stasis_app_playback_operation(struct stasis_app_playback *playback,
+ enum stasis_app_playback_media_operation operation);
/*!
* \brief Message type for playback updates. The data is an
Modified: team/dlee/playback-controls/res/res_stasis_playback.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/res/res_stasis_playback.c?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/res/res_stasis_playback.c (original)
+++ team/dlee/playback-controls/res/res_stasis_playback.c Mon May 13 14:24:00 2013
@@ -86,36 +86,6 @@
}
}
-static struct ast_json *playback_to_json(struct stasis_app_playback *playback)
-{
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
- char *state = "?";
-
- if (playback == NULL) {
- return NULL;
- }
-
- switch (playback->state) {
- case STASIS_PLAYBACK_STATE_QUEUED:
- state = "queued";
- break;
- case STASIS_PLAYBACK_STATE_PLAYING:
- state = "playing";
- break;
- case STASIS_PLAYBACK_STATE_COMPLETE:
- state = "complete";
- break;
- }
-
- json = ast_json_pack("{s: s, s: s, s: s, s: s}",
- "id", playback->id,
- "media_uri", playback->media,
- "language", playback->language,
- "state", state);
-
- return ast_json_ref(json);
-}
-
static void playback_publish(struct stasis_app_playback *playback)
{
RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
@@ -124,7 +94,7 @@
ast_assert(playback != NULL);
- json = playback_to_json(playback);
+ json = stasis_app_playback_to_json(playback);
if (json == NULL) {
return;
}
@@ -168,7 +138,13 @@
playback = data;
ast_assert(playback != NULL);
+ ao2_lock(playback);
+ if (playback->state == STASIS_PLAYBACK_STATE_CANCELLED) {
+ ao2_unlock(playback);
+ return NULL;
+ }
playback_set_state(playback, STASIS_PLAYBACK_STATE_PLAYING);
+ ao2_unlock(playback);
if (ast_channel_state(chan) != AST_STATE_UP) {
ast_answer(chan);
@@ -246,26 +222,111 @@
return control->id;
}
-struct ast_json *stasis_app_playback_find_by_id(const char *id)
+struct stasis_app_playback *stasis_app_playback_find_by_id(const char *id)
{
RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
playback = ao2_find(playbacks, id, OBJ_KEY);
if (playback == NULL) {
return NULL;
}
- json = playback_to_json(playback);
+ ao2_ref(playback, +1);
+ return playback;
+}
+
+struct ast_json *stasis_app_playback_to_json(
+ const struct stasis_app_playback *playback)
+{
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ char *state = "?";
+
+ if (playback == NULL) {
+ return NULL;
+ }
+
+ switch (playback->state) {
+ case STASIS_PLAYBACK_STATE_QUEUED:
+ state = "queued";
+ break;
+ case STASIS_PLAYBACK_STATE_PLAYING:
+ state = "playing";
+ break;
+ case STASIS_PLAYBACK_STATE_COMPLETE:
+ case STASIS_PLAYBACK_STATE_CANCELLED:
+ /* Treat cancelled as complete */
+ state = "complete";
+ break;
+ }
+
+ json = ast_json_pack("{s: s, s: s, s: s, s: s}",
+ "id", playback->id,
+ "media_uri", playback->media,
+ "language", playback->language,
+ "state", state);
+
return ast_json_ref(json);
}
-int stasis_app_playback_control(struct stasis_app_playback *playback,
- enum stasis_app_playback_media_control control)
-{
+int stasis_app_playback_operation(struct stasis_app_playback *playback,
+ enum stasis_app_playback_media_operation operation)
+{
+ enum ast_control_frame_type frame_type = -1;
+ int res;
+
SCOPED_AO2LOCK(lock, playback);
- ast_assert(0); /* TODO */
- return -1;
+
+ switch (playback->state) {
+ case STASIS_PLAYBACK_STATE_COMPLETE:
+ case STASIS_PLAYBACK_STATE_CANCELLED:
+ if (operation == STASIS_PLAYBACK_STOP) {
+ /* Already stopped. */
+ return 0;
+ } else {
+ /* Invalid state for operation */
+ return STASIS_PLAYBACK_OPER_NOT_PLAYING;
+ }
+ break;
+ case STASIS_PLAYBACK_STATE_QUEUED:
+ if (operation == STASIS_PLAYBACK_STOP) {
+ /* Cancel a playback before it starts */
+ playback_set_state(playback,
+ STASIS_PLAYBACK_STATE_CANCELLED);
+ } else {
+ /* None of the other ops make sense for queued media */
+ return STASIS_PLAYBACK_OPER_NOT_PLAYING;
+ }
+ break;
+ case STASIS_PLAYBACK_STATE_PLAYING:
+ /* Media control makes sense. Carry on, then. */
+ break;
+ }
+
+ switch (operation) {
+ case STASIS_PLAYBACK_STOP:
+ frame_type = AST_CONTROL_STREAM_STOP;
+ break;
+ case STASIS_PLAYBACK_PAUSE:
+ frame_type = AST_CONTROL_STREAM_SUSPEND;
+ break;
+ case STASIS_PLAYBACK_PLAY:
+ frame_type = AST_CONTROL_STREAM_RESTART;
+ break;
+ case STASIS_PLAYBACK_REWIND:
+ frame_type = AST_CONTROL_STREAM_REVERSE;
+ break;
+ case STASIS_PLAYBACK_FAST_FORWARD:
+ frame_type = AST_CONTROL_STREAM_FORWARD;
+ break;
+ }
+
+ if (frame_type == -1) {
+ /* Invalid operation. Tsk, tsk. */
+ return STASIS_PLAYBACK_OPER_FAILED;
+ }
+
+ res = stasis_app_control_queue_control(playback->control, frame_type);
+ return res ? STASIS_PLAYBACK_OPER_FAILED : STASIS_PLAYBACK_OPER_OK;
}
static int load_module(void)
Modified: team/dlee/playback-controls/res/stasis/control.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/res/stasis/control.c?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/res/stasis/control.c (original)
+++ team/dlee/playback-controls/res/stasis/control.c Mon May 13 14:24:00 2013
@@ -175,6 +175,12 @@
stasis_publish(ast_channel_topic(control->channel), message);
}
+int stasis_app_control_queue_control(struct stasis_app_control *control,
+ enum ast_control_frame_type frame_type)
+{
+ return ast_queue_control(control->channel, frame_type);
+}
+
int control_dispatch_all(struct stasis_app_control *control,
struct ast_channel *chan)
{
Modified: team/dlee/playback-controls/res/stasis_http/resource_playback.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/res/stasis_http/resource_playback.c?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/res/stasis_http/resource_playback.c (original)
+++ team/dlee/playback-controls/res/stasis_http/resource_playback.c Mon May 13 14:24:00 2013
@@ -34,7 +34,9 @@
struct ast_get_playback_args *args,
struct stasis_http_response *response)
{
- RAII_VAR(struct ast_json *, playback, NULL, ast_json_unref);
+ RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+
playback = stasis_app_playback_find_by_id(args->playback_id);
if (playback == NULL) {
stasis_http_response_error(response, 404, "Not Found",
@@ -42,13 +44,94 @@
return;
}
- stasis_http_response_ok(response, ast_json_ref(playback));
+ json = stasis_app_playback_to_json(playback);
+ if (json == NULL) {
+ stasis_http_response_error(response, 500,
+ "Internal Server Error", "Error building response");
+ return;
+ }
+
+ stasis_http_response_ok(response, ast_json_ref(json));
}
-void stasis_http_stop_playback(struct ast_variable *headers, struct ast_stop_playback_args *args, struct stasis_http_response *response)
+void stasis_http_stop_playback(struct ast_variable *headers,
+ struct ast_stop_playback_args *args,
+ struct stasis_http_response *response)
{
- ast_log(LOG_ERROR, "TODO: stasis_http_stop_playback\n");
+ RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
+ enum stasis_playback_oper_results res;
+
+ playback = stasis_app_playback_find_by_id(args->playback_id);
+ if (playback == NULL) {
+ stasis_http_response_error(response, 404, "Not Found",
+ "Playback not found");
+ return;
+ }
+
+ res = stasis_app_playback_operation(playback, STASIS_PLAYBACK_STOP);
+
+ switch (res) {
+ case STASIS_PLAYBACK_OPER_OK:
+ stasis_http_response_no_content(response);
+ return;
+ case STASIS_PLAYBACK_OPER_FAILED:
+ stasis_http_response_error(response, 500,
+ "Internal Server Error", "Could not stop playback");
+ return;
+ case STASIS_PLAYBACK_OPER_NOT_PLAYING:
+ /* Stop operation should be valid even when not playing */
+ ast_assert(0);
+ stasis_http_response_error(response, 500,
+ "Internal Server Error", "Could not stop playback");
+ return;
+ }
}
-void stasis_http_control_playback(struct ast_variable *headers, struct ast_control_playback_args *args, struct stasis_http_response *response)
+void stasis_http_control_playback(struct ast_variable *headers,
+ struct ast_control_playback_args *args,
+ struct stasis_http_response *response)
{
- ast_log(LOG_ERROR, "TODO: stasis_http_control_playback\n");
+ RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
+ enum stasis_app_playback_media_operation oper;
+ enum stasis_playback_oper_results res;
+
+ if (strcmp(args->operation, "play") == 0) {
+ oper = STASIS_PLAYBACK_PLAY;
+ } else if (strcmp(args->operation, "pause") == 0) {
+ oper = STASIS_PLAYBACK_PAUSE;
+ } else if (strcmp(args->operation, "rewind") == 0) {
+ oper = STASIS_PLAYBACK_REWIND;
+ } else if (strcmp(args->operation, "fast-forward") == 0) {
+ oper = STASIS_PLAYBACK_FAST_FORWARD;
+ } else {
+ stasis_http_response_error(response, 400,
+ "Bad Request", "Invalid operation %s",
+ args->operation);
+ return;
+
+ }
+
+ playback = stasis_app_playback_find_by_id(args->playback_id);
+ if (playback == NULL) {
+ stasis_http_response_error(response, 404, "Not Found",
+ "Playback not found");
+ return;
+ }
+
+ res = stasis_app_playback_operation(playback, oper);
+
+ switch (res) {
+ case STASIS_PLAYBACK_OPER_OK:
+ stasis_http_response_no_content(response);
+ return;
+ case STASIS_PLAYBACK_OPER_FAILED:
+ stasis_http_response_error(response, 500,
+ "Internal Server Error", "Could not %s playback",
+ args->operation);
+ return;
+ case STASIS_PLAYBACK_OPER_NOT_PLAYING:
+ /* Stop operation should be valid even when not playing */
+ ast_assert(0);
+ stasis_http_response_error(response, 409, "Conflict",
+ "Can only %s while media is playing", args->operation);
+ return;
+ }
}
Modified: team/dlee/playback-controls/rest-api/api-docs/playback.json
URL: http://svnview.digium.com/svn/asterisk/team/dlee/playback-controls/rest-api/api-docs/playback.json?view=diff&rev=388577&r1=388576&r2=388577
==============================================================================
--- team/dlee/playback-controls/rest-api/api-docs/playback.json (original)
+++ team/dlee/playback-controls/rest-api/api-docs/playback.json Mon May 13 14:24:00 2013
@@ -76,13 +76,25 @@
"play",
"pause",
"rewind",
- "fast-forward",
- "speed-up",
- "slow-down"
+ "fast-forward"
]
}
}
- ]
+ ],
+ "errorResponses": [
+ {
+ "code": 400,
+ "reason": "The provided operation parameter was invalid"
+ },
+ {
+ "code": 404,
+ "reason": "The playback cannot be found"
+ },
+ {
+ "code": 409,
+ "reason": "The operation cannot be performed in the playback's current state"
+ }
+]
}
]
}
More information about the asterisk-commits
mailing list