[asterisk-commits] dlee: branch dlee/ari-monitor2 r395923 - in /team/dlee/ari-monitor2: include/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 31 21:35:13 CDT 2013


Author: dlee
Date: Wed Jul 31 21:35:11 2013
New Revision: 395923

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=395923
Log:
Merged ari-monitor work

Added:
    team/dlee/ari-monitor2/res/stasis_recording/
      - copied from r395922, team/dlee/ari-monitor/res/stasis_recording/
Modified:
    team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h
    team/dlee/ari-monitor2/res/Makefile
    team/dlee/ari-monitor2/res/ari/resource_channels.c
    team/dlee/ari-monitor2/res/ari/resource_channels.h
    team/dlee/ari-monitor2/res/res_ari_channels.c
    team/dlee/ari-monitor2/res/res_stasis_recording.c
    team/dlee/ari-monitor2/rest-api/api-docs/channels.json

Modified: team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h (original)
+++ team/dlee/ari-monitor2/include/asterisk/stasis_app_recording.h Wed Jul 31 21:35:11 2013
@@ -133,6 +133,26 @@
 	struct stasis_app_recording_options *options);
 
 /*!
+ * \brief Monitor media from a channel.
+ *
+ * A reference to the \a options object may be kept, so it MUST NOT be modified
+ * after calling this function.
+ *
+ * On error, \c errno is set to indicate the failure reason.
+ *  - \c EINVAL: Invalid input.
+ *  - \c EEXIST: A monitor with that name is in session.
+ *  - \c ENOMEM: Out of memory.
+ *
+ * \param control Control for \c res_stasis.
+ * \param options Monitor options.
+ * \return Recording control object.
+ * \return \c NULL on error.
+ */
+struct stasis_app_recording *stasis_app_control_monitor(
+	struct stasis_app_control *control,
+	struct stasis_app_recording_options *options);
+
+/*!
  * \brief Gets the current state of a recording operation.
  *
  * \param recording Recording control object.

Modified: team/dlee/ari-monitor2/res/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/Makefile?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/Makefile (original)
+++ team/dlee/ari-monitor2/res/Makefile Wed Jul 31 21:35:11 2013
@@ -86,5 +86,9 @@
 res_ari_model.so: ari/ari_model_validators.o
 ari/ari_model_validators.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_ari_model)
 
+res_stasis_recording.so: stasis_recording/monitor.o
+stasis_recording/monitor.o: _ASTCFLAGS+=$(call MOD_ASTCFLAGS,res_stasis_recording)
+
+
 # Dependencies for res_ari_*.so are generated, so they're in this file
 include ari.make

Modified: team/dlee/ari-monitor2/res/ari/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/ari/resource_channels.c?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/ari/resource_channels.c (original)
+++ team/dlee/ari-monitor2/res/ari/resource_channels.c Wed Jul 31 21:35:11 2013
@@ -329,71 +329,15 @@
 	ast_ari_response_created(response, playback_url, json);
 }
 
-void ast_ari_record_channel(struct ast_variable *headers,
-	struct ast_record_channel_args *args,
+static void response_from_recording(struct stasis_app_recording *recording,
 	struct ast_ari_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(char *, uri_encoded_name, NULL, ast_free);
 	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
-	RAII_VAR(struct stasis_app_recording_options *, options, NULL,
-		ao2_cleanup);
-	RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
+	const char *name = stasis_app_recording_get_name(recording);
 	size_t uri_name_maxlen;
 
-	ast_assert(response != NULL);
-
-	if (args->max_duration_seconds < 0) {
-		ast_ari_response_error(
-			response, 400, "Bad Request",
-			"max_duration_seconds cannot be negative");
-		return;
-	}
-
-	if (args->max_silence_seconds < 0) {
-		ast_ari_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 = stasis_app_recording_options_create(args->name, args->format);
-	if (options == NULL) {
-		ast_ari_response_error(
-			response, 500, "Internal Server Error",
-			"Out of memory");
-	}
-	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);
-	options->if_exists =
-		stasis_app_recording_if_exists_parse(args->if_exists);
-	options->beep = args->beep;
-
-	if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
-		ast_ari_response_error(
-			response, 400, "Bad Request",
-			"terminateOn invalid");
-		return;
-	}
-
-	if (options->if_exists == -1) {
-		ast_ari_response_error(
-			response, 400, "Bad Request",
-			"ifExists invalid");
-		return;
-	}
-
-	recording = stasis_app_control_record(control, options);
 	if (recording == NULL) {
 		switch(errno) {
 		case EINVAL:
@@ -407,7 +351,7 @@
 		case EEXIST:
 			ast_ari_response_error(response, 409, "Conflict",
 				"Recording '%s' already in progress",
-				args->name);
+				name);
 			break;
 		case ENOMEM:
 			ast_ari_response_error(
@@ -431,7 +375,7 @@
 		return;
 	}
 
-	uri_name_maxlen = strlen(args->name) * 3;
+	uri_name_maxlen = strlen(name) * 3;
 	uri_encoded_name = ast_malloc(uri_name_maxlen);
 	if (!uri_encoded_name) {
 		ast_ari_response_error(
@@ -439,7 +383,7 @@
 			"Out of memory");
 		return;
 	}
-	ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
+	ast_uri_encode(name, uri_encoded_name, uri_name_maxlen,
 		ast_uri_http);
 
 	ast_asprintf(&recording_url, "/recordings/live/%s", uri_encoded_name);
@@ -459,6 +403,111 @@
 	}
 
 	ast_ari_response_created(response, recording_url, json);
+}
+
+void ast_ari_monitor_channel(struct ast_variable *headers,
+	struct ast_monitor_channel_args *args,
+	struct ast_ari_response *response)
+{
+	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+	RAII_VAR(struct stasis_app_recording_options *, options, NULL,
+		ao2_cleanup);
+
+	ast_assert(response != NULL);
+
+	control = find_control(response, args->channel_id);
+	if (control == NULL) {
+		/* Response filled in by find_control */
+		return;
+	}
+
+	options = stasis_app_recording_options_create(args->name, args->format);
+	if (options == NULL) {
+		ast_ari_response_error(
+			response, 500, "Internal Server Error",
+			"Out of memory");
+	}
+	options->if_exists =
+		stasis_app_recording_if_exists_parse(args->if_exists);
+
+
+	if (options->if_exists == -1) {
+		ast_ari_response_error(
+			response, 400, "Bad Request",
+			"ifExists invalid");
+		return;
+	}
+
+	recording = stasis_app_control_monitor(control, options);
+
+	response_from_recording(recording, response);
+}
+
+void ast_ari_record_channel(struct ast_variable *headers,
+	struct ast_record_channel_args *args,
+	struct ast_ari_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(struct stasis_app_recording_options *, options, NULL,
+		ao2_cleanup);
+
+	ast_assert(response != NULL);
+
+	if (args->max_duration_seconds < 0) {
+		ast_ari_response_error(
+			response, 400, "Bad Request",
+			"max_duration_seconds cannot be negative");
+		return;
+	}
+
+	if (args->max_silence_seconds < 0) {
+		ast_ari_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 = stasis_app_recording_options_create(args->name, args->format);
+	if (options == NULL) {
+		ast_ari_response_error(
+			response, 500, "Internal Server Error",
+			"Out of memory");
+	}
+	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);
+	options->if_exists =
+		stasis_app_recording_if_exists_parse(args->if_exists);
+	options->beep = args->beep;
+
+	if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
+		ast_ari_response_error(
+			response, 400, "Bad Request",
+			"terminateOn invalid");
+		return;
+	}
+
+	if (options->if_exists == -1) {
+		ast_ari_response_error(
+			response, 400, "Bad Request",
+			"ifExists invalid");
+		return;
+	}
+
+	recording = stasis_app_control_record(control, options);
+
+	response_from_recording(recording, response);
 }
 
 void ast_ari_get_channel(struct ast_variable *headers,

Modified: team/dlee/ari-monitor2/res/ari/resource_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/ari/resource_channels.h?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/ari/resource_channels.h (original)
+++ team/dlee/ari-monitor2/res/ari/resource_channels.h Wed Jul 31 21:35:11 2013
@@ -265,6 +265,27 @@
  * \param[out] response HTTP response
  */
 void ast_ari_play_on_channel(struct ast_variable *headers, struct ast_play_on_channel_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_monitor_channel() */
+struct ast_monitor_channel_args {
+	/*! \brief Channel's id */
+	const char *channel_id;
+	/*! \brief Recording's filename */
+	const char *name;
+	/*! \brief Format to encode audio in */
+	const char *format;
+	/*! \brief Action to take if a recording with the same name already exists. */
+	const char *if_exists;
+};
+/*!
+ * \brief Start a monitor recording.
+ *
+ * Record audio to/from a channel.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_monitor_channel(struct ast_variable *headers, struct ast_monitor_channel_args *args, struct ast_ari_response *response);
 /*! \brief Argument struct for ast_ari_record_channel() */
 struct ast_record_channel_args {
 	/*! \brief Channel's id */

Modified: team/dlee/ari-monitor2/res/res_ari_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/res_ari_channels.c?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/res_ari_channels.c (original)
+++ team/dlee/ari-monitor2/res/res_ari_channels.c Wed Jul 31 21:35:11 2013
@@ -901,22 +901,22 @@
 #endif /* AST_DEVMODE */
 }
 /*!
- * \brief Parameter parsing callback for /channels/{channelId}/record.
- * \param get_params GET parameters in the HTTP request.
- * \param path_vars Path variables extracted from the request.
- * \param headers HTTP headers.
- * \param[out] response Response to the HTTP request.
- */
-static void ast_ari_record_channel_cb(
-	struct ast_variable *get_params, struct ast_variable *path_vars,
-	struct ast_variable *headers, struct ast_ari_response *response)
-{
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
-	struct ast_record_channel_args args = {};
+ * \brief Parameter parsing callback for /channels/{channelId}/monitor.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_monitor_channel_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
+
+	struct ast_monitor_channel_args args = {};
 	struct ast_variable *i;
 
 	for (i = get_params; i; i = i->next) {
@@ -926,6 +926,75 @@
 		if (strcmp(i->name, "format") == 0) {
 			args.format = (i->value);
 		} else
+		if (strcmp(i->name, "ifExists") == 0) {
+			args.if_exists = (i->value);
+		} else
+		{}
+	}
+	for (i = path_vars; i; i = i->next) {
+		if (strcmp(i->name, "channelId") == 0) {
+			args.channel_id = (i->value);
+		} else
+		{}
+	}
+	ast_ari_monitor_channel(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+	case 400: /* Invalid parameters */
+	case 404: /* Channel not found */
+	case 409: /* Channel is not in a Stasis application; the channel is currently bridged with other channels; A recording with the same name is currently in progress. */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_live_recording(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/monitor\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/monitor\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/record.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_record_channel_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
+
+	struct ast_record_channel_args args = {};
+	struct ast_variable *i;
+
+	for (i = get_params; i; i = i->next) {
+		if (strcmp(i->name, "name") == 0) {
+			args.name = (i->value);
+		} else
+		if (strcmp(i->name, "format") == 0) {
+			args.format = (i->value);
+		} else
 		if (strcmp(i->name, "maxDurationSeconds") == 0) {
 			args.max_duration_seconds = atoi(i->value);
 		} else
@@ -1200,6 +1269,15 @@
 	.children = {  }
 };
 /*! \brief REST handler for /api-docs/channels.{format} */
+static struct stasis_rest_handlers channels_channelId_monitor = {
+	.path_segment = "monitor",
+	.callbacks = {
+		[AST_HTTP_POST] = ast_ari_monitor_channel_cb,
+	},
+	.num_children = 0,
+	.children = {  }
+};
+/*! \brief REST handler for /api-docs/channels.{format} */
 static struct stasis_rest_handlers channels_channelId_record = {
 	.path_segment = "record",
 	.callbacks = {
@@ -1226,8 +1304,8 @@
 		[AST_HTTP_GET] = ast_ari_get_channel_cb,
 		[AST_HTTP_DELETE] = ast_ari_delete_channel_cb,
 	},
-	.num_children = 12,
-	.children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_mohstart,&channels_channelId_mohstop,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable, }
+	.num_children = 13,
+	.children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_mohstart,&channels_channelId_mohstop,&channels_channelId_play,&channels_channelId_monitor,&channels_channelId_record,&channels_channelId_variable, }
 };
 /*! \brief REST handler for /api-docs/channels.{format} */
 static struct stasis_rest_handlers channels = {

Modified: team/dlee/ari-monitor2/res/res_stasis_recording.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/res/res_stasis_recording.c?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/res/res_stasis_recording.c (original)
+++ team/dlee/ari-monitor2/res/res_stasis_recording.c Wed Jul 31 21:35:11 2013
@@ -32,13 +32,13 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "asterisk/dsp.h"
 #include "asterisk/file.h"
 #include "asterisk/module.h"
 #include "asterisk/paths.h"
 #include "asterisk/stasis_app_impl.h"
 #include "asterisk/stasis_app_recording.h"
 #include "asterisk/stasis_channels.h"
+#include "stasis_recording/recording.h"
 
 /*! Number of hash buckets for recording container. Keep it prime! */
 #define RECORDING_BUCKETS 127
@@ -53,18 +53,6 @@
 
 /*! Container of all current recordings */
 static struct ao2_container *recordings;
-
-struct stasis_app_recording {
-	/*! Recording options. */
-	struct stasis_app_recording_options *options;
-	/*! Absolute path (minus extension) of the recording */
-	char *absolute_name;
-	/*! 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;
-};
 
 static int recording_hash(const void *obj, int flags)
 {
@@ -177,7 +165,7 @@
 	return -1;
 }
 
-static void recording_publish(struct stasis_app_recording *recording)
+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);
@@ -290,7 +278,7 @@
 	ao2_cleanup(recording->options);
 }
 
-struct stasis_app_recording *stasis_app_control_record(
+struct stasis_app_recording *recording_create(
 	struct stasis_app_control *control,
 	struct stasis_app_recording_options *options)
 {
@@ -359,6 +347,21 @@
 		ao2_link(recordings, recording);
 	}
 
+	ao2_ref(recording, +1);
+	return recording;
+}
+
+struct stasis_app_recording *stasis_app_control_record(
+	struct stasis_app_control *control,
+	struct stasis_app_recording_options *options)
+{
+	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
+
+	recording = recording_create(control, options);
+	if (!recording) {
+		return NULL;
+	}
+
 	/* A ref is kept in the recordings container; no need to bump */
 	stasis_app_send_command_async(control, record_file, recording);
 

Modified: team/dlee/ari-monitor2/rest-api/api-docs/channels.json
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-monitor2/rest-api/api-docs/channels.json?view=diff&rev=395923&r1=395922&r2=395923
==============================================================================
--- team/dlee/ari-monitor2/rest-api/api-docs/channels.json (original)
+++ team/dlee/ari-monitor2/rest-api/api-docs/channels.json Wed Jul 31 21:35:11 2013
@@ -597,6 +597,76 @@
 						{
 							"code": 409,
 							"reason": "Channel not in a Stasis application"
+						}
+					]
+				}
+			]
+		},
+		{
+			"path": "/channels/{channelId}/monitor",
+			"description": "Starts a monitor recording on a channel",
+			"operations": [
+				{
+					"httpMethod": "POST",
+					"summary": "Start a monitor recording.",
+					"notes": "Record audio to/from a channel.",
+					"nickname": "monitorChannel",
+					"responseClass": "LiveRecording",
+					"parameters": [
+						{
+							"name": "channelId",
+							"description": "Channel's id",
+							"paramType": "path",
+							"required": true,
+							"allowMultiple": false,
+							"dataType": "string"
+						},
+						{
+							"name": "name",
+							"description": "Recording's filename",
+							"paramType": "query",
+							"required": true,
+							"allowMultiple": false,
+							"dataType": "string"
+						},
+						{
+							"name": "format",
+							"description": "Format to encode audio in",
+							"paramType": "query",
+							"required": true,
+							"allowMultiple": true,
+							"dataType": "string"
+						},
+						{
+							"name": "ifExists",
+							"description": "Action to take if a recording with the same name already exists.",
+							"paramType": "query",
+							"required": false,
+							"allowMultiple": false,
+							"dataType": "string",
+							"defaultValue": "fail",
+							"allowableValues": {
+								"valueType": "LIST",
+								"values": [
+									"fail",
+									"overwrite",
+									"append"
+								]
+							}
+						}
+					],
+					"errorResponses": [
+						{
+							"code": 400,
+							"reason": "Invalid parameters"
+						},
+						{
+							"code": 404,
+							"reason": "Channel not found"
+						},
+						{
+							"code": 409,
+							"reason": "Channel is not in a Stasis application; the channel is currently bridged with other channels; A recording with the same name is currently in progress."
 						}
 					]
 				}




More information about the asterisk-commits mailing list