[asterisk-commits] dlee: branch dlee/record r389615 - in /team/dlee/record: include/asterisk/ re...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 23 15:34:14 CDT 2013


Author: dlee
Date: Thu May 23 15:34:11 2013
New Revision: 389615

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=389615
Log:
Recording initial work

Added:
    team/dlee/record/include/asterisk/stasis_app_recording.h   (with props)
    team/dlee/record/res/res_stasis_recording.c   (with props)
    team/dlee/record/res/res_stasis_recording.exports.in   (with props)
Modified:
    team/dlee/record/include/asterisk/channel.h
    team/dlee/record/include/asterisk/file.h
    team/dlee/record/include/asterisk/stasis_http.h
    team/dlee/record/res/res_stasis_http.c
    team/dlee/record/res/res_stasis_playback.c
    team/dlee/record/res/stasis_http/resource_channels.c

Modified: team/dlee/record/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/include/asterisk/channel.h?view=diff&rev=389615&r1=389614&r2=389615
==============================================================================
--- team/dlee/record/include/asterisk/channel.h (original)
+++ team/dlee/record/include/asterisk/channel.h Thu May 23 15:34:11 2013
@@ -1560,6 +1560,24 @@
  * \retval non-zero on failure
  */
 int ast_answer(struct ast_channel *chan);
+
+/*!
+ * \brief Answer a channel, if it's not already answered.
+ *
+ * \param chan channel to answer
+ *
+ * \details See ast_answer()
+ *
+ * \retval 0 on success
+ * \retval non-zero on failure
+ */
+static inline int ast_auto_answer(struct ast_channel *chan)
+{
+	if (ast_channel_state(chan) == AST_STATE_UP) {
+		/* Already answered */
+		return 0;
+	}
+	return ast_answer(chan);}
 
 /*!
  * \brief Answer a channel

Modified: team/dlee/record/include/asterisk/file.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/include/asterisk/file.h?view=diff&rev=389615&r1=389614&r2=389615
==============================================================================
--- team/dlee/record/include/asterisk/file.h (original)
+++ team/dlee/record/include/asterisk/file.h Thu May 23 15:34:11 2013
@@ -64,8 +64,8 @@
  */
 typedef void (ast_waitstream_fr_cb)(struct ast_channel *chan, long ms, enum ast_waitstream_fr_cb_values val);
 
-/*! 
- * \brief Streams a file 
+/*!
+ * \brief Streams a file
  * \param c channel to stream the file to
  * \param filename the name of the file you wish to stream, minus the extension
  * \param preflang the preferred language you wish to have the file streamed to you in
@@ -75,6 +75,27 @@
  * \retval -1 on failure.
  */
 int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang);
+
+/*!
+ * \brief Plays a sound to the channel, in the channel's default language.
+ *
+ * This will stop any existing streams on the channel.
+
+ * \param c channel to stream the file to
+ * \param filename the name of the file you wish to stream, minus the extension
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+static int ast_play_sound(struct ast_channel *c, const char *filename)
+{
+	int res;
+	res = ast_streamfile(chan, "beep", ast_channel_language(chan));
+	if (res == 0) {
+		res = ast_waitstream(chan, "");
+	}
+	ast_stopstream(chan);
+	return res;
+}
 
 /*!
  * \brief stream file until digit
@@ -86,12 +107,12 @@
  */
 int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits);
 
