diff --git a/libgstd/gstd_action.c b/libgstd/gstd_action.c index cee64b34..79dc20d3 100644 --- a/libgstd/gstd_action.c +++ b/libgstd/gstd_action.c @@ -208,7 +208,9 @@ gstd_action_create_default (GstdObject * object, const gchar * name, GstdAction *action = NULL; GSignalQuery query; guint action_id; - gint ret_sig = 0; + GValue ret_sig = G_VALUE_INIT; + GValue *args = NULL; + gchar **arg_list = NULL; GST_INFO_OBJECT (action, "Action create"); @@ -222,19 +224,62 @@ gstd_action_create_default (GstdObject * object, const gchar * name, G_OBJECT_TYPE (action->target)); g_signal_query (action_id, &query); - if (query.n_params > 0) { - GST_ERROR_OBJECT (action, "Only actions with no parameters are supported"); - ret = GSTD_BAD_VALUE; - goto out; + if (query.n_params > 0 && (!description || g_strcmp0(description, "(null)") == 0 || g_strcmp0(description, "") == 0)) { + return GSTD_NULL_ARGUMENT; + } else if (description) { + arg_list = g_strsplit (description, " ", query.n_params); } - GST_INFO_OBJECT (action, "Emit to %s", GST_OBJECT_NAME (action->target)); - g_signal_emit_by_name (action->target, name, &ret_sig); + if (g_strv_length (arg_list) != query.n_params) { + return GSTD_NULL_ARGUMENT; + } + + /* One additional value to store the instance as first value */ + args = g_new0 (GValue, query.n_params + 1); + + g_value_init (&args[0], G_TYPE_OBJECT); + g_value_set_object (&args[0], action->target); + + for (guint i = 0; i < query.n_params; i++) { + g_value_init (&args[i + 1], query.param_types[i]); + + if (query.param_types[i] == G_TYPE_STRING) { + g_value_set_string (&args[i + 1], arg_list[i]); + } else if (query.param_types[i] == G_TYPE_INT) { + g_value_set_int (&args[i + 1], g_ascii_strtoll (arg_list[i], NULL, 10)); + } else if (query.param_types[i] == G_TYPE_UINT) { + g_value_set_uint (&args[i + 1], (guint) g_ascii_strtoull (arg_list[i], NULL, 10)); + } else if (query.param_types[i] == G_TYPE_UINT64) { + g_value_set_uint64 (&args[i + 1], (guint64) g_ascii_strtoull (arg_list[i], + NULL, 10)); + } else if (query.param_types[i] == G_TYPE_BOOLEAN) { + g_value_set_boolean (&args[i + 1], g_ascii_strcasecmp (arg_list[i], "true") == 0); + } else if (query.param_types[i] == G_TYPE_FLOAT) { + g_value_set_float (&args[i + 1], g_ascii_strtod (arg_list[i], NULL)); + } else if (query.param_types[i] == G_TYPE_DOUBLE) { + g_value_set_double (&args[i + 1], g_ascii_strtod (arg_list[i], NULL)); + } else { + ret = GSTD_BAD_COMMAND; + goto out; + } + } - if (ret_sig != 0) { - ret = GSTD_BAD_VALUE; + if (query.return_type != G_TYPE_NONE) { + g_value_init(&ret_sig, query.return_type); + g_signal_emitv (args, action_id, 0, &ret_sig); + + /* The return value is not required */ + + g_value_unset(&ret_sig); + } else { + g_signal_emitv (args, action_id, 0, NULL); } out: + for (guint i = 0; i <= query.n_params; i++) + g_value_unset (&args[i]); + g_free (args); + g_strfreev (arg_list); + return ret; } diff --git a/libgstd/gstd_http.c b/libgstd/gstd_http.c index ef4a20f5..703f98cc 100644 --- a/libgstd/gstd_http.c +++ b/libgstd/gstd_http.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "gstd_http.h" #include "gstd_parser.h" @@ -83,6 +84,7 @@ static GstdReturnCode do_put (SoupServer * server, SoupMessage * msg, static GstdReturnCode do_delete (SoupServer * server, SoupMessage * msg, char *name, char **output, const char *path, GstdSession * session); static void do_request (gpointer data_request, gpointer eval); +static void parse_json_body (SoupMessage *msg, gchar **out_name, gchar **out_desc); static void server_callback (SoupServer * server, SoupMessage * msg, const char *path, GHashTable * query, SoupClientContext * context, gpointer data); @@ -311,9 +313,13 @@ do_request (gpointer data_request, gpointer eval) path = data_request_local->path; query = data_request_local->query; - if (query != NULL) { - name = g_hash_table_lookup (query, "name"); - description_pipe = g_hash_table_lookup (query, "description"); + parse_json_body (msg, &name, &description_pipe); + + if (!name && query) { + name = g_strdup (g_hash_table_lookup (query, "name")); + } + if (!description_pipe && query) { + description_pipe = g_strdup (g_hash_table_lookup (query, "description")); } if (msg->method == SOUP_METHOD_GET) { @@ -327,6 +333,10 @@ do_request (gpointer data_request, gpointer eval) } else if (msg->method == SOUP_METHOD_OPTIONS) { ret = GSTD_EOK; } + g_free (name); + g_free (description_pipe); + name = NULL; + description_pipe = NULL; description = gstd_return_code_to_string (ret); response = @@ -356,6 +366,56 @@ do_request (gpointer data_request, gpointer eval) return; } +static void +parse_json_body (SoupMessage *msg, gchar **out_name, gchar **out_desc) +{ + const char *content_type = NULL; + JsonParser *parser = NULL; + JsonNode *root = NULL; + GError *err = NULL; + + g_return_if_fail (msg); + g_return_if_fail (out_name); + g_return_if_fail (out_desc); + + *out_name = NULL; + *out_desc = NULL; + + soup_message_body_flatten (msg->request_body); + if (!msg->request_body || msg->request_body->length == 0) { + return; + } + + content_type = soup_message_headers_get_content_type (msg->request_headers, NULL); + if (!content_type || !g_str_has_prefix (content_type, "application/json")) { + return; + } + + parser = json_parser_new (); + if (!json_parser_load_from_data (parser, + msg->request_body->data, + msg->request_body->length, + &err)) { + g_clear_error (&err); + g_object_unref (parser); + return; + } + + root = json_parser_get_root (parser); + if (JSON_NODE_HOLDS_OBJECT (root)) { + JsonObject *obj = json_node_get_object (root); + if (json_object_has_member (obj, "name")) { + const char *value = json_object_get_string_member (obj, "name"); + if (value) *out_name = g_strdup (value); + } + if (json_object_has_member (obj, "description")) { + const char *value = json_object_get_string_member (obj, "description"); + if (value) *out_desc = g_strdup (value); + } + } + g_object_unref (parser); +} + static void server_callback (SoupServer * server, SoupMessage * msg, const char *path, GHashTable * query, diff --git a/libgstd/gstd_parser.c b/libgstd/gstd_parser.c index 821984ee..84d62ab8 100644 --- a/libgstd/gstd_parser.c +++ b/libgstd/gstd_parser.c @@ -939,13 +939,13 @@ gstd_parser_action_emit (GstdSession * session, gchar * action, g_return_val_if_fail (args, GSTD_NULL_ARGUMENT); g_return_val_if_fail (response, GSTD_NULL_ARGUMENT); - tokens = g_strsplit (args, " ", 3); + tokens = g_strsplit (args, " ", 4); check_argument (tokens[0], GSTD_BAD_COMMAND); check_argument (tokens[1], GSTD_BAD_COMMAND); check_argument (tokens[2], GSTD_BAD_COMMAND); - uri = g_strdup_printf ("/pipelines/%s/elements/%s/actions/%s %s", - tokens[0], tokens[1], tokens[2], tokens[2]); + uri = g_strdup_printf ("/pipelines/%s/elements/%s/actions/%s %s %s", + tokens[0], tokens[1], tokens[2], tokens[2], tokens[3]); ret = gstd_parser_parse_raw_cmd (session, (gchar *) "create", uri, response); g_free (uri);