/dev/tomkiewicz/new-smileys: 2aa79f05247e: Custom smileys storage
Tomasz Wasilczyk
twasilczyk at pidgin.im
Tue Apr 1 19:08:26 EDT 2014
Changeset: 2aa79f05247ea0369bc638ceff423e720b147993
Author: Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date: 2014-04-02 01:08 +0200
Branch: default
URL: https://hg.pidgin.im/dev/tomkiewicz/new-smileys/rev/2aa79f05247e
Description:
Custom smileys storage
diffstat:
libpurple/Makefile.am | 2 +
libpurple/core.c | 7 +-
libpurple/imgstore.h | 3 +-
libpurple/smiley-custom.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++
libpurple/smiley-custom.h | 46 +++++++
5 files changed, 338 insertions(+), 4 deletions(-)
diffs (truncated from 403 to 300 lines):
diff --git a/libpurple/Makefile.am b/libpurple/Makefile.am
--- a/libpurple/Makefile.am
+++ b/libpurple/Makefile.am
@@ -101,6 +101,7 @@ purple_coresources = \
savedstatuses.c \
server.c \
signals.c \
+ smiley-custom.c \
smiley-list.c \
smiley-parser.c \
smiley-theme.c \
@@ -179,6 +180,7 @@ purple_coreheaders = \
savedstatuses.h \
server.h \
signals.h \
+ smiley-custom.h \
smiley-list.h \
smiley-parser.h \
smiley-theme.h \
diff --git a/libpurple/core.c b/libpurple/core.c
--- a/libpurple/core.c
+++ b/libpurple/core.c
@@ -41,6 +41,7 @@
#include "proxy.h"
#include "savedstatuses.h"
#include "signals.h"
+#include "smiley-custom.h"
#include "smiley-theme.h"
#include "sound.h"
#include "sound-theme-loader.h"
@@ -202,9 +203,8 @@ purple_core_init(const char *ui)
purple_xfers_init();
purple_idle_init();
purple_http_init();
-#if 0
- purple_smileys_init();
-#endif
+ purple_smiley_custom_init();
+
/*
* Call this early on to try to auto-detect our IP address and
* hopefully save some time later.
@@ -257,6 +257,7 @@ purple_core_quit(void)
/* Save .xml files, remove signals, etc. */
purple_smiley_theme_uninit();
+ purple_smiley_custom_uninit();
purple_http_uninit();
purple_idle_uninit();
purple_pounces_uninit();
diff --git a/libpurple/imgstore.h b/libpurple/imgstore.h
--- a/libpurple/imgstore.h
+++ b/libpurple/imgstore.h
@@ -45,7 +45,8 @@
*/
typedef struct _PurpleStoredImage PurpleStoredImage;
-#define PURPLE_TYPE_STORED_IMAGE (purple_imgstore_get_type())
+#define PURPLE_TYPE_STORED_IMAGE (purple_imgstore_get_type())
+#define PURPLE_IS_STORED_IMAGE(image) (G_TYPE_CHECK_INSTANCE_TYPE((image), PURPLE_TYPE_STORED_IMAGE))
G_BEGIN_DECLS
diff --git a/libpurple/smiley-custom.c b/libpurple/smiley-custom.c
new file mode 100644
--- /dev/null
+++ b/libpurple/smiley-custom.c
@@ -0,0 +1,284 @@
+/* purpleOB
+ *
+ * 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 "smiley-custom.h"
+
+#include "debug.h"
+
+#include <glib/gstdio.h>
+
+#define SMILEYS_DEFAULT_FOLDER "custom_smiley"
+#define SMILEYS_INDEX_FILE "smileys.xml"
+
+static gchar *smileys_dir;
+static gchar *smileys_index;
+
+static PurpleTrie *smileys_trie;
+static GHashTable *smileys_table;
+static gboolean disable_write = FALSE;
+
+/*******************************************************************************
+ * XML storage
+ ******************************************************************************/
+
+static void
+purple_smiley_custom_load(void)
+{
+ PurpleXmlNode *root_node, *profile_node, *smileyset_node, *smiley_node;
+ int got_smileys = 0;
+
+ if (!g_file_test(smileys_index, G_FILE_TEST_EXISTS))
+ return;
+
+ root_node = purple_xmlnode_from_file(g_path_get_dirname(smileys_index),
+ g_path_get_basename(smileys_index),
+ "custom smileys index", "smiley-custom");
+ g_return_if_fail(root_node);
+
+ profile_node = purple_xmlnode_get_child(root_node, "profile");
+ if (!profile_node) {
+ purple_xmlnode_free(root_node);
+ g_return_if_fail(profile_node);
+ }
+
+ smileyset_node = purple_xmlnode_get_child(profile_node, "smiley_set");
+ if (!smileyset_node) {
+ purple_xmlnode_free(root_node);
+ g_return_if_fail(smileyset_node);
+ }
+
+ smiley_node = purple_xmlnode_get_child(smileyset_node, "smiley");
+ while (smiley_node) {
+ const gchar *shortcut, *file_name;
+
+ shortcut = purple_xmlnode_get_attrib(smiley_node, "shortcut");
+ file_name = purple_xmlnode_get_attrib(smiley_node, "filename");
+
+ if (shortcut && file_name) {
+ PurpleSmiley *smiley;
+ gchar *file_path = g_build_filename(
+ smileys_dir, file_name, NULL);
+
+ got_smileys++;
+ smiley = purple_smiley_new(shortcut, file_path);
+ g_free(file_path);
+
+ g_hash_table_insert(smileys_table,
+ g_strdup(shortcut), smiley);
+ }
+
+ smiley_node = purple_xmlnode_get_next_twin(smiley_node);
+ }
+
+ purple_xmlnode_free(root_node);
+
+ purple_debug_info("smiley-custom", "Loaded %d custom smiley(s)",
+ got_smileys);
+}
+
+static PurpleXmlNode *
+smileys_to_xmlnode(void)
+{
+ PurpleXmlNode *root_node, *profile_node, *smileyset_node;
+ GHashTableIter it;
+ gpointer value;
+
+ root_node = purple_xmlnode_new("smileys");
+ purple_xmlnode_set_attrib(root_node, "version", "1.0");
+
+ profile_node = purple_xmlnode_new("profile");
+ purple_xmlnode_insert_child(root_node, profile_node);
+ purple_xmlnode_set_attrib(profile_node, "name", "Default");
+
+ smileyset_node = purple_xmlnode_new("smiley_set");
+ purple_xmlnode_insert_child(profile_node, smileyset_node);
+
+ g_hash_table_iter_init(&it, smileys_table);
+ while (g_hash_table_iter_next(&it, NULL, &value)) {
+ PurpleSmiley *smiley = PURPLE_SMILEY(value);
+ PurpleXmlNode *smiley_node;
+
+ smiley_node = purple_xmlnode_new("smiley");
+ purple_xmlnode_set_attrib(smiley_node, "shortcut",
+ purple_smiley_get_shortcut(smiley));
+ purple_xmlnode_set_attrib(smiley_node, "filename",
+ g_path_get_basename(purple_smiley_get_path(smiley)));
+ }
+
+ return root_node;
+}
+
+static void
+purple_smiley_custom_save(void)
+{
+ PurpleXmlNode *root_node;
+ gchar *data;
+ GError *error = NULL;
+
+ if (disable_write)
+ return;
+
+ root_node = smileys_to_xmlnode();
+ g_return_if_fail(root_node != NULL);
+
+ data = purple_xmlnode_to_formatted_str(root_node, NULL);
+ g_return_if_fail(data != NULL);
+
+ g_file_set_contents(smileys_index, data, -1, &error);
+
+ g_free(data);
+ purple_xmlnode_free(root_node);
+
+ if (error) {
+ purple_debug_error("smiley-custom",
+ "Error writting custom smileys xml file");
+ }
+}
+
+static gchar *
+purple_smiley_custom_img_checksum(PurpleStoredImage *img)
+{
+ g_return_val_if_fail(PURPLE_IS_STORED_IMAGE(img), NULL);
+
+ return g_compute_checksum_for_data(G_CHECKSUM_SHA1,
+ purple_imgstore_get_data(img),
+ purple_imgstore_get_size(img));
+}
+
+
+/*******************************************************************************
+ * API implementation
+ ******************************************************************************/
+
+PurpleSmiley *
+purple_smiley_custom_add(PurpleStoredImage *img, const gchar *shortcut)
+{
+ PurpleSmiley *existing_smiley, *smiley;
+ gchar *checksum, *file_path;
+ gchar file_name[256];
+ const gchar *file_ext;
+ GError *error = NULL;
+
+ g_return_val_if_fail(PURPLE_IS_STORED_IMAGE(img), NULL);
+
+ existing_smiley = g_hash_table_lookup(smileys_table, shortcut);
+
+ g_object_ref(img);
+
+ if (existing_smiley) {
+ disable_write = TRUE;
+ purple_smiley_custom_remove(existing_smiley);
+ disable_write = FALSE;
+ }
+
+ checksum = purple_smiley_custom_img_checksum(img);
+ file_ext = purple_imgstore_get_extension(img);
+ if (file_ext == NULL || g_strcmp0("icon", file_ext) == 0) {
+ purple_debug_warning("smiley-custom", "Invalid image type");
+ return NULL;
+ }
+
+ g_snprintf(file_name, sizeof(file_name), "%s.%s", checksum, file_ext);
+ file_path = g_build_filename(smileys_dir, file_name, NULL);
+
+ g_file_set_contents(file_path, purple_imgstore_get_data(img),
+ purple_imgstore_get_size(img), &error);
+
+ g_free(checksum);
+ g_object_unref(img);
+
+ if (error) {
+ purple_debug_error("smiley-custom", "Failed writing smiley "
+ "file %s: %s", file_path, error->message);
+ g_free(file_path);
+ return NULL;
+ }
+
+ smiley = purple_smiley_new(shortcut, file_path);
+ g_free(file_path);
+
+ g_hash_table_insert(smileys_table, g_strdup(shortcut), smiley);
+ purple_smiley_custom_save();
+
+ return smiley;
+}
+
+void
+purple_smiley_custom_remove(PurpleSmiley *smiley)
+{
+ PurpleSmiley *existing_smiley;
+ const gchar *smiley_shortcut;
+
+ g_return_if_fail(PURPLE_IS_SMILEY(smiley));
+
+ smiley_shortcut = purple_smiley_get_shortcut(smiley);
More information about the Commits
mailing list