-/*! 
- * \brief Stops a stream 
+/*!
+ * \brief Stops a stream
  *
  * \param c The channel you wish to stop playback on
  *
- * Stop playback of a stream 
+ * Stop playback of a stream
  *
  * \retval 0 always
  *

Added: team/dlee/record/include/asterisk/stasis_app_recording.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/include/asterisk/stasis_app_recording.h?view=auto&rev=389615
==============================================================================
--- team/dlee/record/include/asterisk/stasis_app_recording.h (added)
+++ team/dlee/record/include/asterisk/stasis_app_recording.h Thu May 23 15:34:11 2013
@@ -1,0 +1,159 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * David M. Lee, II <dlee at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#ifndef _ASTERISK_STASIS_APP_RECORDING_H
+#define _ASTERISK_STASIS_APP_RECORDING_H
+
+/*! \file
+ *
+ * \brief Stasis Application Recording API. See \ref res_stasis "Stasis
+ * Application API" for detailed documentation.
+ *
+ * \author David M. Lee, II <dlee at digium.com>
+ * \since 12
+ */
+
+#include "asterisk/stasis_app.h"
+
+/*! Opaque struct for handling the recording of media to a file. */
+struct stasis_app_recording;
+
+/*! State of a recording operation */
+enum stasis_app_recording_state {
+	/*! The recording has not started yet */
+	STASIS_APP_RECORDING_STATE_QUEUED,
+	/*! The media is currently recording */
+	STASIS_APP_RECORDING_STATE_RECORDING,
+	/*! The media is currently paused */
+	STASIS_APP_RECORDING_STATE_PAUSED,
+	/*! The media has stopped recording */
+	STASIS_APP_RECORDING_STATE_COMPLETE,
+	/*! The media has stopped playing */
+	STASIS_APP_RECORDING_STATE_FAILED,
+	/*! Enum end sentinel. */
+	STASIS_APP_RECORDING_STATE_MAX,
+};
+
+/*! Valid operation for controlling a recording. */
+enum stasis_app_recording_media_operation {
+	/*! Stop the recording operation. */
+	STASIS_APP_RECORDING_STOP,
+	/*! Enum end sentinel. */
+	STASIS_APP_RECORDING_MEDIA_OP_MAX,
+};
+
+enum stasis_app_recording_termination {
+	STASIS_APP_RECORDING_TERMINATE_NONE,
+	STASIS_APP_RECORDING_TERMINATE_HASH,
+	STASIS_APP_RECORDING_TERMINATE_STAR,
+	STASIS_APP_RECORDING_TERMINATE_ANY,
+};
+
+struct stasis_app_recording_options {
+	/*! \param name Name of the recording. */
+	const char *name;
+	/*! Format to be recorded (wav, gsm, etc.) */
+	const char *format;
+	/*! Number of seconds of silence before ending the recording. */
+	int max_silence_seconds;
+	/*! Maximum recording duration. 0 for no maximum. */
+	int max_duration_seconds;
+	/*! Which DTMF to use to terminate the recording */
+	enum stasis_app_recording_termination terminate_on;
+	/*! If true, file is appended to instead of overwriting. */
+	int append:1;
+	/*! If true, no beep is played at the start of recording */
+	int no_beep:1;
+};
+
+/*!
+ * \brief Parse a string into the recording termination enum.
+ *
+ * \param str String to parse.
+ * \return Parsed value.
+ * \return -1 on error.
+ */
+enum stasis_app_recording_termination stasis_app_recording_termination_parse(const char *str);
+
+/*!
+ * \brief Record media from a channel.
+ *
+ * \param control Control for \c res_stasis.
+ * \return Recording control object.
+ * \return \c NULL on error.
+ */
+struct stasis_app_recording *stasis_app_control_record(
+	struct stasis_app_control *control,
+	const struct stasis_app_recording_options *options);
+
+/*!
+ * \brief Gets the current state of a recording operation.
+ *
+ * \param recording Recording control object.
+ * \return The state of the \a recording object.
+ */
+enum stasis_app_recording_state stasis_app_recording_get_state(
+	struct stasis_app_recording *recording);
+
+/*!
+ * \brief Gets the unique id of a recording object.
+ *
+ * \param recording Recording control object.
+ * \return \a recording's id.
+ * \return \c NULL if \a recording ic \c NULL
+ */
+const char *stasis_app_recording_get_id(
+	struct stasis_app_recording *recording);
+
+/*!
+ * \brief Finds the recording object with the given id.
+ *
+ * \param id Id of the recording object to find.
+ * \return Associated \ref stasis_app_recording object.
+ * \return \c NULL if \a id not found.
+ */
+struct stasis_app_recording *stasis_app_recording_find_by_id(const char *id);
+
+struct ast_json *stasis_app_recording_to_json(
+	const struct stasis_app_recording *recording);
+
+enum stasis_app_recording_oper_results {
+	STASIS_APP_RECORDING_OPER_OK,
+	STASIS_APP_RECORDING_OPER_FAILED,
+	STASIS_APP_RECORDING_OPER_NOT_RECORDING,
+};
+
+/*!
+ * \brief Controls the media for a given recording operation.
+ *
+ * \param recording Recording control object.
+ * \param control Media control operation.
+ * \return \c STASIS_APP_RECORDING_OPER_OK on success.
+ * \return \ref stasis_app_recording_oper_results indicating failure.
+ */
+enum stasis_app_recording_oper_results stasis_app_recording_operation(
+	struct stasis_app_recording *recording,
+	enum stasis_app_recording_media_operation operation);
+
+/*!
+ * \brief Message type for recording updates. The data is an
+ * \ref ast_channel_blob.
+ */
+struct stasis_message_type *stasis_app_recording_snapshot_type(void);
+
+#endif /* _ASTERISK_STASIS_APP_RECORDING_H */

