From bd06d8d14a8c6f511f2c2b35642cbfeb1ce16e59 Mon Sep 17 00:00:00 2001 From: Gergely Polonkai Date: Fri, 3 Nov 2017 13:32:38 +0100 Subject: [PATCH] Port MatrixVideoInfo to C --- .gitignore | 1 - src/Makefile.am | 7 +- src/{matrix-c-types.c => matrix-types.c} | 441 ++++++++++++++++++++++- src/{matrix-c-types.h => matrix-types.h} | 25 ++ src/matrix-types.vala | 109 ------ vapi/c-api.vapi | 37 +- 6 files changed, 502 insertions(+), 118 deletions(-) rename src/{matrix-c-types.c => matrix-types.c} (72%) rename src/{matrix-c-types.h => matrix-types.h} (83%) delete mode 100644 src/matrix-types.vala diff --git a/.gitignore b/.gitignore index 79e5df2..23acb4b 100644 --- a/.gitignore +++ b/.gitignore @@ -49,7 +49,6 @@ Makefile.in /src/matrix-glib.h /src/matrix-api.c /src/matrix-client.c -/src/matrix-types.c /src/matrix-http-api.c /src/matrix-http-client.c /src/matrix-compacts.c diff --git a/src/Makefile.am b/src/Makefile.am index 11f007f..a3c8f35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -19,7 +19,6 @@ libmatrix_glib_0_0_la_VALA_SOURCES = \ namespace-info.vala \ matrix-api.vala \ matrix-client.vala \ - matrix-types.vala \ matrix-http-api.vala \ matrix-http-client.vala \ matrix-compacts.vala \ @@ -114,7 +113,7 @@ $(libmatrix_glib_0_0_la_VALA_SOURCES:.vala=.c): vala-stamp bin_PROGRAMS = test-api-client test-client INST_H_SRC_FILES = \ - matrix-c-types.h \ + matrix-types.h \ utils.h \ $(NULL) @@ -125,7 +124,7 @@ INST_H_BUILT_FILES = \ $(NULL) matrix_enum_headers = \ - matrix-c-types.h \ + matrix-types.h \ $(NULL) libmatrix_glib_0_0_la_SOURCES = \ @@ -134,7 +133,7 @@ libmatrix_glib_0_0_la_SOURCES = \ $(libmatrix_glib_0_0_la_VALA_SOURCES:.vala=.c) \ matrix-event-types.c \ matrix-version.c \ - matrix-c-types.c \ + matrix-types.c \ utils.c \ matrix-enumtypes.c \ $(INST_H_SRC_FILES) \ diff --git a/src/matrix-c-types.c b/src/matrix-types.c similarity index 72% rename from src/matrix-c-types.c rename to src/matrix-types.c index 97e60fa..e7a45d3 100644 --- a/src/matrix-c-types.c +++ b/src/matrix-types.c @@ -17,7 +17,7 @@ */ #include "config.h" -#include "matrix-c-types.h" +#include "matrix-types.h" /** * SECTION:matrix-types @@ -1073,3 +1073,442 @@ matrix_image_info_differs(MatrixImageInfo *image_info, MatrixImageInfo *other) (image_info->height == other->height) || (g_strcmp0(image_info->mimetype, other->mimetype) != 0)); } + +struct _MatrixVideoInfo { + gssize size; + gchar *mimetype; + gint duration; + gint width; + gint height; + gchar *thumbnail_url; + MatrixImageInfo *thumbnail_info; + + volatile int refcount; +}; + +/** + * MatrixVideoInfo: (ref-func matrix_video_info_ref) (unref-func matrix_video_info_unref) + * + * Information about a video file referred to by an URL. + */ +G_DEFINE_BOXED_TYPE(MatrixVideoInfo, matrix_video_info, (GBoxedCopyFunc)matrix_video_info_ref, (GBoxedFreeFunc)matrix_video_info_unref); + +/** + * matrix_video_info_new: + * + * Create a new #MatrixVideoInfo object with a reference count of 1. + */ +MatrixVideoInfo * +matrix_video_info_new(void) +{ + MatrixVideoInfo *ret = g_new0(MatrixVideoInfo, 1); + + ret->refcount = 1; + ret->size = -1; + ret->duration = -1; + ret->width = -1; + ret->height = -1; + + return ret; +} + +/** + * matrix_video_info_ref: + * @video_info: a #MatrixVideoInfo object + * + * Increment reference count of @video_info by 1. + * + * Returns: (transfer full): @video_info + */ +MatrixVideoInfo * +matrix_video_info_ref(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, NULL); + + matrix_video_info->refcount++; + + return matrix_video_info; +} + +static void +matrix_video_info_destroy(MatrixVideoInfo *video_info) +{ + g_free(video_info->mimetype); + g_free(video_info->thumbnail_url); + matrix_image_info_unref(video_info->thumbnail_info); +} + +/** + * matrix_video_info_unref: + * @video_info: (transfer full): a #MatrixVideoInfo object + * + * Decrement reference count on @video_info by 1. + * + * If reference count reaches 0, the object is freed. + */ +void +matrix_video_info_unref(MatrixVideoInfo *matrix_video_info) +{ + g_return_if_fail(matrix_video_info != NULL); + + if (--(matrix_video_info->refcount) == 0) { + matrix_video_info_destroy(matrix_video_info); + g_free(matrix_video_info); + } +} + +/** + * matrix_video_info_set_size: + * @video_info: a #MatrixVideoInfo object + * @size: the size of the file, in bytes + * + * Set the size of the video file described by @video_info. + * + * -1 is considered an invalid value by matrix_video_info_get_json_node(), but can be set to + * indicate incompleteness. + */ +void +matrix_video_info_set_size(MatrixVideoInfo *matrix_video_info, gsize size) +{ + g_return_if_fail(matrix_video_info != NULL); + + matrix_video_info->size = size; +} + +/** + * matrix_video_info_get_size: + * @video_info: a #MatrixVideoInfo object + * + * Get the size of the video file described by @video_info, in bytes. + * + * Returns: the file size + */ +gsize +matrix_video_info_get_size(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, -1); + + return matrix_video_info->size; +} + +/** + * matrix_video_info_set_mimetype: + * @video_info: a #MatrixVideoInfo object + * @mimetype: (transfer none): a MIME type + * + * Set the MIME type of the video file described by @video_info. + * + * NULL is considered an invalid value by matrix_video_info_get_json_node(), but can be set to + * indicate incompleteness. + */ +void +matrix_video_info_set_mimetype(MatrixVideoInfo *matrix_video_info, const gchar *mimetype) +{ + g_return_if_fail(matrix_video_info != NULL); + + g_free(matrix_video_info->mimetype); + matrix_video_info->mimetype = g_strdup(mimetype); +} + +/** + * matrix_video_info_get_mimetype: + * @video_info: a #MatrixVideoInfo object + * + * Get the MIME type of the video file described by @video_info. + * + * Returns: (transfer none) (nullable): the MIME type, or %NULL if not set + */ +const gchar * +matrix_video_info_get_mimetype(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, NULL); + + return matrix_video_info->mimetype; +} + +/** + * matrix_video_info_set_duration: + * @video_info: a #MatrixVideoInfo object + * @duration: the duration of the video, in seconds + * + * Set the duration of the video file described by @video_info. + * + * -1 is considered an invalid value by matrix_video_info_get_json_node(), but can be set to + * indicate incompleteness. + */ +void +matrix_video_info_set_duration(MatrixVideoInfo *matrix_video_info, gint duration) +{ + g_return_if_fail(matrix_video_info != NULL); + + matrix_video_info->duration = duration; +} + +/** + * matrix_video_info_get_duration: + * @video_info: a #MatrixVideoInfo object + * + * Get the duration of the video file described by @video_info, in seconds. + * + * Returns: the duration + */ +gint +matrix_video_info_get_duration(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, -1); + + return matrix_video_info->duration; +} + +/** + * matrix_video_info_set_width: + * @video_info: a #MatrixVideoInfo object + * @width: the width of the video, in pixels + * + * Set the width of the video file described by @video_info. + * + * -1 is considered an invalid value by matrix_video_info_get_json_node(), but can be set to + * indicate incompleteness. + */ +void +matrix_video_info_set_width(MatrixVideoInfo *matrix_video_info, gint width) +{ + g_return_if_fail(matrix_video_info != NULL); + + matrix_video_info->width = width; +} + +/** + * matrix_video_info_get_width: + * @video_info: a #MatrixVideoInfo object + * + * Get the width of the video file described by @video_info, in pixels. + * + * Returns: the video width + */ +gint +matrix_video_info_get_width(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, -1); + + return matrix_video_info->width; +} + +/** + * matrix_video_info_set_height: + * @video_info: a #MatrixVideoInfo object + * @height: the height of the video, in pixels + * + * Set the width of the video file described by @video_info. + * + * -1 is considered an invalid value by matrix_video_info_get_json_node(), but can be set to + * indicate incompleteness. + */ +void +matrix_video_info_set_height(MatrixVideoInfo *matrix_video_info, gint height) +{ + g_return_if_fail(matrix_video_info != NULL); + + matrix_video_info->height = height; +} + +/** + * matrix_video_info_get_height: + * @video_info: a #MatrixVideoInfo object + * + * Get the height of the video file described by @video_info, in pixels. + * + * Returns: the video height + */ +gint +matrix_video_info_get_height(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, -1); + + return matrix_video_info->height; +} + +/** + * matrix_video_info_set_thumbnail_url: + * @video_info: a #MatrixVideoInfo object + * @thumbnail_url: (transfer none): the URL of the thumbnail image for the video + * + * Set the thumbnail image URL for the video described by @video_info. + */ +void +matrix_video_info_set_thumbnail_url(MatrixVideoInfo *matrix_video_info, const gchar *thumbnail_url) +{ + g_return_if_fail(matrix_video_info != NULL); + + g_free(matrix_video_info->thumbnail_url); + matrix_video_info->thumbnail_url = g_strdup(thumbnail_url); +} + +/** + * matrix_video_info_get_thumbnail_url: + * @video_info: a #MatrixVideoInfo object + * + * Get the thumbnail URL for the video described by @video_info. + * + * Returns: (transfer none) (nullable): the thumbnail URL + */ +const gchar * +matrix_video_info_get_thumbnail_url(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, NULL); + + return matrix_video_info->thumbnail_url; +} + +/** + * matrix_video_info_set_thumbnail_info: + * @video_info: a #MatrixVideoInfo object + * @thumbnail_info: (transfer none): a #MatrixImageInfo object describing the video’s thumbnail + * image + * + * Set the image info for the video’s thumbnail image, referred to by the URL set with + * matrix_video_info_set_thumbnail_url(). + */ +void +matrix_video_info_set_thumbnail_info(MatrixVideoInfo *matrix_video_info, const MatrixImageInfo *thumbnail_info) +{ + g_return_if_fail(matrix_video_info != NULL); + + matrix_image_info_unref(matrix_video_info->thumbnail_info); + matrix_video_info->thumbnail_info = matrix_image_info_ref((MatrixImageInfo *)thumbnail_info); +} + +/** + * matrix_video_info_get_thumbnail_info: + * @video_info: a #MatrixVideoInfo object + * + * Get the image info for the video’s thumbnail image, referred to by the URL that can be + * retrieved with matrix_video_info_get_thumbnail_url(). + * + * Returns: (transfer none): a #MatrixImageInfo object, or %NULL if not set + */ +const MatrixImageInfo * +matrix_video_info_get_thumbnail_info(MatrixVideoInfo *matrix_video_info) +{ + g_return_val_if_fail(matrix_video_info != NULL, NULL); + + return matrix_video_info->thumbnail_info; +} + +/** + * matrix_video_info_set_from_json: + * @video_info: A #MatrixVideoInfo object + * @json_data: (nullable): a #JsonNode object + * + * Load the data in @json_data into the fields of @video_info. @json_data must hold a valid + * Matrix video info object with a size, duration, width, height, and mimetype fields. + */ +void +matrix_video_info_set_from_json(MatrixVideoInfo *video_info, JsonNode *json_data) +{ + JsonObject *root = NULL; + JsonNode *node; + + root = json_node_get_object(json_data); + + if ((node = json_object_get_member(root, "size"))) { + video_info->size = json_node_get_int(node); + } else if (DEBUG) { + g_warning("size is missing from an VideoInfo"); + } + + if ((node = json_object_get_member(root, "mimetype"))) { + g_free(video_info->mimetype); + video_info->mimetype = g_strdup(json_node_get_string(node)); + } else if (DEBUG) { + g_warning("mimetype is missing from an VideoInfo"); + } + + if ((node = json_object_get_member(root, "duration"))) { + video_info->duration = json_node_get_int(node); + } else if (DEBUG) { + g_warning("duration is missing from an VideoInfo"); + } + + if ((node = json_object_get_member(root, "w"))) { + video_info->width = json_node_get_int(node); + } else if (DEBUG) { + g_warning("w is missing from a VideoInfo"); + } + + if ((node = json_object_get_member(root, "h"))) { + video_info->height = json_node_get_int(node); + } else if (DEBUG) { + g_warning("h is missing from a VideoInfo"); + } + + if ((node = json_object_get_member(root, "thumbnail_url"))) { + g_free(video_info->thumbnail_url); + video_info->thumbnail_url = g_strdup(json_node_get_string(node)); + } + + if ((node = json_object_get_member(root, "thumbnail_info"))) { + matrix_image_info_unref(video_info->thumbnail_info); + video_info->thumbnail_info = matrix_image_info_new(); + matrix_image_info_set_from_json(video_info->thumbnail_info, node); + } +} + +/** + * matrix_video_info_get_json_node: + * @video_info: a #MatrixImageInfo object + * @error: (nullable): a #GError, or NULL to ignore + * + * Convert @video_info to a #JsonNode. If the file size, duration, width, or height is negative, + * or the MIME type is not set, this function returns NULL and @error is set to + * #MATRIX_ERROR_INCOMPLETE. + * + * Returns: (transfer full) (nullable): a #JsonNode with a valid Matrix video info object, or NULL + * if any of the fields are invalid. + */ +JsonNode * +matrix_video_info_get_json_node(MatrixVideoInfo *video_info, GError **error) +{ + JsonNode *node; + JsonObject *obj; + + if ((video_info->size == -1) + || (video_info->mimetype == NULL) + || (video_info->duration == -1) + || (video_info->width == -1) + || (video_info->height == -1)) { + g_set_error(error, MATRIX_ERROR, MATRIX_ERROR_INCOMPLETE, + "Won't generate a VideoInfo without all the fields set."); + return NULL; + } + + node = json_node_new(JSON_NODE_OBJECT); + obj = json_object_new(); + json_node_set_object(node, obj); + + json_object_set_int_member(obj, "size", video_info->size); + json_object_set_string_member(obj, "mimetype", video_info->mimetype); + json_object_set_int_member(obj, "duration", (video_info->duration)); + json_object_set_int_member(obj, "w", video_info->width); + json_object_set_int_member(obj, "h", video_info->height); + + if(video_info->thumbnail_url && video_info->thumbnail_info) { + GError *here_error = NULL; + JsonNode *thumbnail_info = matrix_image_info_get_json_node(video_info->thumbnail_info, &here_error); + + if (here_error) { + g_propagate_error(error, here_error); + + json_node_free(node); + + return NULL; + } + + json_object_set_string_member(obj, "thumbnail_url", video_info->thumbnail_url); + json_object_set_member(obj, "thumbnail_info", thumbnail_info); + + json_node_unref(thumbnail_info); + } + + return node; +} diff --git a/src/matrix-c-types.h b/src/matrix-types.h similarity index 83% rename from src/matrix-c-types.h rename to src/matrix-types.h index 0dc5033..101f520 100644 --- a/src/matrix-c-types.h +++ b/src/matrix-types.h @@ -248,4 +248,29 @@ void matrix_image_info_set_from_json(MatrixImageInfo *image_info, JsonNode *json JsonNode *matrix_image_info_get_json_node(MatrixImageInfo *image_info, GError **error); gboolean matrix_image_info_differs(MatrixImageInfo *image_info, MatrixImageInfo *other); +typedef struct _MatrixVideoInfo MatrixVideoInfo; + +GType matrix_video_info_get_type(void) G_GNUC_CONST; +# define MATRIX_TYPE_VIDEO_INFO matrix_video_info_get_type() + +MatrixVideoInfo *matrix_video_info_new(void); +MatrixVideoInfo *matrix_video_info_ref(MatrixVideoInfo *video_info); +void matrix_video_info_unref(MatrixVideoInfo *video_info); +void matrix_video_info_set_size(MatrixVideoInfo *video_info, gsize size); +gsize matrix_video_info_get_size(MatrixVideoInfo *video_info); +void matrix_video_info_set_mimetype(MatrixVideoInfo *video_info, const gchar *mimetype); +const gchar *matrix_video_info_get_mimetype(MatrixVideoInfo *video_info); +void matrix_video_info_set_duration(MatrixVideoInfo *video_info, gint duration); +gint matrix_video_info_get_duration(MatrixVideoInfo *video_info); +void matrix_video_info_set_width(MatrixVideoInfo *video_info, gint width); +gint matrix_video_info_get_width(MatrixVideoInfo *video_info); +void matrix_video_info_set_height(MatrixVideoInfo *video_info, gint height); +gint matrix_video_info_get_height(MatrixVideoInfo *video_info); +void matrix_video_info_set_thumbnail_url(MatrixVideoInfo *video_info, const gchar *thumbnail_url); +const gchar *matrix_video_info_get_thumbnail_url(MatrixVideoInfo *video_info); +void matrix_video_info_set_thumbnail_info(MatrixVideoInfo *video_info, const MatrixImageInfo *thumbnail_info); +const MatrixImageInfo *matrix_video_info_get_thumbnail_info(MatrixVideoInfo *video_info); +void matrix_video_info_set_from_json(MatrixVideoInfo *video_info, JsonNode *json_data); +JsonNode *matrix_video_info_get_json_node(MatrixVideoInfo *video_info, GError **error); + #endif /* __MATRIX_TYPE_H__ */ diff --git a/src/matrix-types.vala b/src/matrix-types.vala deleted file mode 100644 index 8fcb38e..0000000 --- a/src/matrix-types.vala +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This file is part of matrix-glib-sdk - * - * matrix-glib-sdk is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * matrix-glib-sdk is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with matrix-glib-sdk. If not, see - * . - */ - -namespace Matrix { - public struct VideoInfo { - int? size; - string? mimetype; - int? duration; - int? width; - int? height; - string? thumbnail_url; - ImageInfo? thumbnail_info; - - public void - set_from_json(Json.Node json_data) - { - size = null; - mimetype = null; - duration = null; - - var root = json_data.get_object(); - Json.Node? node; - - if ((node = root.get_member("size")) != null) { - size = (int)node.get_int(); - } else if (Config.DEBUG) { - warning("size is missing from an VideoInfo"); - } - - if ((node = root.get_member("mimetype")) != null) { - mimetype = node.get_string(); - } else if (Config.DEBUG) { - warning("mimetype is missing from an VideoInfo"); - } - - if ((node = root.get_member("duration")) != null) { - duration = (int)node.get_int(); - } else if (Config.DEBUG) { - warning("duration is missing from an VideoInfo"); - } - - if ((node = root.get_member("w")) != null) { - width = (int)node.get_int(); - } else if (Config.DEBUG) { - warning("w is missing from a VideoInfo"); - } - - if ((node = root.get_member("h")) != null) { - height = (int)node.get_int(); - } else if (Config.DEBUG) { - warning("h is missing from a VideoInfo"); - } - - if ((node = root.get_member("thumbnail_url")) != null) { - thumbnail_url = node.get_string(); - } - - if ((node = root.get_member("thumbnail_info")) != null) { - thumbnail_info = ImageInfo(); - thumbnail_info.set_from_json(node); - } - } - - public Json.Node - get_json_node() - throws Matrix.Error - { - if ((size == null) - || (mimetype == null) - || (duration == null) - || (width == null) - || (height == null) - || (thumbnail_url == null) - || (thumbnail_info == null)) { - throw new Matrix.Error.INCOMPLETE( - "Won't generate an ImageInfo without all fields set."); - } - - var node = new Json.Node(Json.NodeType.OBJECT); - var obj = new Json.Object(); - node.set_object(obj); - - obj.set_int_member("size", size); - obj.set_string_member("mimetype", mimetype); - obj.set_int_member("duration", duration); - obj.set_int_member("w", width); - obj.set_int_member("h", height); - obj.set_string_member("thumbnail_url", thumbnail_url); - obj.set_member("thumbnail_info", thumbnail_info.get_json_node()); - - return node; - } - } -} diff --git a/vapi/c-api.vapi b/vapi/c-api.vapi index 44aaf47..7ab59b1 100644 --- a/vapi/c-api.vapi +++ b/vapi/c-api.vapi @@ -204,7 +204,7 @@ namespace Matrix { ANSWER; } - [CCode (cheader_filename = "matrix-c-types.h")] + [CCode (cheader_filename = "matrix-types.h")] public struct FileInfo { public void set_size(ssize size); public ssize get_size(); @@ -218,7 +218,7 @@ namespace Matrix { throws Matrix.Error; } - [CCode (cheader_filename = "matrix-c-types.h")] + [CCode (cheader_filename = "matrix-types.h")] public struct AudioInfo { public ssize get_size(); public void set_size(ssize size); @@ -235,7 +235,7 @@ namespace Matrix { throws Matrix.Error; } - [CCode (cheader_filename = "matrix-c-types.h")] + [CCode (cheader_filename = "matrix-types.h")] public struct ImageInfo { public ssize get_size(); public void set_size(ssize size); @@ -253,6 +253,37 @@ namespace Matrix { public bool differs(ImageInfo other); } + [CCode (cheader_filename = "matrix-types.h")] + public struct VideoInfo { + public ssize get_size(); + public void set_size(ssize size); + + public string? get_mimetype(); + public void set_mimetype(string? mimetype); + + public int get_duration(); + public void set_duration(int duration); + + public int get_width(); + public void set_width(int witdh); + + public int get_height(); + public void set_height(int height); + + public string? get_thumbnail_url(); + public void set_thumbnail_url(); + + public ImageInfo? get_thumbnail_info(); + public void set_image_info(ImageInfo? image_info); + + public void + set_from_json(Json.Node json_data); + + public Json.Node + get_json_node() + throws Matrix.Error; + } + /* Utilities */ [CCode (cheader_filename = "utils.h", cname = "_matrix_g_enum_to_string")] public string? _g_enum_value_to_nick(GLib.Type enum_type, int value, bool convert_dashes = true);