/pidgin/main: 2c21828e7442: PurpleImage: initial implementation
Tomasz Wasilczyk
twasilczyk at pidgin.im
Wed Apr 9 12:05:39 EDT 2014
Changeset: 2c21828e7442d5cc1de149605b902c12a633d533
Author: Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date: 2014-04-09 18:05 +0200
Branch: default
URL: https://hg.pidgin.im/pidgin/main/rev/2c21828e7442
Description:
PurpleImage: initial implementation
diffstat:
libpurple/Makefile.am | 2 +
libpurple/Makefile.mingw | 1 +
libpurple/image.c | 387 +++++++++++++++++++++++++++++++++++++++++++++++
libpurple/image.h | 110 +++++++++++++
4 files changed, 500 insertions(+), 0 deletions(-)
diffs (truncated from 537 to 300 lines):
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -71,6 +71,7 @@ purple_coresources = \
eventloop.c \
http.c \
idle.c \
+ image.c \
imgstore.c \
keyring.c \
log.c \
@@ -155,6 +156,7 @@ purple_coreheaders = \
eventloop.h \
http.h \
idle.h \
+ image.h \
imgstore.h \
keyring.h \
log.h \
diff --git a/libpurple/Makefile.mingw b/libpurple/Makefile.mingw
--- a/libpurple/Makefile.mingw
+++ b/libpurple/Makefile.mingw
@@ -95,6 +95,7 @@ C_SRC = \
eventloop.c \
http.c \
idle.c \
+ image.c \
imgstore.c \
keyring.c \
log.c \
diff --git a/libpurple/image.c b/libpurple/image.c
new file mode 100644
--- /dev/null
+++ b/libpurple/image.c
@@ -0,0 +1,387 @@
+/* purple
+ *
+ * Purple is the legal property of its developers, whose names are too numerous
+ * to list here. Please refer to the COPYRIGHT file distributed with this
+ * source distribution.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include "internal.h"
+#include "glibcompat.h"
+
+#include "debug.h"
+#include "image.h"
+
+#define PURPLE_IMAGE_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_IMAGE, PurpleImagePrivate))
+
+typedef struct {
+ gchar *path;
+ GString *contents;
+
+ gboolean is_ready;
+ gboolean has_failed;
+} PurpleImagePrivate;
+
+enum
+{
+ PROP_0,
+ PROP_IS_READY,
+ PROP_HAS_FAILED,
+ PROP_LAST
+};
+
+enum
+{
+ SIG_READY,
+ SIG_FAILED,
+ SIG_LAST
+};
+
+static guint signals[SIG_LAST];
+static GParamSpec *properties[PROP_LAST];
+
+/******************************************************************************
+ * Internal logic
+ ******************************************************************************/
+
+static void
+has_failed(PurpleImage *image)
+{
+ gboolean ready_changed;
+ PurpleImagePrivate *priv;
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
+
+ g_return_if_fail(!priv->has_failed);
+
+ priv->has_failed = TRUE;
+ ready_changed = (priv->is_ready != FALSE);
+ priv->is_ready = FALSE;
+
+ if (priv->contents) {
+ g_string_free(priv->contents, TRUE);
+ priv->contents = NULL;
+ }
+
+ if (ready_changed) {
+ g_object_notify_by_pspec(G_OBJECT(image),
+ properties[PROP_IS_READY]);
+ }
+ g_object_notify_by_pspec(G_OBJECT(image), properties[PROP_HAS_FAILED]);
+ g_signal_emit(image, signals[SIG_FAILED], 0);
+}
+
+static void
+became_ready(PurpleImage *image)
+{
+ PurpleImagePrivate *priv;
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
+
+ g_return_if_fail(!priv->has_failed);
+ g_return_if_fail(!priv->is_ready);
+
+ priv->is_ready = TRUE;
+
+ g_object_notify_by_pspec(G_OBJECT(image), properties[PROP_IS_READY]);
+ g_signal_emit(image, signals[SIG_READY], 0);
+}
+
+static void
+steal_contents(PurpleImagePrivate *priv, gpointer data, gsize length)
+{
+ g_return_if_fail(priv != NULL);
+ g_return_if_fail(priv->contents == NULL);
+ g_return_if_fail(data != NULL);
+ g_return_if_fail(length > 0);
+
+ priv->contents = g_string_new(NULL);
+ g_free(priv->contents->str);
+ priv->contents->str = data;
+ priv->contents->len = priv->contents->allocated_len = length;
+}
+
+static void
+fill_data(PurpleImage *image)
+{
+ PurpleImagePrivate *priv;
+ GError *error = NULL;
+ gchar *contents;
+ gsize length;
+
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
+ if (priv->contents)
+ return;
+
+ if (!priv->is_ready)
+ return;
+
+ g_return_if_fail(priv->path);
+ g_file_get_contents(priv->path, &contents, &length, &error);
+ if (error) {
+ purple_debug_error("image", "failed to read '%s' image: %s",
+ priv->path, error->message);
+ g_error_free(error);
+
+ has_failed(image);
+ return;
+ }
+
+ steal_contents(priv, contents, length);
+}
+
+
+/******************************************************************************
+ * API implementation
+ ******************************************************************************/
+
+PurpleImage *
+purple_image_new_from_file(const gchar *path)
+{
+ g_return_val_if_fail(path != NULL, NULL);
+ g_return_val_if_fail(g_file_test(path, G_FILE_TEST_EXISTS), NULL);
+
+ return g_object_new(PURPLE_TYPE_IMAGE,
+ "path", path,
+ NULL);
+}
+
+PurpleImage *
+purple_image_new_from_data(gpointer data, gsize length)
+{
+ PurpleImage *img;
+ PurpleImagePrivate *priv;
+
+ g_return_val_if_fail(data != NULL, NULL);
+ g_return_val_if_fail(length > 0, NULL);
+
+ img = g_object_new(PURPLE_TYPE_IMAGE, NULL);
+ priv = PURPLE_IMAGE_GET_PRIVATE(img);
+
+ steal_contents(priv, data, length);
+
+ return img;
+}
+
+PurpleImage *
+purple_image_transfer_new(void)
+{
+ PurpleImage *img;
+ PurpleImagePrivate *priv;
+
+ img = g_object_new(PURPLE_TYPE_IMAGE, NULL);
+ priv = PURPLE_IMAGE_GET_PRIVATE(img);
+
+ priv->is_ready = FALSE;
+ priv->contents = g_string_new(NULL);
+
+ return img;
+}
+
+gsize
+purple_image_get_data_size(PurpleImage *image)
+{
+ PurpleImagePrivate *priv;
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
+
+ g_return_val_if_fail(priv != NULL, 0);
+ g_return_val_if_fail(priv->is_ready, 0);
+
+ fill_data(image);
+ g_return_val_if_fail(priv->contents, 0);
+
+ return priv->contents->len;
+}
+
+gpointer
+purple_image_get_data(PurpleImage *image)
+{
+ PurpleImagePrivate *priv;
+ priv = PURPLE_IMAGE_GET_PRIVATE(image);
+
+ g_return_val_if_fail(priv != NULL, NULL);
+ g_return_val_if_fail(priv->is_ready, NULL);
+
+ fill_data(image);
+ g_return_val_if_fail(priv->contents, NULL);
+
+ return priv->contents->str;
+}
+
+void
+purple_image_transfer_write(PurpleImage *image, const gpointer data,
+ gsize length)
+{
+ PurpleImagePrivate *priv =
+ PURPLE_IMAGE_GET_PRIVATE(image);
+
+ g_return_if_fail(priv != NULL);
+ g_return_if_fail(!priv->has_failed);
+ g_return_if_fail(!priv->is_ready);
+ g_return_if_fail(priv->contents != NULL);
+ g_return_if_fail(data != NULL || length == 0);
+
+ if (length == 0)
+ return;
+
+ g_string_append_len(priv->contents, (const gchar*)data, length);
+}
+
+void
+purple_image_transfer_close(PurpleImage *image)
+{
+ PurpleImagePrivate *priv =
+ PURPLE_IMAGE_GET_PRIVATE(image);
+
+ g_return_if_fail(priv != NULL);
+ g_return_if_fail(!priv->has_failed);
+ g_return_if_fail(!priv->is_ready);
+ g_return_if_fail(priv->contents != NULL);
+
+ if (priv->contents->len == 0) {
+ purple_debug_error("image", "image is empty");
+ has_failed(image);
+ return;
+ }
+
+ became_ready(image);
+}
+
+void
+purple_image_transfer_failed(PurpleImage *image)
+{
+ PurpleImagePrivate *priv =
More information about the Commits
mailing list