Propchange: team/dlee/record/include/asterisk/stasis_app_recording.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/dlee/record/include/asterisk/stasis_app_recording.h
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/dlee/record/include/asterisk/stasis_app_recording.h
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/dlee/record/include/asterisk/stasis_http.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/include/asterisk/stasis_http.h?view=diff&rev=389615&r1=389614&r2=389615
==============================================================================
--- team/dlee/record/include/asterisk/stasis_http.h (original)
+++ team/dlee/record/include/asterisk/stasis_http.h Thu May 23 15:34:11 2013
@@ -166,7 +166,7 @@
  * \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);
+	const char *url, struct ast_json *message);
 
 /*!
  * \brief Fill in \a response with a 500 message for allocation failures.

Modified: team/dlee/record/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/res/res_stasis_http.c?view=diff&rev=389615&r1=389614&r2=389615
==============================================================================
--- team/dlee/record/res/res_stasis_http.c (original)
+++ team/dlee/record/res/res_stasis_http.c Thu May 23 15:34:11 2013
@@ -331,9 +331,9 @@
 }
 
 void stasis_http_response_created(struct stasis_http_response *response,
-	const char *url)
-{
-	response->message = ast_json_null();
+	const char *url, struct ast_json *message)
+{
+	response->message = message;
 	response->response_code = 201;
 	response->response_text = "Created";
 	ast_str_append(&response->headers, 0, "Location: %s\r\n", url);

Modified: team/dlee/record/res/res_stasis_playback.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/res/res_stasis_playback.c?view=diff&rev=389615&r1=389614&r2=389615
==============================================================================
--- team/dlee/record/res/res_stasis_playback.c (original)
+++ team/dlee/record/res/res_stasis_playback.c Thu May 23 15:34:11 2013
@@ -266,7 +266,7 @@
 		stasis_app_control_get_channel_id(control), uri);
 
 	playback = ao2_alloc(sizeof(*playback), playback_dtor);
-	if (!playback || ast_string_field_init(playback, 128) ){
+	if (!playback || ast_string_field_init(playback, 128)) {
 		return NULL;
 	}
 
@@ -329,7 +329,6 @@
 	if (playback == NULL) {
 		return NULL;
 	}
-
 
 	json = ast_json_pack("{s: s, s: s, s: s, s: s}",
 		"id", playback->id,

Added: team/dlee/record/res/res_stasis_recording.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/res/res_stasis_recording.c?view=auto&rev=389615
==============================================================================
--- team/dlee/record/res/res_stasis_recording.c (added)
+++ team/dlee/record/res/res_stasis_recording.c Thu May 23 15:34:11 2013
@@ -1,0 +1,346 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * David M. Lee, II <dlee at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief res_stasis recording support.
+ *
+ * \author David M. Lee, II <dlee at digium.com>
+ */
+
+/*** MODULEINFO
+	<depend type="module">res_stasis</depend>
+	<support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/file.h"
+#include "asterisk/module.h"
+#include "asterisk/stasis_app_impl.h"
+#include "asterisk/stasis_app_recording.h"
+#include "asterisk/stasis_channels.h"
+#include "asterisk/uuid.h"
+
+/*! Number of hash buckets for recording container. Keep it prime! */
+#define RECORDING_BUCKETS 127
+
+STASIS_MESSAGE_TYPE_DEFN(stasis_app_recording_snapshot_type);
+
+/*! Container of all current recordings */
+static struct ao2_container *recordings;
+
+struct stasis_app_recording {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(id);	/*!< Recording unique id */
+		AST_STRING_FIELD(name);
+		AST_STRING_FIELD(format);
+		);
+	/*! Control object for the channel we're playing back to */
+	struct stasis_app_control *control;
+	/*! Current state of the recording. */
+	enum stasis_app_recording_state state;
+	/*! Number of seconds of silence before ending the recording. */
+	int max_silence_seconds;
+	/*! Maximum recording duration. 0 for no maximum. */
+	int max_duration_seconds;
+	/*! Which DTMF to use to terminate the recording */
+	enum stasis_app_recording_termination terminate_on;
+	/*! If true, file is appended to instead of overwriting. */
+	int append:1;
+	/*! If true, no beep is played at the start of recording */
+	int no_beep:1;
+};
+
+static int recording_hash(const void *obj, int flags)
+{
+	const struct stasis_app_recording *recording = obj;
+	const char *id = flags & OBJ_KEY ? obj : recording->id;
+	return ast_str_hash(id);
+}
+
+static int recording_cmp(void *obj, void *arg, int flags)
+{
+	struct stasis_app_recording *lhs = obj;
+	struct stasis_app_recording *rhs = arg;
+	const char *rhs_id = flags & OBJ_KEY ? arg : rhs->id;
+
+	if (strcmp(lhs->id, rhs_id) == 0) {
+		return CMP_MATCH | CMP_STOP;
+	} else {
+		return 0;
+	}
+}
+
+enum stasis_app_recording_termination stasis_app_recording_termination_parse(const char *str)
+{
+	if (ast_strlen_zero(str)) {
+		return STASIS_APP_RECORDING_TERMINATE_NONE;
+	}
+
+	if (strcmp(str, "none")) {
+		return STASIS_APP_RECORDING_TERMINATE_NONE;
+	}
+
+	if (strcmp(str, "#") == 0) {
+		return STASIS_APP_RECORDING_TERMINATE_HASH;
+	}
+
+	if (strcmp(str, "*") == 0) {
+		return STASIS_APP_RECORDING_TERMINATE_STAR;
+	}
+
+	if (strcmp(str, "any") == 0) {
+		return STASIS_APP_RECORDING_TERMINATE_ANY;
+	}
+
+	return -1;
+}
+
+static void recording_publish(struct stasis_app_recording *recording)
+{
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+
+	ast_assert(recording != NULL);
+
+	json = stasis_app_recording_to_json(recording);
+	if (json == NULL) {
+		return;
+	}
+
+	message = ast_channel_blob_create_from_cache(
+		stasis_app_control_get_channel_id(recording->control),
+		stasis_app_recording_snapshot_type(), json);
+	if (message == NULL) {
+		return;
+	}
+
+	stasis_app_control_publish(recording->control, message);
+}
+
+static void recording_fail(struct stasis_app_recording *recording)
+{
+	SCOPED_AO2LOCK(lock, recording);
+	recording->state = STASIS_APP_RECORDING_STATE_FAILED;
+	recording_publish(recording);
+}
+
+static void *record_file(struct stasis_app_control *control,
+	struct ast_channel *chan, void *data)
+{
+	struct stasis_app_recording *recording = data;
+	int res;
+	long maxms;
+
+	ao2_lock(recording);
+	recording->state = STASIS_APP_RECORDING_STATE_RECORDING;
+	recording_publish(recording);
+	ao2_unlock(recording);
+
+	res = ast_auto_answer(chan);
+	if (res != 0) {
+		recording_fail(recording);
+		return NULL;
+	}
+
+	if (!recording->no_beep) {
+		res = ast_play_sound(chan, "beep");
+	}
+	if (res != 0) {
+		recording_fail(recording);
+		return NULL;
+	}
+
+	maxms = control->max_duration_seconds * 1000;
+	start = ast_tvnow();
+	while ((ms = ast_remaining_ms(start, maxms))) {
+		RAII_VAR(struct ast_frame *, f, NULL, ast_frame_dtor);
+
+		res = ast_waitfor(chan, ms);
+		if (res < 0) {
+			break;
+		}
+
+		if (maxduration > 0 && res == 0) {
+			break;
+		}
+
+		f = ast_read(chan);
+		if (!f) {
+			break;
+		}
+
+		switch (f->frametype) {
+		case AST_FRAME_VOICE:
+			res = ast_writestream(s, f);
+			break;
+		case AST_FRAME_VIDEO:
+			res = ast_writestream(s, f);
+			break;
+		case AST_FRAME_DTMF:
+			
+			break;
+		}
+	}
+
+	ao2_lock(recording);
+	recording->state = STASIS_APP_RECORDING_STATE_COMPLETE;
+	recording_publish(recording);
+	ao2_unlock(recording);
+	return NULL;
+}
+
+static void recording_dtor(void *obj)
+{
+	struct stasis_app_recording *recording = obj;
+
+	ast_string_field_free_memory(recording);
+}
+
+struct stasis_app_recording *stasis_app_control_record(
+	struct stasis_app_control *control,
+	const struct stasis_app_recording_options *options)
+{
+	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+	char id[AST_UUID_STR_LEN];
+
+	if (options == NULL ||
+		ast_strlen_zero(options->name) ||
+		ast_strlen_zero(options->format) ||
+		options->max_silence_seconds < 0 ||
+		options->max_duration_seconds < 0 ||
+		options->terminate_on < 0) {
+		return NULL;
+	}
+
+	ast_debug(3, "%s: Sending record(%s.%s) command\n",
+		stasis_app_control_get_channel_id(control), options->name,
+		options->format);
+
+	recording = ao2_alloc(sizeof(*recording), recording_dtor);
+	if (!recording || ast_string_field_init(recording, 128)) {
+		return NULL;
+	}
+
+	ast_uuid_generate_str(id, sizeof(id));
+	recording->control = control;
+	ast_string_field_set(recording, id, id);
+	ast_string_field_set(recording, name, options->name);
+	ast_string_field_set(recording, format, options->format);
+	recording->max_silence_seconds = options->max_silence_seconds;
+	recording->max_duration_seconds = options->max_duration_seconds;
+	recording->terminate_on = options->terminate_on;
+	recording->append = options->append;
+	recording->no_beep = options->no_beep;
+	ao2_link(recordings, recording);
+
+	recording->state = STASIS_APP_RECORDING_STATE_QUEUED;
+
+	/* A ref is kept in the recordings container; no need to bump */
+	stasis_app_send_command_async(control, record_file, recording);
+
+	/* Although this should be bumped for the caller */
+	ao2_ref(recording, +1);
+	return recording;
+}
+
+enum stasis_app_recording_state stasis_app_recording_get_state(
+	struct stasis_app_recording *recording)
+{
+	return recording->state;
+}
+
+const char *stasis_app_recording_get_id(
+	struct stasis_app_recording *recording)
+{
+	return recording->id;
+}
+
+struct stasis_app_recording *stasis_app_recording_find_by_id(const char *id)
+{
+	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+
+	recording = ao2_find(recordings, id, OBJ_KEY);
+	if (recording == NULL) {
+		return NULL;
+	}
+
+	ao2_ref(recording, +1);
+	return recording;
+}
+
+struct ast_json *stasis_app_recording_to_json(
+	const struct stasis_app_recording *recording)
+{
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+
+	if (recording == NULL) {
+		return NULL;
+	}
+
+	json = ast_json_pack("{s: s, s: s, s: s, s: s}",
+		"id", recording->id,
+		"name", recording->name,
+		"format", recording->format,
+		"state", recording->state);
+
+	return ast_json_ref(json);
+}
+
+enum stasis_app_recording_oper_results stasis_app_recording_operation(
+	struct stasis_app_recording *recording,
+	enum stasis_app_recording_media_operation operation)
+{
+	ast_assert(0); // TODO
+	return STASIS_APP_RECORDING_OPER_FAILED;
+}
+
+static int load_module(void)
+{
+	int r;
+
+	r = STASIS_MESSAGE_TYPE_INIT(stasis_app_recording_snapshot_type);
+	if (r != 0) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
+
+	recordings = ao2_container_alloc(RECORDING_BUCKETS, recording_hash,
+		recording_cmp);
+	if (!recordings) {
+		return AST_MODULE_LOAD_FAILURE;
+	}
+	return AST_MODULE_LOAD_SUCCESS;
+}
+
+static int unload_module(void)
+{
+	ao2_cleanup(recordings);
+	recordings = NULL;
+	STASIS_MESSAGE_TYPE_CLEANUP(stasis_app_recording_snapshot_type);
+	return 0;
+}
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,
+	"Stasis application recording support",
+	.load = load_module,
+	.unload = unload_module,
+	.nonoptreq = "res_stasis");

