summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2009-11-05 21:49:38 +0000
committerBastien Nocera <hadess@hadess.net>2009-11-09 19:04:18 +0000
commitcc467bfa5259c1fdb31a54398cd6a4b6085e1fb2 (patch)
tree745bea765d32e12c4e798bc97e4e08e55da6c709 /common
parent92c179d6ce2682595e7ce1a77e301ffc49e25526 (diff)
downloadgvfs-cc467bfa5259c1fdb31a54398cd6a4b6085e1fb2.tar.gz
[common] Loading icon and title on Blu-ray video discs
Using the BDMV/META/DL/bdmt_eng.xml file on BDMV discs, we can load better names and icons for the disc. Adds expat requirement to the common library if it is found. https://bugzilla.gnome.org/show_bug.cgi?id=600887
Diffstat (limited to 'common')
-rw-r--r--common/Makefile.am7
-rw-r--r--common/gvfsmountinfo.c250
-rw-r--r--common/gvfsmountinfo.h10
3 files changed, 264 insertions, 3 deletions
diff --git a/common/Makefile.am b/common/Makefile.am
index 35d6f2d0..ccece5ee 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -4,7 +4,7 @@ lib_LTLIBRARIES=libgvfscommon.la
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \
-I$(top_srcdir)/daemon \
- $(GLIB_CFLAGS) $(DBUS_CFLAGS) \
+ $(GLIB_CFLAGS) $(DBUS_CFLAGS) $(EXPAT_CFLAGS) \
-DG_LOG_DOMAIN=\"GVFS\" -DG_DISABLE_DEPRECATED \
-DDBUS_API_SUBJECT_TO_CHANGE
@@ -25,8 +25,9 @@ libgvfscommon_la_SOURCES = \
libgvfscommon_la_LDFLAGS = -no-undefined
libgvfscommon_la_LIBADD = \
- $(DBUS_LIBS) \
- $(GLIB_LIBS)
+ $(DBUS_LIBS) \
+ $(GLIB_LIBS) \
+ $(EXPAT_LIBS)
if HAVE_AVAHI
lib_LTLIBRARIES += libgvfscommon-dnssd.la
diff --git a/common/gvfsmountinfo.c b/common/gvfsmountinfo.c
index 6522d19a..3ebbef86 100644
--- a/common/gvfsmountinfo.c
+++ b/common/gvfsmountinfo.c
@@ -25,6 +25,10 @@
#include <string.h>
#include <glib/gi18n-lib.h>
+#ifdef HAVE_EXPAT
+#include <expat.h>
+#endif
+
#include "gvfsmountinfo.h"
#define VOLUME_INFO_GROUP "Volume Info"
@@ -419,6 +423,252 @@ GIcon *g_vfs_mount_info_query_xdg_volume_info_finish (GFile *directory,
/* ---------------------------------------------------------------------------------------------------- */
+#ifdef HAVE_EXPAT
+
+typedef struct {
+ gboolean in_name;
+ char *name;
+ const char *icon_path;
+ gboolean image_is_small;
+} BdmvParseData;
+
+static void
+bdmt_parse_start_tag (void *data,
+ const gchar *element_name,
+ const gchar **attr)
+{
+ BdmvParseData *bdata = (BdmvParseData *) data;
+ const char *image;
+ gboolean image_small;
+ gint i;
+
+ if (g_str_equal (element_name, "di:name"))
+ {
+ bdata->in_name = TRUE;
+ return;
+ }
+
+ if (g_str_equal (element_name, "di:thumbnail") == FALSE)
+ return;
+
+ image = NULL;
+ image_small = FALSE;
+
+ for (i = 0; attr[i]; ++i)
+ {
+ const char *name;
+ const char *value;
+
+ name = attr[i];
+ value = attr[++i];
+
+ if (g_str_equal (name, "href"))
+ {
+ image = value;
+ }
+ else if (g_str_equal (name, "size") && value)
+ {
+ image_small = g_str_equal (value, "416x240");
+ }
+ }
+
+ if (bdata->icon_path == NULL)
+ {
+ bdata->icon_path = image;
+ bdata->image_is_small = image_small;
+ return;
+ }
+
+ if (image != NULL &&
+ bdata->icon_path != NULL &&
+ bdata->image_is_small != FALSE)
+ {
+ bdata->icon_path = image;
+ bdata->image_is_small = image_small;
+ }
+}
+
+static void
+bdmt_parse_end_tag (void *data,
+ const gchar *element_name)
+{
+ BdmvParseData *bdata = (BdmvParseData *) data;
+
+ if (g_str_equal (element_name, "di:name"))
+ bdata->in_name = FALSE;
+}
+
+static void
+bdmt_parse_text (void *data,
+ const XML_Char *text,
+ int text_len)
+{
+ BdmvParseData *bdata = (BdmvParseData *) data;
+
+ if (bdata->in_name == FALSE)
+ return;
+
+ bdata->name = g_strndup (text, text_len);
+}
+
+static void
+on_bdmv_volume_info_loaded (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+ GFile *bdmt_volume_info_file;
+ gchar *content;
+ gsize content_length;
+ GError *error;
+ BdmvParseData data;
+ XML_Parser parser;
+ const gchar *icon_file;
+ GIcon *icon;
+
+ content = NULL;
+ parser = NULL;
+ icon_file = NULL;
+ memset (&data, 0, sizeof (data));
+
+ bdmt_volume_info_file = G_FILE (source_object);
+
+ error = NULL;
+ if (g_file_load_contents_finish (bdmt_volume_info_file,
+ res,
+ &content,
+ &content_length,
+ NULL,
+ &error))
+ {
+ data.name = NULL;
+
+ parser = XML_ParserCreate (NULL);
+ XML_SetElementHandler (parser,
+ (XML_StartElementHandler) bdmt_parse_start_tag,
+ (XML_EndElementHandler) bdmt_parse_end_tag);
+ XML_SetCharacterDataHandler (parser,
+ (XML_CharacterDataHandler) bdmt_parse_text);
+ XML_SetUserData (parser, &data);
+ if (XML_Parse (parser, content, content_length, TRUE) == 0)
+ {
+ g_warning ("Failed to parse bdmt file");
+ goto out;
+ }
+ g_message ("icon file: %s", data.icon_path);
+ g_message ("name: %s", data.name);
+ icon_file = data.icon_path;
+
+ icon = NULL;
+
+ if (icon_file != NULL)
+ {
+ GFile *dir, *f;
+
+ dir = g_file_get_parent (bdmt_volume_info_file);
+ if (dir)
+ {
+ f = g_file_resolve_relative_path (dir, icon_file);
+ if (f)
+ {
+ icon = g_file_icon_new (f);
+ g_object_unref (f);
+ }
+
+ g_object_unref (dir);
+ }
+ }
+
+ g_simple_async_result_set_op_res_gpointer (simple, icon, NULL);
+ if (data.name != NULL)
+ g_object_set_data_full (G_OBJECT (simple), "name", data.name, g_free);
+ data.name = NULL; /* steals name */
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ }
+
+ out:
+
+ if (error != NULL)
+ {
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ g_error_free (error);
+ }
+
+ if (parser != NULL)
+ XML_ParserFree (parser);
+ g_free (data.name);
+ g_free (content);
+}
+#endif /* HAVE_EXPAT */
+
+void
+g_vfs_mount_info_query_bdmv_volume_info (GFile *directory,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+#ifdef HAVE_EXPAT
+ GSimpleAsyncResult *simple;
+ GFile *file;
+
+ simple = g_simple_async_result_new (G_OBJECT (directory),
+ callback,
+ user_data,
+ g_vfs_mount_info_query_bdmv_volume_info);
+
+ /* FIXME: handle other languages:
+ * Check the current locale
+ * Get 3 letter-code from 2 letter locale using /usr/share/xml/iso-codes/iso_639_3.xml
+ * load bdmt_<code>.xml
+ * Fall-back to bdmt_eng.xml if it fails */
+ file = g_file_resolve_relative_path (directory, "BDMV/META/DL/bdmt_eng.xml");
+ g_file_load_contents_async (file,
+ cancellable,
+ on_bdmv_volume_info_loaded,
+ simple);
+ g_object_unref (file);
+#else
+ GSimpleAsyncResult *simple;
+ simple = g_simple_async_result_new (G_OBJECT (directory),
+ callback,
+ user_data,
+ g_vfs_mount_info_query_bdmv_volume_info);
+ g_simple_async_result_set_error (simple,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "gvfs built without Expat support, no BDMV support");
+#endif /* HAVE_EXPAT */
+}
+
+GIcon *g_vfs_mount_info_query_bdmv_volume_info_finish (GFile *directory,
+ GAsyncResult *res,
+ gchar **out_name,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+ GIcon *ret;
+
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_vfs_mount_info_query_bdmv_volume_info);
+
+ ret = NULL;
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ goto out;
+
+ ret = g_simple_async_result_get_op_res_gpointer (simple);
+
+ if (out_name != NULL)
+ *out_name = g_strdup (g_object_get_data (G_OBJECT (simple), "name"));
+
+ out:
+ return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
#define INSENSITIVE_SEARCH_ITEMS_PER_CALLBACK 100
static void
diff --git a/common/gvfsmountinfo.h b/common/gvfsmountinfo.h
index 6879f04a..81d0b8f0 100644
--- a/common/gvfsmountinfo.h
+++ b/common/gvfsmountinfo.h
@@ -47,6 +47,16 @@ GIcon *g_vfs_mount_info_query_xdg_volume_info_finish (GFile *directory,
gchar **out_name,
GError **error);
+void g_vfs_mount_info_query_bdmv_volume_info (GFile *directory,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+GIcon *g_vfs_mount_info_query_bdmv_volume_info_finish (GFile *directory,
+ GAsyncResult *res,
+ gchar **out_name,
+ GError **error);
+
G_END_DECLS
#endif /* __G_VFS_MOUNT_INFO_H__ */