/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