Propchange: team/dlee/record/res/res_stasis_recording.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/dlee/record/res/res_stasis_recording.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/dlee/record/res/res_stasis_recording.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: team/dlee/record/res/res_stasis_recording.exports.in
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/res/res_stasis_recording.exports.in?view=auto&rev=389615
==============================================================================
--- team/dlee/record/res/res_stasis_recording.exports.in (added)
+++ team/dlee/record/res/res_stasis_recording.exports.in Thu May 23 15:34:11 2013
@@ -1,0 +1,6 @@
+{
+	global:
+		LINKER_SYMBOL_PREFIXstasis_app_*;
+	local:
+		*;
+};

Propchange: team/dlee/record/res/res_stasis_recording.exports.in
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/dlee/record/res/res_stasis_recording.exports.in
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: team/dlee/record/res/res_stasis_recording.exports.in
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/dlee/record/res/stasis_http/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/record/res/stasis_http/resource_channels.c?view=diff&rev=389615&r1=389614&r2=389615
==============================================================================
--- team/dlee/record/res/stasis_http/resource_channels.c (original)
+++ team/dlee/record/res/stasis_http/resource_channels.c Thu May 23 15:34:11 2013
@@ -1,4 +1,4 @@
-/* -*- C -*-
+/*
  * Asterisk -- An open source telephony toolkit.
  *
  * Copyright (C) 2012 - 2013, Digium, Inc.
@@ -35,6 +35,7 @@
 #include "asterisk/file.h"
 #include "asterisk/stasis_app.h"
 #include "asterisk/stasis_app_playback.h"
+#include "asterisk/stasis_app_recording.h"
 #include "asterisk/stasis_channels.h"
 #include "resource_channels.h"
 
@@ -145,6 +146,7 @@
 	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);
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
 	const char *language;
 
 	ast_assert(response != NULL);
@@ -197,12 +199,84 @@
 		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)
-{
-	ast_log(LOG_ERROR, "TODO: stasis_http_record_channel\n");
-}
+	json = stasis_app_playback_to_json(playback);
+	if (!json) {
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Out of memory");
+		return;
+	}
+
+	stasis_http_response_created(response, playback_url, json);
+}
+
+void stasis_http_record_channel(struct ast_variable *headers,
+	struct ast_record_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_recording *, recording, NULL, ao2_cleanup);
+	RAII_VAR(char *, recording_url, NULL, ast_free);
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+	struct stasis_app_recording_options options = {};
+
+	ast_assert(response != NULL);
+
+	if (args->max_duration_seconds < 0) {
+		stasis_http_response_error(
+			response, 400, "Bad Request",
+			"max_duration_seconds cannot be negative");
+		return;
+	}
+
+	if (args->max_silence_seconds < 0) {
+		stasis_http_response_error(
+			response, 400, "Bad Request",
+			"max_silence_seconds cannot be negative");
+		return;
+	}
+
+	control = find_control(response, args->channel_id);
+	if (control == NULL) {
+		/* Response filled in by find_control */
+		return;
+	}
+
+	options.name = args->name;
+	options.format = args->format;
+	options.max_silence_seconds = args->max_silence_seconds;
+	options.max_duration_seconds = args->max_duration_seconds;
+	options.terminate_on =
+		stasis_app_recording_termination_parse(args->terminate_on);
+
+	if (options.terminate_on == -1) {
+		stasis_http_response_error(
+			response, 400, "Bad Request",
+			"terminateOn invalid");
+		return;
+	}
+
+	recording = stasis_app_control_record(control, &options);
+	if (!recording) {
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Failed to start recording");
+		return;
+	}
+
+	ast_asprintf(&recording_url, "/recording/%s",
+		stasis_app_recording_get_id(recording));
+	if (!recording_url) {
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Out of memory");
+		return;
+	}
+
+	stasis_http_response_created(response, recording_url, json);
+}
+
 void stasis_http_get_channel(struct ast_variable *headers,
 			     struct ast_get_channel_args *args,
 			     struct stasis_http_response *response)




More information about the asterisk-commits mailing list