libpurple/smiley-remote.c

Fri, 04 Apr 2014 20:30:07 +0200

author
Tomasz Wasilczyk <twasilczyk@pidgin.im>
date
Fri, 04 Apr 2014 20:30:07 +0200
changeset 35753
222e69060b4a
parent 35749
d71c41a54bb3
child 35755
d91c44b4a8e6
permissions
-rw-r--r--

Remote smileys: display them even on the first time

/* 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 "smiley.h"
#include "smiley-remote.h"

#define PURPLE_REMOTE_SMILEY_GET_PRIVATE(obj) \
	(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_REMOTE_SMILEY, PurpleRemoteSmileyPrivate))

typedef struct {
	GString *contents;
	PurpleStoredImage *image; /* it's not the same as in parent */

	gboolean failed;
} PurpleRemoteSmileyPrivate;

#if 0
enum
{
	PROP_0,
	PROP_LAST
};
#endif

enum
{
	SIG_FAILED,
	SIG_LAST
};

static GObjectClass *parent_class;

static guint signals[SIG_LAST];
#if 0
static GParamSpec *properties[PROP_LAST];
#endif

/******************************************************************************
 * API implementation
 ******************************************************************************/

void
purple_remote_smiley_write(PurpleRemoteSmiley *smiley, const guchar *data,
	gsize size)
{
	PurpleRemoteSmileyPrivate *priv =
		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);

	g_return_if_fail(priv != NULL);
	g_return_if_fail(!priv->failed);
	g_return_if_fail(!purple_smiley_is_ready(PURPLE_SMILEY(smiley)));
	g_return_if_fail(data != NULL || size == 0);

	if (size == 0)
		return;

	g_string_append_len(priv->contents, (const gchar*)data, size);
}

void
purple_remote_smiley_close(PurpleRemoteSmiley *smiley)
{
	PurpleRemoteSmileyPrivate *priv =
		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);

	g_return_if_fail(priv != NULL);
	g_return_if_fail(!priv->failed);
	g_return_if_fail(!purple_smiley_is_ready(PURPLE_SMILEY(smiley)));
	g_return_if_fail(priv->contents != NULL);
	g_return_if_fail(priv->image == NULL);

	if (priv->contents->len == 0) {
		purple_debug_error("smiley-remote", "Smiley is empty");
		purple_remote_smiley_failed(smiley);
		return;
	}

	priv->image = purple_imgstore_new(priv->contents->str,
		priv->contents->len, NULL);
	g_return_if_fail(priv->image != NULL);
	g_string_free(priv->contents, FALSE);
	priv->contents = NULL;

	g_object_set(smiley, "is-ready", TRUE, NULL);
	g_signal_emit_by_name(smiley, "ready");
}

void
purple_remote_smiley_failed(PurpleRemoteSmiley *smiley)
{
	PurpleRemoteSmileyPrivate *priv =
		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);

	g_return_if_fail(priv != NULL);
	g_return_if_fail(!purple_smiley_is_ready(PURPLE_SMILEY(smiley)));

	if (priv->failed)
		return;

	g_object_set(smiley, "failed", TRUE, NULL);
	g_signal_emit(smiley, signals[SIG_FAILED], 0);
}

static PurpleStoredImage *
purple_remote_smiley_get_image_impl(PurpleSmiley *smiley)
{
	PurpleRemoteSmileyPrivate *priv =
		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);

	g_return_val_if_fail(priv != NULL, FALSE);

	if (purple_smiley_get_path(smiley))
		return PURPLE_SMILEY_CLASS(parent_class)->get_image(smiley);

	if (!priv->image) {
		purple_debug_error("smiley-remote",
			"Remote smiley is not ready yet");
		return NULL;
	}

	return priv->image;
}

/******************************************************************************
 * Object stuff
 ******************************************************************************/

static void
purple_remote_smiley_init(GTypeInstance *instance, gpointer klass)
{
	PurpleRemoteSmiley *smiley = PURPLE_REMOTE_SMILEY(instance);
	PurpleRemoteSmileyPrivate *priv =
		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);

	priv->contents = g_string_new(NULL);
}

static void
purple_remote_smiley_finalize(GObject *obj)
{
	PurpleRemoteSmiley *smiley = PURPLE_REMOTE_SMILEY(obj);
	PurpleRemoteSmileyPrivate *priv =
		PURPLE_REMOTE_SMILEY_GET_PRIVATE(smiley);

	if (priv->contents)
		g_string_free(priv->contents, TRUE);
	if (priv->image)
		purple_imgstore_unref(priv->image);

	G_OBJECT_CLASS(parent_class)->finalize(obj);
}

#if 0
static void
purple_remote_smiley_get_property(GObject *object, guint par_id, GValue *value,
	GParamSpec *pspec)
{
	PurpleRemoteSmiley *remote_smiley = PURPLE_REMOTE_SMILEY(object);
	PurpleRemoteSmileyPrivate *priv = PURPLE_REMOTE_SMILEY_GET_PRIVATE(remote_smiley);

	switch (par_id) {
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
			break;
	}
}

static void
purple_remote_smiley_set_property(GObject *object, guint par_id, const GValue *value,
	GParamSpec *pspec)
{
	PurpleRemoteSmiley *remote_smiley = PURPLE_REMOTE_SMILEY(object);
	PurpleRemoteSmileyPrivate *priv = PURPLE_REMOTE_SMILEY_GET_PRIVATE(remote_smiley);

	switch (par_id) {
		default:
			G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
			break;
	}
}
#endif

static void
purple_remote_smiley_class_init(PurpleRemoteSmileyClass *klass)
{
	GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
	PurpleSmileyClass *ps_class = PURPLE_SMILEY_CLASS(klass);

	parent_class = g_type_class_peek_parent(klass);

	g_type_class_add_private(klass, sizeof(PurpleRemoteSmileyPrivate));

	gobj_class->finalize = purple_remote_smiley_finalize;

	ps_class->get_image = purple_remote_smiley_get_image_impl;

#if 0
	gobj_class->get_property = purple_remote_smiley_get_property;
	gobj_class->set_property = purple_remote_smiley_set_property;

	g_object_class_install_properties(gobj_class, PROP_LAST, properties);
#endif

	signals[SIG_FAILED] = g_signal_new("failed", G_OBJECT_CLASS_TYPE(klass),
		0, 0, NULL, NULL,
		g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}

GType
purple_remote_smiley_get_type(void)
{
	static GType type = 0;

	if (G_UNLIKELY(type == 0)) {
		static const GTypeInfo info = {
			.class_size = sizeof(PurpleRemoteSmileyClass),
			.class_init = (GClassInitFunc)purple_remote_smiley_class_init,
			.instance_size = sizeof(PurpleRemoteSmiley),
			.instance_init = purple_remote_smiley_init,
		};

		type = g_type_register_static(PURPLE_TYPE_SMILEY,
			"PurpleRemoteSmiley", &info, 0);
	}

	return type;
}

mercurial