[asterisk-commits] dlee: trunk r389587 - in /trunk: include/asterisk/ main/ res/ res/stasis/ res...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu May 23 15:11:40 CDT 2013
Author: dlee
Date: Thu May 23 15:11:35 2013
New Revision: 389587
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389587
Log:
This patch implements the REST API's for POST /channels/{channelId}/play
and GET /playback/{playbackId}.
This allows an external application to initiate playback of a sound on a
channel while the channel is in the Stasis application.
/play commands are issued asynchronously, and return immediately with
the URL of the associated /playback resource. Playback commands queue up,
playing in succession. The /playback resource shows the state of a
playback operation as enqueued, playing or complete. (Although the
operation will only be in the 'complete' state for a very short time,
since it is almost immediately freed up).
(closes issue ASTERISK-21283)
(closes issue ASTERISK-21586)
Review: https://reviewboard.asterisk.org/r/2531/
Added:
trunk/include/asterisk/stasis_app_playback.h
- copied unchanged from r389585, team/dlee/playback-rebase/include/asterisk/stasis_app_playback.h
trunk/res/res_stasis_playback.c
- copied unchanged from r389585, team/dlee/playback-rebase/res/res_stasis_playback.c
trunk/res/res_stasis_playback.exports.in
- copied unchanged from r389585, team/dlee/playback-rebase/res/res_stasis_playback.exports.in
Modified:
trunk/include/asterisk/app.h
trunk/include/asterisk/stasis_channels.h
trunk/include/asterisk/stasis_http.h
trunk/main/channel_internal_api.c
trunk/main/stasis_channels.c
trunk/res/res_stasis_http.c
trunk/res/res_stasis_http_channels.c
trunk/res/res_stasis_json_events.c
trunk/res/res_stasis_json_events.exports.in
trunk/res/stasis/control.c
trunk/res/stasis_http/resource_channels.c
trunk/res/stasis_http/resource_channels.h
trunk/res/stasis_http/resource_playback.c
trunk/res/stasis_json/resource_channels.h
trunk/res/stasis_json/resource_events.h
trunk/rest-api/api-docs/channels.json
trunk/rest-api/api-docs/events.json
Modified: trunk/include/asterisk/app.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/app.h?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/include/asterisk/app.h (original)
+++ trunk/include/asterisk/app.h Thu May 23 15:11:35 2013
@@ -636,14 +636,19 @@
/*!
* \brief Stream a file with fast forward, pause, reverse, restart.
- * \param chan
- * \param file filename
- * \param fwd, rev, stop, pause, restart, skipms, offsetms
+ * \param chan Channel
+ * \param file File to play.
+ * \param fwd, rev, stop, pause, restart DTMF keys for media control
+ * \param skipms Number of milliseconds to skip for fwd/rev.
+ * \param offsetms Number of milliseconds to skip when starting the media.
*
* Before calling this function, set this to be the number
* of ms to start from the beginning of the file. When the function
* returns, it will be the number of ms from the beginning where the
* playback stopped. Pass NULL if you don't care.
+ *
+ * \retval 0 on success
+ * \retval Non-zero on failure
*/
int ast_control_streamfile(struct ast_channel *chan, const char *file, const char *fwd, const char *rev, const char *stop, const char *pause, const char *restart, int skipms, long *offsetms);
Modified: trunk/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/stasis_channels.h?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/include/asterisk/stasis_channels.h (original)
+++ trunk/include/asterisk/stasis_channels.h Thu May 23 15:11:35 2013
@@ -54,6 +54,7 @@
AST_STRING_FIELD(caller_number); /*!< Caller ID Number */
AST_STRING_FIELD(connected_name); /*!< Connected Line Name */
AST_STRING_FIELD(connected_number); /*!< Connected Line Number */
+ AST_STRING_FIELD(language); /*!< The default spoken language for the channel */
);
struct timeval creationtime; /*!< The time of channel creation */
@@ -124,6 +125,17 @@
/*!
* \since 12
+ * \brief Get the most recent snapshot for channel with the given \a uniqueid.
+ *
+ * \param uniqueid Uniqueid of the snapshot to fetch.
+ * \return Most recent channel snapshot
+ * \return \c NULL on error
+ */
+struct ast_channel_snapshot *ast_channel_snapshot_get_latest(
+ const char *uniqueid);
+
+/*!
+ * \since 12
* \brief Creates a \ref ast_channel_blob message.
*
* The given \a blob should be treated as immutable and not modified after it is
@@ -139,6 +151,23 @@
*/
struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
struct stasis_message_type *type, struct ast_json *blob);
+
+/*!
+ * \since 12
+ * \brief Create a \ref ast_channel_blob message, pulling channel state from
+ * the cache.
+ *
+ * \param uniqueid Uniqueid of the channel.
+ * \param type Message type for this blob.
+ * \param blob JSON object representing the data, or \c NULL for no data. If
+ * \c NULL, ast_json_null() is put into the object.
+ *
+ * \return \ref ast_channel_blob message.
+ * \return \c NULL on error
+ */
+struct stasis_message *ast_channel_blob_create_from_cache(
+ const char *uniqueid, struct stasis_message_type *type,
+ struct ast_json *blob);
/*!
* \since 12
@@ -220,6 +249,14 @@
*/
void ast_multi_channel_blob_add_channel(struct ast_multi_channel_blob *obj,
const char *role, struct ast_channel_snapshot *snapshot);
+
+/*!
+ * \since 12
+ * \brief Publish a \ref ast_channel_snapshot for a channel.
+ *
+ * \param chan Channel to publish.
+ */
+void ast_channel_publish_snapshot(struct ast_channel *chan);
/*!
* \since 12
Modified: trunk/include/asterisk/stasis_http.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/stasis_http.h?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/include/asterisk/stasis_http.h (original)
+++ trunk/include/asterisk/stasis_http.h Thu May 23 15:11:35 2013
@@ -163,6 +163,12 @@
void stasis_http_response_no_content(struct stasis_http_response *response);
/*!
+ * \brief Fill in a <tt>Created</tt> (201) \a stasis_http_response.
+ */
+void stasis_http_response_created(struct stasis_http_response *response,
+ const char *url);
+
+/*!
* \brief Fill in \a response with a 500 message for allocation failures.
* \param response Response to fill in.
*/
Modified: trunk/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel_internal_api.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/main/channel_internal_api.c (original)
+++ trunk/main/channel_internal_api.c Thu May 23 15:11:35 2013
@@ -414,15 +414,17 @@
/* ACCESSORS */
-#define DEFINE_STRINGFIELD_SETTERS_FOR(field) \
+#define DEFINE_STRINGFIELD_SETTERS_FOR(field, publish) \
void ast_channel_##field##_set(struct ast_channel *chan, const char *value) \
{ \
ast_string_field_set(chan, field, value); \
+ if (publish) ast_channel_publish_snapshot(chan); \
} \
\
void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) \
{ \
ast_string_field_build_va(chan, field, fmt, ap); \
+ if (publish) ast_channel_publish_snapshot(chan); \
} \
void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) \
{ \
@@ -430,19 +432,20 @@
va_start(ap, fmt); \
ast_channel_##field##_build_va(chan, fmt, ap); \
va_end(ap); \
-}
-
-DEFINE_STRINGFIELD_SETTERS_FOR(name);
-DEFINE_STRINGFIELD_SETTERS_FOR(language);
-DEFINE_STRINGFIELD_SETTERS_FOR(musicclass);
-DEFINE_STRINGFIELD_SETTERS_FOR(accountcode);
-DEFINE_STRINGFIELD_SETTERS_FOR(peeraccount);
-DEFINE_STRINGFIELD_SETTERS_FOR(userfield);
-DEFINE_STRINGFIELD_SETTERS_FOR(call_forward);
-DEFINE_STRINGFIELD_SETTERS_FOR(uniqueid);
-DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot);
-DEFINE_STRINGFIELD_SETTERS_FOR(hangupsource);
-DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext);
+ if (publish) ast_channel_publish_snapshot(chan); \
+}
+
+DEFINE_STRINGFIELD_SETTERS_FOR(name, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(language, 1);
+DEFINE_STRINGFIELD_SETTERS_FOR(musicclass, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(accountcode, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(peeraccount, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(userfield, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(call_forward, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(uniqueid, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(hangupsource, 0);
+DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0);
#define DEFINE_STRINGFIELD_GETTER_FOR(field) const char *ast_channel_##field(const struct ast_channel *chan) \
{ \
Modified: trunk/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/stasis_channels.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/main/stasis_channels.c (original)
+++ trunk/main/stasis_channels.c Thu May 23 15:11:35 2013
@@ -134,6 +134,7 @@
S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
ast_string_field_set(snapshot, connected_number,
S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
+ ast_string_field_set(snapshot, language, ast_channel_language(chan));
snapshot->creationtime = ast_channel_creationtime(chan);
snapshot->state = ast_channel_state(chan);
@@ -149,6 +150,28 @@
return snapshot;
}
+struct ast_channel_snapshot *ast_channel_snapshot_get_latest(
+ const char *uniqueid)
+{
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct ast_channel_snapshot *snapshot;
+
+ msg = stasis_cache_get(ast_channel_topic_all_cached(),
+ ast_channel_snapshot_type(), uniqueid);
+
+ if (!msg) {
+ return NULL;
+ }
+
+ snapshot = stasis_message_data(msg);
+ if (!snapshot) {
+ return NULL;
+ }
+
+ ao2_ref(snapshot, +1);
+ return snapshot;
+}
+
static void publish_message_for_channel_topics(struct stasis_message *message, struct ast_channel *chan)
{
if (chan) {
@@ -207,37 +230,65 @@
publish_message_for_channel_topics(msg, caller);
}
+static struct stasis_message *channel_blob_create(
+ struct ast_channel_snapshot *snapshot,
+ struct stasis_message_type *type, struct ast_json *blob)
+{
+ RAII_VAR(struct ast_channel_blob *, obj, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+ if (blob == NULL) {
+ blob = ast_json_null();
+ }
+
+ obj = ao2_alloc(sizeof(*obj), channel_blob_dtor);
+ if (!obj) {
+ return NULL;
+ }
+
+ if (snapshot) {
+ ao2_ref(snapshot, +1);
+ obj->snapshot = snapshot;
+ }
+
+ obj->blob = ast_json_ref(blob);
+
+ msg = stasis_message_create(type, obj);
+ if (!msg) {
+ return NULL;
+ }
+
+ ao2_ref(msg, +1);
+ return msg;
+}
+
struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
struct stasis_message_type *type, struct ast_json *blob)
{
- RAII_VAR(struct ast_channel_blob *, obj, NULL, ao2_cleanup);
- RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
-
- if (blob == NULL) {
- blob = ast_json_null();
- }
-
- obj = ao2_alloc(sizeof(*obj), channel_blob_dtor);
- if (!obj) {
- return NULL;
- }
-
- if (chan) {
- obj->snapshot = ast_channel_snapshot_create(chan);
- if (obj->snapshot == NULL) {
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+
+ if (chan != NULL) {
+ snapshot = ast_channel_snapshot_create(chan);
+ if (snapshot == NULL) {
return NULL;
}
}
- obj->blob = ast_json_ref(blob);
-
- msg = stasis_message_create(type, obj);
- if (!msg) {
- return NULL;
- }
-
- ao2_ref(msg, +1);
- return msg;
+ return channel_blob_create(snapshot, type, blob);
+}
+
+struct stasis_message *ast_channel_blob_create_from_cache(
+ const char *uniqueid, struct stasis_message_type *type,
+ struct ast_json *blob)
+{
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+
+ snapshot = ast_channel_snapshot_get_latest(uniqueid);
+ if (snapshot == NULL) {
+ return NULL;
+ }
+
+ return channel_blob_create(snapshot, type, blob);
}
/*! \brief A channel snapshot wrapper object used in \ref ast_multi_channel_blob objects */
@@ -388,6 +439,26 @@
}
return obj->blob;
}
+
+void ast_channel_publish_snapshot(struct ast_channel *chan)
+{
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+
+ snapshot = ast_channel_snapshot_create(chan);
+ if (!snapshot) {
+ return;
+ }
+
+ message = stasis_message_create(ast_channel_snapshot_type(), snapshot);
+ if (!message) {
+ return;
+ }
+
+ ast_assert(ast_channel_topic(chan) != NULL);
+ stasis_publish(ast_channel_topic(chan), message);
+}
+
void ast_channel_publish_varset(struct ast_channel *chan, const char *name, const char *value)
{
Modified: trunk/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_stasis_http.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/res_stasis_http.c (original)
+++ trunk/res/res_stasis_http.c Thu May 23 15:11:35 2013
@@ -328,6 +328,15 @@
response->message = ast_json_ref(alloc_failed_message);
response->response_code = 500;
response->response_text = "Internal Server Error";
+}
+
+void stasis_http_response_created(struct stasis_http_response *response,
+ const char *url)
+{
+ response->message = ast_json_null();
+ response->response_code = 201;
+ response->response_text = "Created";
+ ast_str_append(&response->headers, 0, "Location: %s\r\n", url);
}
static void add_allow_header(struct stasis_rest_handlers *handler,
Modified: trunk/res/res_stasis_http_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_stasis_http_channels.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/res_stasis_http_channels.c (original)
+++ trunk/res/res_stasis_http_channels.c Thu May 23 15:11:35 2013
@@ -327,6 +327,9 @@
if (strcmp(i->name, "media") == 0) {
args.media = (i->value);
} else
+ if (strcmp(i->name, "lang") == 0) {
+ args.lang = (i->value);
+ } else
{}
}
for (i = path_vars; i; i = i->next) {
Modified: trunk/res/res_stasis_json_events.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_stasis_json_events.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/res_stasis_json_events.c (original)
+++ trunk/res/res_stasis_json_events.c Thu May 23 15:11:35 2013
@@ -116,6 +116,210 @@
return ast_json_ref(message);
}
+struct ast_json *stasis_json_event_playback_finished_create(
+ struct ast_json *blob
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ struct ast_json *validator;
+
+ ast_assert(blob != NULL);
+ ast_assert(ast_json_object_get(blob, "type") == NULL);
+
+ validator = ast_json_object_get(blob, "playback");
+ if (validator) {
+ /* do validation? XXX */
+ } else {
+ /* fail message generation if the required parameter doesn't exist */
+ return NULL;
+ }
+
+ event = ast_json_deep_copy(blob);
+ if (!event) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "playback_finished", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
+struct ast_json *stasis_json_event_channel_snapshot_create(
+ struct ast_channel_snapshot *channel_snapshot
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ int ret;
+
+ ast_assert(channel_snapshot != NULL);
+
+ event = ast_json_object_create();
+ if (!event) {
+ return NULL;
+ }
+
+ ret = ast_json_object_set(event,
+ "channel", ast_channel_snapshot_to_json(channel_snapshot));
+ if (ret) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "channel_snapshot", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
+struct ast_json *stasis_json_event_channel_caller_id_create(
+ struct ast_channel_snapshot *channel_snapshot,
+ struct ast_json *blob
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ struct ast_json *validator;
+ int ret;
+
+ ast_assert(channel_snapshot != NULL);
+ ast_assert(blob != NULL);
+ ast_assert(ast_json_object_get(blob, "channel") == NULL);
+ ast_assert(ast_json_object_get(blob, "type") == NULL);
+
+ validator = ast_json_object_get(blob, "caller_presentation_txt");
+ if (validator) {
+ /* do validation? XXX */
+ } else {
+ /* fail message generation if the required parameter doesn't exist */
+ return NULL;
+ }
+
+ validator = ast_json_object_get(blob, "caller_presentation");
+ if (validator) {
+ /* do validation? XXX */
+ } else {
+ /* fail message generation if the required parameter doesn't exist */
+ return NULL;
+ }
+
+ event = ast_json_deep_copy(blob);
+ if (!event) {
+ return NULL;
+ }
+
+ ret = ast_json_object_set(event,
+ "channel", ast_channel_snapshot_to_json(channel_snapshot));
+ if (ret) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "channel_caller_id", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
+struct ast_json *stasis_json_event_playback_started_create(
+ struct ast_json *blob
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ struct ast_json *validator;
+
+ ast_assert(blob != NULL);
+ ast_assert(ast_json_object_get(blob, "type") == NULL);
+
+ validator = ast_json_object_get(blob, "playback");
+ if (validator) {
+ /* do validation? XXX */
+ } else {
+ /* fail message generation if the required parameter doesn't exist */
+ return NULL;
+ }
+
+ event = ast_json_deep_copy(blob);
+ if (!event) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "playback_started", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
+struct ast_json *stasis_json_event_bridge_destroyed_create(
+ struct ast_bridge_snapshot *bridge_snapshot
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ int ret;
+
+ ast_assert(bridge_snapshot != NULL);
+
+ event = ast_json_object_create();
+ if (!event) {
+ return NULL;
+ }
+
+ ret = ast_json_object_set(event,
+ "bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
+ if (ret) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "bridge_destroyed", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
+struct ast_json *stasis_json_event_application_replaced_create(
+ struct ast_json *blob
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ struct ast_json *validator;
+
+ ast_assert(blob != NULL);
+ ast_assert(ast_json_object_get(blob, "type") == NULL);
+
+ validator = ast_json_object_get(blob, "application");
+ if (validator) {
+ /* do validation? XXX */
+ } else {
+ /* fail message generation if the required parameter doesn't exist */
+ return NULL;
+ }
+
+ event = ast_json_deep_copy(blob);
+ if (!event) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "application_replaced", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
struct ast_json *stasis_json_event_channel_destroyed_create(
struct ast_channel_snapshot *channel_snapshot,
struct ast_json *blob
@@ -159,190 +363,6 @@
}
message = ast_json_pack("{s: o}", "channel_destroyed", ast_json_ref(event));
- if (!message) {
- return NULL;
- }
-
- return ast_json_ref(message);
-}
-
-struct ast_json *stasis_json_event_channel_snapshot_create(
- struct ast_channel_snapshot *channel_snapshot
- )
-{
- RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
- int ret;
-
- ast_assert(channel_snapshot != NULL);
-
- event = ast_json_object_create();
- if (!event) {
- return NULL;
- }
-
- ret = ast_json_object_set(event,
- "channel", ast_channel_snapshot_to_json(channel_snapshot));
- if (ret) {
- return NULL;
- }
-
- message = ast_json_pack("{s: o}", "channel_snapshot", ast_json_ref(event));
- if (!message) {
- return NULL;
- }
-
- return ast_json_ref(message);
-}
-
-struct ast_json *stasis_json_event_channel_caller_id_create(
- struct ast_channel_snapshot *channel_snapshot,
- struct ast_json *blob
- )
-{
- RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
- struct ast_json *validator;
- int ret;
-
- ast_assert(channel_snapshot != NULL);
- ast_assert(blob != NULL);
- ast_assert(ast_json_object_get(blob, "channel") == NULL);
- ast_assert(ast_json_object_get(blob, "type") == NULL);
-
- validator = ast_json_object_get(blob, "caller_presentation_txt");
- if (validator) {
- /* do validation? XXX */
- } else {
- /* fail message generation if the required parameter doesn't exist */
- return NULL;
- }
-
- validator = ast_json_object_get(blob, "caller_presentation");
- if (validator) {
- /* do validation? XXX */
- } else {
- /* fail message generation if the required parameter doesn't exist */
- return NULL;
- }
-
- event = ast_json_deep_copy(blob);
- if (!event) {
- return NULL;
- }
-
- ret = ast_json_object_set(event,
- "channel", ast_channel_snapshot_to_json(channel_snapshot));
- if (ret) {
- return NULL;
- }
-
- message = ast_json_pack("{s: o}", "channel_caller_id", ast_json_ref(event));
- if (!message) {
- return NULL;
- }
-
- return ast_json_ref(message);
-}
-
-struct ast_json *stasis_json_event_channel_hangup_request_create(
- struct ast_channel_snapshot *channel_snapshot,
- struct ast_json *blob
- )
-{
- RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
- struct ast_json *validator;
- int ret;
-
- ast_assert(channel_snapshot != NULL);
- ast_assert(blob != NULL);
- ast_assert(ast_json_object_get(blob, "channel") == NULL);
- ast_assert(ast_json_object_get(blob, "type") == NULL);
-
- validator = ast_json_object_get(blob, "soft");
- if (validator) {
- /* do validation? XXX */
- }
-
- validator = ast_json_object_get(blob, "cause");
- if (validator) {
- /* do validation? XXX */
- }
-
- event = ast_json_deep_copy(blob);
- if (!event) {
- return NULL;
- }
-
- ret = ast_json_object_set(event,
- "channel", ast_channel_snapshot_to_json(channel_snapshot));
- if (ret) {
- return NULL;
- }
-
- message = ast_json_pack("{s: o}", "channel_hangup_request", ast_json_ref(event));
- if (!message) {
- return NULL;
- }
-
- return ast_json_ref(message);
-}
-
-struct ast_json *stasis_json_event_bridge_destroyed_create(
- struct ast_bridge_snapshot *bridge_snapshot
- )
-{
- RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
- int ret;
-
- ast_assert(bridge_snapshot != NULL);
-
- event = ast_json_object_create();
- if (!event) {
- return NULL;
- }
-
- ret = ast_json_object_set(event,
- "bridge", ast_bridge_snapshot_to_json(bridge_snapshot));
- if (ret) {
- return NULL;
- }
-
- message = ast_json_pack("{s: o}", "bridge_destroyed", ast_json_ref(event));
- if (!message) {
- return NULL;
- }
-
- return ast_json_ref(message);
-}
-
-struct ast_json *stasis_json_event_application_replaced_create(
- struct ast_json *blob
- )
-{
- RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
- struct ast_json *validator;
-
- ast_assert(blob != NULL);
- ast_assert(ast_json_object_get(blob, "type") == NULL);
-
- validator = ast_json_object_get(blob, "application");
- if (validator) {
- /* do validation? XXX */
- } else {
- /* fail message generation if the required parameter doesn't exist */
- return NULL;
- }
-
- event = ast_json_deep_copy(blob);
- if (!event) {
- return NULL;
- }
-
- message = ast_json_pack("{s: o}", "application_replaced", ast_json_ref(event));
if (!message) {
return NULL;
}
@@ -580,6 +600,50 @@
}
message = ast_json_pack("{s: o}", "channel_state_change", ast_json_ref(event));
+ if (!message) {
+ return NULL;
+ }
+
+ return ast_json_ref(message);
+}
+
+struct ast_json *stasis_json_event_channel_hangup_request_create(
+ struct ast_channel_snapshot *channel_snapshot,
+ struct ast_json *blob
+ )
+{
+ RAII_VAR(struct ast_json *, message, NULL, ast_json_unref);
+ RAII_VAR(struct ast_json *, event, NULL, ast_json_unref);
+ struct ast_json *validator;
+ int ret;
+
+ ast_assert(channel_snapshot != NULL);
+ ast_assert(blob != NULL);
+ ast_assert(ast_json_object_get(blob, "channel") == NULL);
+ ast_assert(ast_json_object_get(blob, "type") == NULL);
+
+ validator = ast_json_object_get(blob, "soft");
+ if (validator) {
+ /* do validation? XXX */
+ }
+
+ validator = ast_json_object_get(blob, "cause");
+ if (validator) {
+ /* do validation? XXX */
+ }
+
+ event = ast_json_deep_copy(blob);
+ if (!event) {
+ return NULL;
+ }
+
+ ret = ast_json_object_set(event,
+ "channel", ast_channel_snapshot_to_json(channel_snapshot));
+ if (ret) {
+ return NULL;
+ }
+
+ message = ast_json_pack("{s: o}", "channel_hangup_request", ast_json_ref(event));
if (!message) {
return NULL;
}
Modified: trunk/res/res_stasis_json_events.exports.in
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_stasis_json_events.exports.in?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/res_stasis_json_events.exports.in (original)
+++ trunk/res/res_stasis_json_events.exports.in Thu May 23 15:11:35 2013
@@ -2,18 +2,20 @@
global:
LINKER_SYMBOL_PREFIXstasis_json_event_channel_userevent_create;
LINKER_SYMBOL_PREFIXstasis_json_event_bridge_created_create;
- LINKER_SYMBOL_PREFIXstasis_json_event_channel_destroyed_create;
+ LINKER_SYMBOL_PREFIXstasis_json_event_playback_finished_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_snapshot_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_caller_id_create;
- LINKER_SYMBOL_PREFIXstasis_json_event_channel_hangup_request_create;
+ LINKER_SYMBOL_PREFIXstasis_json_event_playback_started_create;
LINKER_SYMBOL_PREFIXstasis_json_event_bridge_destroyed_create;
LINKER_SYMBOL_PREFIXstasis_json_event_application_replaced_create;
+ LINKER_SYMBOL_PREFIXstasis_json_event_channel_destroyed_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_varset_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_left_bridge_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_created_create;
LINKER_SYMBOL_PREFIXstasis_json_event_stasis_start_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_dialplan_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_state_change_create;
+ LINKER_SYMBOL_PREFIXstasis_json_event_channel_hangup_request_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_entered_bridge_create;
LINKER_SYMBOL_PREFIXstasis_json_event_channel_dtmf_received_create;
LINKER_SYMBOL_PREFIXstasis_json_event_stasis_end_create;
Modified: trunk/res/stasis/control.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis/control.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/stasis/control.c (original)
+++ trunk/res/stasis/control.c Thu May 23 15:11:35 2013
@@ -56,7 +56,8 @@
return NULL;
}
- control->command_queue = ao2_container_alloc_list(0, 0, NULL, NULL);
+ control->command_queue = ao2_container_alloc_list(
+ AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
control->channel = channel;
@@ -75,10 +76,8 @@
return NULL;
}
- ao2_lock(control);
- ao2_ref(command, +1);
+ /* command_queue is a thread safe list; no lock needed */
ao2_link(control->command_queue, command);
- ao2_unlock(control);
ao2_ref(command, +1);
return command;
@@ -182,8 +181,6 @@
struct ao2_iterator i;
void *obj;
- SCOPED_AO2LOCK(lock, control);
-
ast_assert(control->channel == chan);
i = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
Modified: trunk/res/stasis_http/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_http/resource_channels.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/stasis_http/resource_channels.c (original)
+++ trunk/res/stasis_http/resource_channels.c Thu May 23 15:11:35 2013
@@ -24,6 +24,7 @@
*/
/*** MODULEINFO
+ <depend type="module">res_stasis_app_playback</depend>
<support_level>core</support_level>
***/
@@ -31,9 +32,13 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/file.h"
#include "asterisk/stasis_app.h"
+#include "asterisk/stasis_app_playback.h"
#include "asterisk/stasis_channels.h"
#include "resource_channels.h"
+
+#include <limits.h>
/*!
* \brief Finds the control object for a channel, filling the response with an
@@ -131,9 +136,53 @@
{
ast_log(LOG_ERROR, "TODO: stasis_http_unhold_channel\n");
}
-void stasis_http_play_on_channel(struct ast_variable *headers, struct ast_play_on_channel_args *args, struct stasis_http_response *response)
-{
- ast_log(LOG_ERROR, "TODO: stasis_http_play_on_channel\n");
+
+void stasis_http_play_on_channel(struct ast_variable *headers,
+ struct ast_play_on_channel_args *args,
+ struct stasis_http_response *response)
+{
+ RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+ RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
+ RAII_VAR(char *, playback_url, NULL, ast_free);
+ const char *language;
+
+ ast_assert(response != NULL);
+
+ control = find_control(response, args->channel_id);
+ if (control == NULL) {
+ /* Response filled in by find_control */
+ return;
+ }
+
+ snapshot = stasis_app_control_get_snapshot(control);
+ if (!snapshot) {
+ stasis_http_response_error(
+ response, 404, "Not Found",
+ "Channel not found");
+ return;
+ }
+
+ language = S_OR(args->lang, snapshot->language);
+
+ playback = stasis_app_control_play_uri(control, args->media, language);
+ if (!playback) {
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Failed to answer channel");
+ return;
+ }
+
+ ast_asprintf(&playback_url, "/playback/%s",
+ stasis_app_playback_get_id(playback));
+ if (!playback_url) {
+ stasis_http_response_error(
+ response, 500, "Internal Server Error",
+ "Out of memory");
+ return;
+ }
+
+ stasis_http_response_created(response, playback_url);
}
void stasis_http_record_channel(struct ast_variable *headers, struct ast_record_channel_args *args, struct stasis_http_response *response)
{
@@ -143,8 +192,8 @@
struct ast_get_channel_args *args,
struct stasis_http_response *response)
{
- RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+ struct stasis_caching_topic *caching_topic;
struct ast_channel_snapshot *snapshot;
caching_topic = ast_channel_topic_all_cached();
@@ -154,7 +203,6 @@
"Message bus not initialized");
return;
}
- ao2_ref(caching_topic, +1);
msg = stasis_cache_get(caching_topic, ast_channel_snapshot_type(),
args->channel_id);
Modified: trunk/res/stasis_http/resource_channels.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_http/resource_channels.h?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/stasis_http/resource_channels.h (original)
+++ trunk/res/stasis_http/resource_channels.h Thu May 23 15:11:35 2013
@@ -200,6 +200,8 @@
const char *channel_id;
/*! \brief Media's URI to play. */
const char *media;
+ /*! \brief For sounds, selects language for sound */
+ const char *lang;
};
/*!
* \brief Start playback of media.
Modified: trunk/res/stasis_http/resource_playback.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_http/resource_playback.c?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/stasis_http/resource_playback.c (original)
+++ trunk/res/stasis_http/resource_playback.c Thu May 23 15:11:35 2013
@@ -27,11 +27,22 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/stasis_app_playback.h"
#include "resource_playback.h"
-void stasis_http_get_playback(struct ast_variable *headers, struct ast_get_playback_args *args, struct stasis_http_response *response)
+void stasis_http_get_playback(struct ast_variable *headers,
+ struct ast_get_playback_args *args,
+ struct stasis_http_response *response)
{
- ast_log(LOG_ERROR, "TODO: stasis_http_get_playback\n");
+ RAII_VAR(struct ast_json *, playback, 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",
+ "Playback not found");
+ return;
+ }
+
+ stasis_http_response_ok(response, ast_json_ref(playback));
}
void stasis_http_stop_playback(struct ast_variable *headers, struct ast_stop_playback_args *args, struct stasis_http_response *response)
{
Modified: trunk/res/stasis_json/resource_channels.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_json/resource_channels.h?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/stasis_json/resource_channels.h (original)
+++ trunk/res/stasis_json/resource_channels.h Thu May 23 15:11:35 2013
@@ -40,7 +40,17 @@
/*
* JSON models
*
+ * CallerID
+ * - name: string (required)
+ * - number: string (required)
+ * Dialed
* Originated
+ * Playback
+ * - language: string
+ * - media_uri: string (required)
+ * - id: string (required)
+ * - target_uri: string (required)
+ * - state: string (required)
* DialplanCEP
* - priority: long (required)
* - exten: string (required)
@@ -61,10 +71,6 @@
* - hangupsource: string (required)
* - dialplan: DialplanCEP (required)
* - data: string (required)
- * CallerID
- * - name: string (required)
- * - number: string (required)
- * Dialed
*/
#endif /* _ASTERISK_RESOURCE_CHANNELS_H */
Modified: trunk/res/stasis_json/resource_events.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_json/resource_events.h?view=diff&rev=389587&r1=389586&r2=389587
==============================================================================
--- trunk/res/stasis_json/resource_events.h (original)
+++ trunk/res/stasis_json/resource_events.h Thu May 23 15:11:35 2013
@@ -68,6 +68,85 @@
);
/*!
+ * \brief Event showing the completion of a media playback operation.
+ *
+ * \param blob JSON blob containing the following parameters:
+ * - playback: Playback - Playback control object (required)
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_playback_finished_create(
+ struct ast_json *blob
+ );
+
+/*!
+ * \brief Some part of channel state changed.
+ *
+ * \param channel The channel to be used to generate this event
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_channel_snapshot_create(
+ struct ast_channel_snapshot *channel_snapshot
+ );
+
+/*!
+ * \brief Channel changed Caller ID.
+ *
+ * \param channel The channel that changed Caller ID.
+ * \param blob JSON blob containing the following parameters:
+ * - caller_presentation_txt: string - The text representation of the Caller Presentation value. (required)
+ * - caller_presentation: integer - The integer representation of the Caller Presentation value. (required)
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_channel_caller_id_create(
+ struct ast_channel_snapshot *channel_snapshot,
+ struct ast_json *blob
+ );
+
+/*!
+ * \brief Event showing the start of a media playback operation.
+ *
+ * \param blob JSON blob containing the following parameters:
+ * - playback: Playback - Playback control object (required)
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_playback_started_create(
+ struct ast_json *blob
+ );
+
+/*!
+ * \brief Notification that a bridge has been destroyed.
+ *
+ * \param bridge The bridge to be used to generate this event
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_bridge_destroyed_create(
+ struct ast_bridge_snapshot *bridge_snapshot
+ );
+
+/*!
+ * \brief Notification that another WebSocket has taken over for an application.
+ *
+ * \param blob JSON blob containing the following parameters:
+ * - application: string (required)
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_application_replaced_create(
+ struct ast_json *blob
+ );
+
+/*!
* \brief Notification that a channel has been destroyed.
*
* \param channel The channel to be used to generate this event
@@ -84,31 +163,88 @@
);
/*!
- * \brief Some part of channel state changed.
- *
- * \param channel The channel to be used to generate this event
- *
- * \retval NULL on error
- * \retval JSON (ast_json) describing the event
- */
-struct ast_json *stasis_json_event_channel_snapshot_create(
- struct ast_channel_snapshot *channel_snapshot
- );
-
-/*!
- * \brief Channel changed Caller ID.
- *
- * \param channel The channel that changed Caller ID.
- * \param blob JSON blob containing the following parameters:
- * - caller_presentation_txt: string - The text representation of the Caller Presentation value. (required)
- * - caller_presentation: integer - The integer representation of the Caller Presentation value. (required)
- *
- * \retval NULL on error
- * \retval JSON (ast_json) describing the event
- */
-struct ast_json *stasis_json_event_channel_caller_id_create(
- struct ast_channel_snapshot *channel_snapshot,
- struct ast_json *blob
+ * \brief Channel variable changed.
+ *
+ * \param channel The channel on which the variable was set.
+ * \param blob JSON blob containing the following parameters:
+ * - variable: string - The variable that changed. (required)
+ * - value: string - The new value of the variable. (required)
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_channel_varset_create(
+ struct ast_channel_snapshot *channel_snapshot,
+ struct ast_json *blob
+ );
+
+/*!
+ * \brief Notification that a channel has left a bridge.
+ *
+ * \param channel The channel to be used to generate this event
+ * \param bridge The bridge to be used to generate this event
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_channel_left_bridge_create(
+ struct ast_bridge_snapshot *bridge_snapshot,
+ struct ast_channel_snapshot *channel_snapshot
+ );
+
+/*!
+ * \brief Notification that a channel has been created.
+ *
+ * \param channel The channel to be used to generate this event
+ *
+ * \retval NULL on error
+ * \retval JSON (ast_json) describing the event
+ */
+struct ast_json *stasis_json_event_channel_created_create(
+ struct ast_channel_snapshot *channel_snapshot
+ );
+
+/*!
[... 316 lines stripped ...]
More information about the asterisk-commits
mailing list