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."
                                                }
                                        ]
                                }


--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to