[gnac] Used GstDiscoverer to retrieve metadata



commit 61951dd631d563ea077672aac74c56785da044b1
Author: BenoÃt Dupasquier <bdupasqu src gnome org>
Date:   Tue Jan 31 02:08:40 2012 +0000

    Used GstDiscoverer to retrieve metadata

 libgnac/libgnac-metadata-tags.h |  100 ++++---
 libgnac/libgnac-metadata.c      |  597 +++++++++++++--------------------------
 src/gnac-properties.c           |    4 +-
 3 files changed, 263 insertions(+), 438 deletions(-)
---
diff --git a/libgnac/libgnac-metadata-tags.h b/libgnac/libgnac-metadata-tags.h
index 342193d..890f69b 100644
--- a/libgnac/libgnac-metadata-tags.h
+++ b/libgnac/libgnac-metadata-tags.h
@@ -33,17 +33,21 @@ G_BEGIN_DECLS
 typedef GHashTable LibgnacTags;
 
 /* Non official GStreamer tags */
-#define GNAC_TAG_CHANNELS   "channels"
-#define GNAC_TAG_FILENAME   "filename"
-#define GNAC_TAG_FILE_SIZE  "file-size"
-#define GNAC_TAG_FRAMERATE  "framerate"
-#define GNAC_TAG_HAS_AUDIO  "has-audio"
-#define GNAC_TAG_HAS_VIDEO  "has-video"
-#define GNAC_TAG_HEIGHT     "height"
-#define GNAC_TAG_MODE       "mode"
-#define GNAC_TAG_RATE       "rate"
-#define GNAC_TAG_VBR        "vbr"
-#define GNAC_TAG_WIDTH      "width"
+#define GNAC_TAG_CHANNELS    "channels"
+#define GNAC_TAG_AUDIO_DEPTH "audio-depth"
+#define GNAC_TAG_FILENAME    "filename"
+#define GNAC_TAG_FILE_SIZE   "file-size"
+#define GNAC_TAG_FRAMERATE   "framerate"
+#define GNAC_TAG_HAS_AUDIO   "has-audio"
+#define GNAC_TAG_HAS_VIDEO   "has-video"
+#define GNAC_TAG_HEIGHT      "height"
+#define GNAC_TAG_INTERLACED  "interlaced"
+#define GNAC_TAG_MODE        "channel-mode"
+#define GNAC_TAG_PAR         "par"
+#define GNAC_TAG_RATE        "rate"
+#define GNAC_TAG_VBR         "vbr"
+#define GNAC_TAG_VIDEO_DEPTH "video-depth"
+#define GNAC_TAG_WIDTH       "width"
 
 #define LIBGNAC_METADATA_TAG_IS_ALBUM(tag) \
     (g_str_equal((tag), GST_TAG_ALBUM))
@@ -55,6 +59,8 @@ typedef GHashTable LibgnacTags;
     (g_str_equal((tag), GST_TAG_ARTIST))
 #define LIBGNAC_METADATA_TAG_IS_AUDIO_CODEC(tag) \
     (g_str_equal((tag), GST_TAG_AUDIO_CODEC))
+#define LIBGNAC_METADATA_TAG_IS_AUDIO_DEPTH(tag) \
+    (g_str_equal((tag), GST_TAG_AUDIO_DEPTH))
 #define LIBGNAC_METADATA_TAG_IS_BITRATE(tag) \
     (g_str_equal((tag), GST_TAG_BITRATE))
 #define LIBGNAC_METADATA_TAG_IS_CHANNELS(tag) \
@@ -85,6 +91,8 @@ typedef GHashTable LibgnacTags;
     (g_str_equal((tag), GNAC_TAG_HEIGHT))
 #define LIBGNAC_METADATA_TAG_IS_IMAGE(tag) \
     (g_str_equal((tag), GST_TAG_IMAGE))
+#define LIBGNAC_METADATA_TAG_IS_INTERLACED(tag) \
+    (g_str_equal((tag), GNAC_TAG_INTERLACED))
 #define LIBGNAC_METADATA_TAG_IS_LOCATION(tag) \
     (g_str_equal((tag), GST_TAG_LOCATION))
 #define LIBGNAC_METADATA_TAG_IS_MODE(tag) \
@@ -105,71 +113,79 @@ typedef GHashTable LibgnacTags;
     (g_str_equal((tag), GNAC_TAG_VBR))
 #define LIBGNAC_METADATA_TAG_IS_VIDEO_CODEC(tag) \
     (g_str_equal((tag), GST_TAG_VIDEO_CODEC))
+#define LIBGNAC_METADATA_TAG_IS_VIDEO_DEPTH(tag) \
+    (g_str_equal((tag), GST_TAG_VIDEO_DEPTH))
 #define LIBGNAC_METADATA_TAG_IS_WIDTH(tag) \
     (g_str_equal((tag), GNAC_TAG_WIDTH))
 
 #define LIBGNAC_METADATA_TAG_ALBUM(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_ALBUM))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_ALBUM))
 #define LIBGNAC_METADATA_TAG_ALBUM_VOLUME_COUNT(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_ALBUM_VOLUME_COUNT))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_ALBUM_VOLUME_COUNT))
 #define LIBGNAC_METADATA_TAG_ALBUM_VOLUME_NUMBER(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_ALBUM_VOLUME_NUMBER))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_ALBUM_VOLUME_NUMBER))
 #define LIBGNAC_METADATA_TAG_ARTIST(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_ARTIST))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_ARTIST))
 #define LIBGNAC_METADATA_TAG_AUDIO_CODEC(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_AUDIO_CODEC))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_AUDIO_CODEC))
+#define LIBGNAC_METADATA_TAG_AUDIO_DEPTH(tags) \
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_AUDIO_DEPTH))
 #define LIBGNAC_METADATA_TAG_BITRATE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_BITRATE))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_BITRATE))
 #define LIBGNAC_METADATA_TAG_CHANNELS(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_CHANNELS))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_CHANNELS))
 #define LIBGNAC_METADATA_TAG_COMMENT(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_COMMENT))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_COMMENT))
 #define LIBGNAC_METADATA_TAG_CONTAINER_FORMAT(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_CONTAINER_FORMAT))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_CONTAINER_FORMAT))
 #define LIBGNAC_METADATA_TAG_DATE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_DATE))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_DATE))
 #define LIBGNAC_METADATA_TAG_DURATION(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_DURATION))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_DURATION))
 #define LIBGNAC_METADATA_TAG_ENCODER(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_ENCODER))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_ENCODER))
 #define LIBGNAC_METADATA_TAG_FILE_SIZE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_FILE_SIZE))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_FILE_SIZE))
 #define LIBGNAC_METADATA_TAG_FILENAME(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_FILENAME))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_FILENAME))
 #define LIBGNAC_METADATA_TAG_FRAMERATE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_FRAMERATE))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_FRAMERATE))
 #define LIBGNAC_METADATA_TAG_GENRE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_GENRE))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_GENRE))
 #define LIBGNAC_METADATA_TAG_HAS_AUDIO(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_HAS_AUDIO))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_HAS_AUDIO))
 #define LIBGNAC_METADATA_TAG_HAS_VIDEO(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_HAS_VIDEO))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_HAS_VIDEO))
 #define LIBGNAC_METADATA_TAG_HEIGHT(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_HEIGHT))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_HEIGHT))
 #define LIBGNAC_METADATA_TAG_IMAGE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_IMAGE))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_IMAGE))
+#define LIBGNAC_METADATA_TAG_INTERLACED(tags) \
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_INTERLACED))
 #define LIBGNAC_METADATA_TAG_LOCATION(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_LOCATION))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_LOCATION))
 #define LIBGNAC_METADATA_TAG_MODE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_MODE))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_MODE))
 #define LIBGNAC_METADATA_TAG_RATE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_RATE))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_RATE))
 #define LIBGNAC_METADATA_TAG_TITLE(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TITLE))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_TITLE))
 #define LIBGNAC_METADATA_TAG_TRACK_COUNT(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TRACK_COUNT))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_TRACK_COUNT))
 #define LIBGNAC_METADATA_TAG_TRACK_GAIN(tag) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TRACK_GAIN))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_TRACK_GAIN))
 #define LIBGNAC_METADATA_TAG_TRACK_NUMBER(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TRACK_NUMBER))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_TRACK_NUMBER))
 #define LIBGNAC_METADATA_TAG_TRACK_PEAK(tag) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_TRACK_PEAK))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_TRACK_PEAK))
 #define LIBGNAC_METADATA_TAG_VBR(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_VBR))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_VBR))
 #define LIBGNAC_METADATA_TAG_VIDEO_CODEC(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GST_TAG_VIDEO_CODEC))
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_VIDEO_CODEC))
+#define LIBGNAC_METADATA_TAG_VIDEO_DEPTH(tags) \
+    (g_hash_table_lookup((GHashTable *) (tags), GST_TAG_VIDEO_DEPTH))
 #define LIBGNAC_METADATA_TAG_WIDTH(tags) \
-    (g_hash_table_lookup((GHashTable*)(tags), GNAC_TAG_WIDTH))
+    (g_hash_table_lookup((GHashTable *) (tags), GNAC_TAG_WIDTH))
 
 G_END_DECLS
 
diff --git a/libgnac/libgnac-metadata.c b/libgnac/libgnac-metadata.c
index 8b420a5..b063d4d 100644
--- a/libgnac/libgnac-metadata.c
+++ b/libgnac/libgnac-metadata.c
@@ -30,6 +30,7 @@
 #include <gdk/gdk.h>
 #include <glib/gi18n.h>
 #include <gst/gst.h>
+#include <gst/pbutils/pbutils.h>
 #include <gst/tag/tag.h>
 #include <stdarg.h>
 
@@ -38,22 +39,12 @@
 #include "libgnac-gst-utils.h"
 #include "libgnac-metadata.h"
 
-static LibgnacTags *dummy_tags;
 
 struct LibgnacMetadataPrivate
 {
-  GFile *uri;
-
-  GstElement *pipeline;
-  GstElement *sink;
-  
-  GHashTable *tags_table;
-
-  LibgnacTags *metadata;
-
-  gboolean eos;
-
-  GError *error;
+  GHashTable        *tags_table;
+  GstDiscovererInfo *info;
+  LibgnacTags       *metadata;
 };
 
 G_DEFINE_TYPE(LibgnacMetadata, libgnac_metadata, G_TYPE_OBJECT);
@@ -63,33 +54,13 @@ G_DEFINE_TYPE(LibgnacMetadata, libgnac_metadata, G_TYPE_OBJECT);
 
 
 static void
-libgnac_metadata_destroy_pipeline(LibgnacMetadata *md)
-{
-  if (!md->priv->pipeline) return;
-
-  GstBus *bus = gst_element_get_bus(md->priv->pipeline);
-  gst_element_set_state(md->priv->pipeline, GST_STATE_NULL);
-  gst_bus_set_sync_handler(bus, NULL, NULL);
-  gst_object_unref(GST_OBJECT(bus));
-  gst_object_unref(GST_OBJECT(md->priv->pipeline));
-  md->priv->pipeline = NULL;
-}
-
-
-static void
 libgnac_metadata_reset(LibgnacMetadata *md)
 {
-  if (md->priv->uri) {
-    g_object_unref(md->priv->uri);
-    md->priv->uri = NULL;
-  }
-  md->priv->eos = FALSE;
-  md->priv->error = NULL;
-  libgnac_metadata_destroy_pipeline(md);
   /* must be freed by the user */
   if (md->priv->metadata) {
     md->priv->metadata = NULL;
   }
+  md->priv->info = NULL;
 }
 
 
@@ -158,6 +129,75 @@ libgnac_metadata_free_gvalue(GValue *value)
 
 
 static void
+libgnac_metadata_add_boolean_value(LibgnacMetadata *md,
+                                   gchar           *tag_name,
+                                   gboolean         value)
+{
+  GValue *val = g_new0(GValue, 1);
+  g_value_init(val, G_TYPE_BOOLEAN);
+  g_value_set_boolean(val, value);
+  g_hash_table_insert(md->priv->metadata, tag_name, val);
+}
+
+
+static void
+libgnac_metadata_add_fraction_value(LibgnacMetadata *md,
+                                    gchar           *tag_name,
+                                    guint            numerator,
+                                    guint            denominator)
+{
+  if (numerator == 0 || denominator == 0) return;
+
+  GValue *value = g_new0(GValue, 1);
+  g_value_init(value, G_TYPE_FLOAT);
+  g_value_set_float(value, (gfloat) numerator / denominator);
+  g_hash_table_insert(md->priv->metadata, tag_name, value);
+}
+
+
+static void
+libgnac_metadata_add_object_value(LibgnacMetadata *md,
+                                  gchar           *tag_name,
+                                  GObject         *value)
+{
+  if (!value) return;
+
+  GValue *val = g_new0(GValue, 1);
+  g_value_init(val, G_TYPE_OBJECT);
+  g_value_set_object(val, value);
+  g_hash_table_insert(md->priv->metadata, tag_name, val);
+}
+
+
+static void
+libgnac_metadata_add_string_value(LibgnacMetadata *md,
+                                  gchar           *tag_name,
+                                  const gchar     *value)
+{
+  if (!value) return;
+
+  GValue *val = g_new0(GValue, 1);
+  g_value_init(val, G_TYPE_STRING);
+  g_value_set_string(val, value);
+  g_hash_table_insert(md->priv->metadata, tag_name, val);
+}
+
+
+static void
+libgnac_metadata_add_uint_value(LibgnacMetadata *md,
+                                gchar           *tag_name,
+                                guint            value)
+{
+  if (value == 0) return;
+
+  GValue *val = g_new0(GValue, 1);
+  g_value_init(val, G_TYPE_UINT);
+  g_value_set_uint(val, value);
+  g_hash_table_insert(md->priv->metadata, tag_name, val);
+}
+
+
+static void
 libgnac_metadata_size_prepared_cb(GdkPixbufLoader *loader,
                                   gint             width,
                                   gint             height,
@@ -224,59 +264,17 @@ libgnac_metadata_process_tag_image(const GstTagList *taglist,
       }
 
       GdkPixbuf *pixbuf = gdk_pixbuf_loader_get_pixbuf(loader);
-      g_return_if_fail(pixbuf);
-
-      GValue *newval = g_new0(GValue, 1);
-      g_value_init(newval, G_TYPE_OBJECT);
-      g_value_set_object(newval, pixbuf);
+      libgnac_metadata_add_object_value(md, GST_TAG_IMAGE, G_OBJECT(pixbuf));
 
       g_object_unref(G_OBJECT(loader));
-      loader = NULL;
-
-      g_hash_table_insert(md->priv->metadata, GST_TAG_IMAGE, newval);
     }
   }
 }
 
 
 static void
-libgnac_metadata_process_tag_value(GstStructure    *structure,
-                                   gchar           *tag_name,
-                                   LibgnacMetadata *md)
-{
-  const GValue *val = gst_structure_get_value(structure, tag_name);
-  if (!val) return;
-
-  if (GST_VALUE_HOLDS_FRACTION(val)) {
-    gint numerator = gst_value_get_fraction_numerator(val);
-    gint denominator = gst_value_get_fraction_denominator(val);
-
-    GValue *newval = g_new0(GValue, 1);
-    g_value_init(newval, G_TYPE_FLOAT);
-    g_value_set_float(newval, (gfloat) numerator / denominator);
-    g_hash_table_insert(md->priv->metadata, tag_name, newval);
-  }
-}
-
-
-static void
-libgnac_metadata_process_tag_int(GstStructure    *structure,
-                                 gchar           *tag_name,
-                                 LibgnacMetadata *md)
-{
-  gint int_val;
-  if (gst_structure_get_int(structure, tag_name, &int_val)) {
-    GValue *val = g_new0(GValue, 1);
-    g_value_init(val, G_TYPE_INT);
-    g_value_set_int(val, int_val);
-    g_hash_table_insert(md->priv->metadata, tag_name, val);
-  }
-}
-
-
-static void
-libgnac_metadata_process_tag(const GstTagList *taglist, 
-                             const gchar      *tag_name, 
+libgnac_metadata_process_tag(const GstTagList *taglist,
+                             gchar            *tag_name,
                              LibgnacMetadata  *md)
 {
   gint count = gst_tag_list_get_tag_size(taglist, tag_name);
@@ -290,6 +288,7 @@ libgnac_metadata_process_tag(const GstTagList *taglist,
   }
 
   const GValue *val = gst_tag_list_get_value_index(taglist, tag_name, 0);
+
   GType type = gst_tag_get_type(tag_name);
   GValue *newval = g_new0(GValue, 1);
   g_value_init(newval, type);
@@ -310,29 +309,7 @@ libgnac_metadata_process_tag(const GstTagList *taglist,
     g_value_take_string(newval, str);
   }
 
-  if (g_str_equal(tag_name, GST_TAG_BITRATE))
-  {
-    guint32 bitrate = g_value_get_uint(newval);
-    g_value_set_uint(newval, bitrate);
-    if (libgnac_metadata_tag_exists(md->priv->metadata, tag_name)) {
-      guint32 old_bitrate = g_value_get_uint(
-          LIBGNAC_METADATA_TAG_BITRATE(md->priv->metadata));
-      if (bitrate != old_bitrate) {
-        GValue *vbr = g_new0(GValue, 1);
-        g_value_init(vbr, G_TYPE_UINT);
-        g_value_set_uint(vbr, bitrate);
-        g_hash_table_insert(md->priv->metadata, GNAC_TAG_VBR, vbr);
-      }
-    }
-  }
-  else if (g_str_equal(tag_name, GST_TAG_DURATION)) 
-  {
-    guint64 duration = g_value_get_uint64(newval);
-    /* convert the duration from ns to seconds */
-    g_value_set_uint64(newval, duration / GST_SECOND);
-  }
-  else if (g_str_equal(tag_name, GST_TAG_DATE)) 
-  {
+  if (g_str_equal(tag_name, GST_TAG_DATE)) {
     g_return_if_fail(GST_VALUE_HOLDS_DATE(newval));
     const GDate *date = gst_value_get_date(newval);
     if (!date) return;
@@ -342,222 +319,120 @@ libgnac_metadata_process_tag(const GstTagList *taglist,
     g_value_set_uint(newval, year);
   }
 
-  g_hash_table_insert(md->priv->metadata, (gpointer) tag_name, newval);
-}
-
-
-static void 
-libgnac_metadata_on_message_application(GstBus          *bus,
-                                        GstMessage      *message,
-                                        LibgnacMetadata *md)
-{
-  libgnac_metadata_destroy_pipeline(md);
-  md->priv->eos = TRUE;
+  g_hash_table_insert(md->priv->metadata, tag_name, newval);
 }
 
 
 static void
-libgnac_metadata_on_message_eos(GstBus          *bus,
-                                GstMessage      *message,
-                                LibgnacMetadata *md)
-{
-  md->priv->eos = TRUE;
-}
-
-
-static void
-libgnac_metadata_on_message_error(GstBus          *bus,
-                                  GstMessage      *message,
-                                  LibgnacMetadata *md)
+libgnac_metadata_get_file_info(GFile *uri, LibgnacMetadata *md)
 {
   GError *error = NULL;
-  gchar  *debug;
-  gst_message_parse_error(message, &error, &debug);
-  libgnac_debug("Error on metadata reading: %s (%s)", error->message, debug);
-  md->priv->eos = TRUE; 
-  g_free(debug);
-  g_clear_error(&error);
-}
 
+  GFileInfo *info = g_file_query_info(uri,
+      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+      G_FILE_ATTRIBUTE_STANDARD_ICON ","
+      G_FILE_ATTRIBUTE_STANDARD_SIZE ","
+      G_FILE_ATTRIBUTE_THUMBNAIL_PATH,
+      G_FILE_QUERY_INFO_NONE, NULL, &error);
 
-static void
-libgnac_metadata_on_message_tag(GstBus          *bus,
-                                GstMessage      *message,
-                                LibgnacMetadata *md)
-{
-  GstTagList *taglist;
-  gst_message_parse_tag(message, &taglist);
-  if (GST_IS_TAG_LIST(taglist)) {
-    gst_tag_list_foreach(taglist, 
-        (GstTagForeachFunc) libgnac_metadata_process_tag, md);
-    gst_tag_list_free(taglist);
+  if (error) {
+    g_clear_error(&error);
+    return;
   }
-}
-
 
-static gboolean
-libgnac_metadata_bus_handler(GstBus           *bus, 
-                             GstMessage       *message, 
-                             LibgnacMetadata  *md)
-{
-  g_return_val_if_fail(md, FALSE);
+  /* file size */
+  GValue *file_size_value = g_new0(GValue, 1);
+  g_value_init(file_size_value, G_TYPE_INT64);
+  g_value_set_int64(file_size_value, g_file_info_get_size(info));
+  g_hash_table_insert(md->priv->metadata, GNAC_TAG_FILE_SIZE, file_size_value);
 
-  switch (GST_MESSAGE_TYPE(message)) 
-  {
-    case GST_MESSAGE_EOS: 
-      libgnac_metadata_on_message_eos(bus, message, md);
-      break;
-    case GST_MESSAGE_ERROR: 
-      libgnac_metadata_on_message_error(bus, message, md);
-      break;
-    case GST_MESSAGE_TAG:
-      libgnac_metadata_on_message_tag(bus, message, md);
-      break;
-    case GST_MESSAGE_APPLICATION:
-      libgnac_metadata_on_message_application(bus, message, md);
-      break;
-    default:
-      break;
-  }
+  /* location */
+  gchar *path = g_file_get_path(uri);
+  libgnac_metadata_add_string_value(md, GST_TAG_LOCATION, path);
+  g_free(path);
 
-  return FALSE;
-}
+  /* filename */
+  const gchar *filename = g_file_info_get_display_name(info);
+  libgnac_metadata_add_string_value(md, GNAC_TAG_FILENAME, filename);
 
+  /* image */
+  if (!libgnac_metadata_tag_exists(md->priv->metadata, GST_TAG_IMAGE)) {
+    const gchar *thumbnail_path = g_file_info_get_attribute_byte_string(info,
+        G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
+    if (thumbnail_path) {
+      GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(thumbnail_path, NULL);
+      libgnac_metadata_add_object_value(md, GST_TAG_IMAGE, G_OBJECT(pixbuf));
+    }
+  }
 
-static GstBusSyncReply
-libgnac_metadata_bus_sync_handler(GstBus          *bus, 
-                                  GstMessage      *message, 
-                                  LibgnacMetadata *md)
-{
-  libgnac_metadata_bus_handler(bus, message, md);
-  gst_message_unref(message);
-  return GST_BUS_DROP;
+  g_object_unref(info);
 }
 
 
 static void
-libgnac_metadata_new_decoded_pad_cb(GstElement      *decodebin,
-                                    GstPad          *pad,
-                                    LibgnacMetadata *md)
+libgnac_metadata_process_audio_info(LibgnacMetadata *md)
 {
-  GstPad *sink_pad = gst_element_get_pad(md->priv->sink, "sink");
-  if (GST_PAD_IS_LINKED(sink_pad)) {
-    g_object_unref(sink_pad);
-    return;
-  }
+  GList *audio_info = gst_discoverer_info_get_audio_streams(md->priv->info);
+  if (!audio_info) return;
 
-  g_return_if_fail(
-      libgnac_gstu_pad_link(pad, sink_pad, NULL) == GST_PAD_LINK_OK);
+  libgnac_metadata_add_boolean_value(md, GNAC_TAG_HAS_AUDIO, TRUE);
 
-  GstCaps *caps = gst_pad_get_caps(pad);
-  if (gst_caps_is_empty(caps) || gst_caps_is_any(caps)) {
-    gst_caps_unref(caps);
-    g_object_unref(sink_pad);
-    return;
-  }
+  GList *first = g_list_first(audio_info);
+  GstDiscovererAudioInfo *audio = (GstDiscovererAudioInfo *) first->data;
 
-  GstStructure *structure = gst_caps_get_structure(caps, 0);
-  const gchar *mimetype = gst_structure_get_name(structure);
+  guint channels = gst_discoverer_audio_info_get_channels(audio);
+  libgnac_metadata_add_uint_value(md, GNAC_TAG_CHANNELS, channels);
 
-  if (g_str_has_prefix(mimetype, "video"))
-  {
-    GValue *val = g_new0(GValue, 1);
-    g_value_init(val, G_TYPE_BOOLEAN);
-    g_value_set_boolean(val, TRUE);
-    g_hash_table_insert(md->priv->metadata, GNAC_TAG_HAS_VIDEO, val);
-  }
-  else if (g_str_has_prefix(mimetype, "audio"))
-  {
-    GValue *val = g_new0(GValue, 1);
-    g_value_init(val, G_TYPE_BOOLEAN);
-    g_value_set_boolean(val, TRUE);
-    g_hash_table_insert(md->priv->metadata, GNAC_TAG_HAS_AUDIO, val);
-  }
-  else
-  {
-    libgnac_debug("Got a non audio or video pad: %s", mimetype);
-  }
+  guint sample_rate = gst_discoverer_audio_info_get_sample_rate(audio);
+  libgnac_metadata_add_uint_value(md, GNAC_TAG_RATE, sample_rate);
 
-  gst_caps_unref(caps);
-  gst_object_unref(sink_pad);
-}
+  guint depth = gst_discoverer_audio_info_get_depth(audio);
+  libgnac_metadata_add_uint_value(md, GNAC_TAG_AUDIO_DEPTH, depth);
 
+  //guint bitrate = gst_discoverer_audio_info_get_bitrate(audio);
+  //if (gst_discoverer_audio_info_is_vbr(audio)) {
+  //if (audio->is_vbr) {  // XXX not implemented yet
+  //  libgnac_metadata_add_uint_value(md, GNAC_TAG_VBR, bitrate);
+  //}
 
-static gboolean
-libgnac_metadata_autoplug_continue_cb(GstElement      *decodebin,
-                                      GstPad          *pad,
-                                      GstCaps         *caps,
-                                      LibgnacMetadata *md)
-{
-  g_return_val_if_fail(LIBGNAC_IS_METADATA(md), TRUE);
-  
-  if (!gst_caps_is_fixed(caps)) return TRUE;
-
-  GstStructure *structure = gst_caps_get_structure(caps, 0);
-  const gchar *mimetype = gst_structure_get_name(structure);
-
-  libgnac_metadata_process_tag_int(structure, GNAC_TAG_RATE, md);
-  libgnac_metadata_process_tag_int(structure, GNAC_TAG_CHANNELS, md);
-
-  if (g_str_has_prefix(mimetype, "video")) {
-    libgnac_metadata_process_tag_int(structure, GNAC_TAG_HEIGHT, md);
-    libgnac_metadata_process_tag_int(structure, GNAC_TAG_WIDTH, md);
-    libgnac_metadata_process_tag_value(structure, GNAC_TAG_FRAMERATE, md);
-  }
-
-  return TRUE;
+  gst_discoverer_stream_info_list_free(audio_info);
 }
 
 
 static void
-libgnac_metadata_get_file_info(GFile *uri, LibgnacMetadata *md)
+libgnac_metadata_process_video_info(LibgnacMetadata *md)
 {
-  GError *error = NULL;
+  GList *video_info = gst_discoverer_info_get_video_streams(md->priv->info);
+  if (!video_info) return;
 
-  GFileInfo *info = g_file_query_info(uri,
-      G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
-      G_FILE_ATTRIBUTE_STANDARD_ICON ","
-      G_FILE_ATTRIBUTE_STANDARD_SIZE ","
-      G_FILE_ATTRIBUTE_THUMBNAIL_PATH,
-      G_FILE_QUERY_INFO_NONE, NULL, &error);
+  libgnac_metadata_add_boolean_value(md, GNAC_TAG_HAS_VIDEO, TRUE);
 
-  if (error) {
-    g_clear_error(&error);
-    return;
-  }
+  GList *first = g_list_first(video_info);
+  GstDiscovererVideoInfo *video = (GstDiscovererVideoInfo *) first->data;
 
-  /* file size */
-  GValue *file_size_value = g_new0(GValue, 1);
-  g_value_init(file_size_value, G_TYPE_INT64);
-  g_value_set_int64(file_size_value, g_file_info_get_size(info));
-  g_hash_table_insert(md->priv->metadata, GNAC_TAG_FILE_SIZE, file_size_value);
+  guint height = gst_discoverer_video_info_get_height(video);
+  libgnac_metadata_add_uint_value(md, GNAC_TAG_HEIGHT, height);
 
-  /* location */
-  gchar *path = g_file_get_path(uri);
-  GValue *location_value = g_new0(GValue, 1);
-  g_value_init(location_value, G_TYPE_STRING);
-  g_value_set_string(location_value, path);
-  g_free(path);
-  g_hash_table_insert(md->priv->metadata, GST_TAG_LOCATION, location_value);
+  guint width = gst_discoverer_video_info_get_width(video);
+  libgnac_metadata_add_uint_value(md, GNAC_TAG_WIDTH, width);
 
-  /* filename */
-  GValue *filename_value = g_new0(GValue, 1);
-  g_value_init(filename_value, G_TYPE_STRING);
-  g_value_set_string(filename_value, g_file_info_get_display_name(info));
-  g_hash_table_insert(md->priv->metadata, GNAC_TAG_FILENAME, filename_value);  
+  guint depth = gst_discoverer_video_info_get_depth(video);
+  libgnac_metadata_add_uint_value(md, GNAC_TAG_VIDEO_DEPTH, depth);
 
-  /* image */
-  const gchar *thumbnail_path = g_file_info_get_attribute_byte_string(info,
-      G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
-  if (thumbnail_path) {
-    GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(thumbnail_path, NULL);
-    GValue *value = g_new0(GValue, 1);
-    g_value_init(value, G_TYPE_OBJECT);
-    g_value_set_object(value, pixbuf);
-    g_hash_table_insert(md->priv->metadata, GST_TAG_IMAGE, value);
+  guint rate_num = gst_discoverer_video_info_get_framerate_num(video);
+  guint rate_denom = gst_discoverer_video_info_get_framerate_denom(video);
+  libgnac_metadata_add_fraction_value(md, GNAC_TAG_FRAMERATE,
+      rate_num, rate_denom);
+
+  if (gst_discoverer_video_info_is_interlaced(video)) {
+    libgnac_metadata_add_boolean_value(md, GNAC_TAG_INTERLACED, TRUE);
   }
 
-  g_object_unref(info);
+  guint par_num = gst_discoverer_video_info_get_par_num(video);
+  guint par_denom = gst_discoverer_video_info_get_par_denom(video);
+  libgnac_metadata_add_fraction_value(md, GNAC_TAG_PAR, par_num, par_denom);
+
+  gst_discoverer_stream_info_list_free(video_info);
 }
 
 
@@ -576,103 +451,46 @@ libgnac_metadata_extract(LibgnacMetadata  *md,
     /* make sure we start with a clean base */
     libgnac_metadata_reset(md);
 
-    md->priv->uri = g_file_dup(uri);
-
     md->priv->metadata = g_hash_table_new_full(g_str_hash, g_str_equal,
         NULL, (GDestroyNotify) libgnac_metadata_free_gvalue);
 
     /* store file-size, location and filename */
     libgnac_metadata_get_file_info(uri, md);
 
-    GError *metadata_error = NULL;
-
-    GstElement *pipeline = libgnac_gstu_pipeline_new(&metadata_error);
-    if (metadata_error) {
-      g_propagate_error(error, metadata_error);
+    GError *err = NULL;
+    GstDiscoverer *discoverer = gst_discoverer_new(GST_SECOND, &err);
+    if (!discoverer) {
+      libgnac_debug("Failed to create discoverer: %s", err->message);
+      g_propagate_error(error, err);
       return NULL;
     }
 
-    GstElement *source = libgnac_gstu_make_pipeline_element(pipeline,
-        "giosrc", NULL, &metadata_error);
-    if (metadata_error) {
-      libgnac_debug("source creation failed");
-      g_propagate_error(error, metadata_error);
+    GstDiscovererInfo *info = gst_discoverer_discover_uri(discoverer,
+        string_uri, &err);
+    if (!info) {
+      libgnac_debug("Failed to discover: %s", err->message);
+      g_propagate_error(error, err);
       return NULL;
     }
 
-    g_object_set(G_OBJECT(source), "file", md->priv->uri, NULL);
-
-    GstElement *decodebin = libgnac_gstu_make_pipeline_element(pipeline,
-        "decodebin2", NULL, &metadata_error);
-    if (metadata_error) {
-      g_propagate_error(error, metadata_error);
-      return NULL;
-    }
+    md->priv->info = info;
 
-    md->priv->sink = libgnac_gstu_make_pipeline_element(pipeline,
-        "fakesink", NULL, &metadata_error);
-    if (metadata_error) {
-      g_propagate_error(error, metadata_error);
-      return NULL;
+    const GstTagList *taglist = gst_discoverer_info_get_tags(info);
+    if (taglist) {
+      gst_tag_list_foreach(taglist,
+          (GstTagForeachFunc) libgnac_metadata_process_tag, md);
     }
 
-    g_signal_connect(decodebin, "autoplug-continue", 
-        G_CALLBACK(libgnac_metadata_autoplug_continue_cb), md);
-    g_signal_connect(decodebin, "pad-added",
-        G_CALLBACK(libgnac_metadata_new_decoded_pad_cb), md);
-
-    g_return_val_if_fail(
-        libgnac_gstu_element_link(source, decodebin, error),
-        FALSE);
-    md->priv->pipeline = pipeline;
-
-    GstBus *bus = gst_element_get_bus(GST_ELEMENT(pipeline));
-    gst_bus_set_sync_handler(bus,
-        (GstBusSyncHandler) libgnac_metadata_bus_sync_handler, md);
-    gst_object_unref(bus);
-
-    GstStateChangeReturn state_return = gst_element_set_state(
-        md->priv->pipeline, GST_STATE_PAUSED);
+    GstClockTime duration = gst_discoverer_info_get_duration(info);
+    GValue *val = g_new0(GValue, 1);
+    g_value_init(val, G_TYPE_UINT64);
+    /* convert the duration from ns to seconds */
+    g_value_set_uint64(val, duration / GST_SECOND);
+    g_hash_table_insert(md->priv->metadata, GST_TAG_DURATION, val);
 
-    gint timeout_cycle;
-    for (timeout_cycle = 0; timeout_cycle < 5; timeout_cycle++) {
-      if (state_return != GST_STATE_CHANGE_ASYNC || md->priv->eos) {
-        break;
-      }
-      state_return = gst_element_get_state(md->priv->pipeline,
-          NULL, NULL, GST_SECOND);
-    }
+    libgnac_metadata_process_audio_info(md);
+    libgnac_metadata_process_video_info(md);
 
-    if ((state_return == GST_STATE_CHANGE_FAILURE) ||
-        (state_return == GST_STATE_CHANGE_ASYNC && !md->priv->eos)) 
-    {
-      libgnac_debug("An error occured while extracting metadata from file %s", 
-          string_uri);
-    }
-    else if (state_return == GST_STATE_CHANGE_SUCCESS) {
-      if (!g_hash_table_lookup(md->priv->metadata, GST_TAG_DURATION)) {
-        GstFormat format = GST_FORMAT_TIME;
-        gint64 length;
-        if (gst_element_query_duration(md->priv->sink, &format, &length)) {
-          g_assert(format == GST_FORMAT_TIME);
-          GValue *newval = g_new0(GValue, 1);
-          g_value_init(newval, G_TYPE_UINT64);
-          g_value_set_uint64(newval, length/GST_SECOND);
-          g_hash_table_insert(md->priv->metadata, GST_TAG_DURATION, newval);
-        } 
-      }
-    }
-    else if (state_return != GST_STATE_CHANGE_FAILURE) {
-      GstBus *message_bus = gst_element_get_bus(md->priv->pipeline);
-      if (message_bus) {
-        gst_bus_post(message_bus, gst_message_new_application(
-            GST_OBJECT(md->priv->pipeline), NULL));
-        gst_object_unref(message_bus);
-      }
-      while (!md->priv->eos);
-    }
-    
-    libgnac_metadata_destroy_pipeline(md);
     g_hash_table_insert(md->priv->tags_table, g_strdup(string_uri),
         md->priv->metadata);
     tags = md->priv->metadata;
@@ -725,45 +543,36 @@ libgnac_metadata_tags_exist(LibgnacTags *tags, ...)
 LibgnacTags *
 libgnac_metadata_get_dummy_tags(void)
 {
+  static LibgnacTags *dummy_tags = NULL;
+
   if (!dummy_tags) {
     dummy_tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
         (GDestroyNotify) libgnac_metadata_tags_free);
 
-    GValue *filename = g_new0(GValue, 1);
-    g_value_init(filename, G_TYPE_STRING);
-    /* Translators: example filename used in the preview label (do not remove the extension) */
-    g_value_set_static_string(filename, _("filename.oga"));
-    g_hash_table_insert(dummy_tags, GNAC_TAG_FILENAME, filename);
-
-    GValue *album = g_new0(GValue, 1);
-    g_value_init(album, G_TYPE_STRING);
-    g_value_set_static_string(album, "Today!");
-    g_hash_table_insert(dummy_tags, GST_TAG_ALBUM, album);
-    
-    GValue *artist = g_new0(GValue, 1);
-    g_value_init(artist, G_TYPE_STRING);
-    g_value_set_static_string(artist, "The Beach Boys");
-    g_hash_table_insert(dummy_tags, GST_TAG_ARTIST, artist);
-
-    GValue *title = g_new0(GValue, 1);
-    g_value_init(title, G_TYPE_STRING);
-    g_value_set_static_string(title, "Do You Wanna Dance?");
-    g_hash_table_insert(dummy_tags, GST_TAG_TITLE, title);
-
-    GValue *genre = g_new0(GValue, 1);
-    g_value_init(genre, G_TYPE_STRING);
-    g_value_set_static_string(genre, "Rock");
-    g_hash_table_insert(dummy_tags, GST_TAG_GENRE, genre);
-
-    GValue *comment = g_new0(GValue, 1);
-    g_value_init(comment, G_TYPE_STRING);
-    g_value_set_static_string(comment, _("Converted by Gnac"));
-    g_hash_table_insert(dummy_tags, GST_TAG_COMMENT, comment);
-
-    GValue *date = g_new0(GValue, 1);
-    g_value_init(date, G_TYPE_UINT);
-    g_value_set_uint(date, 1965);
-    g_hash_table_insert(dummy_tags, GST_TAG_DATE, date);
+    gchar *string_tags[][2] = {
+      { GST_TAG_ALBUM    , "Today!"               },
+      { GST_TAG_ARTIST   , "The Beach Boys"       },
+      /* Translators: example filename used in the preview label (do not remove the extension) */
+      { GST_TAG_COMMENT  , _("Converted by Gnac") },
+      { GNAC_TAG_FILENAME, _("filename.oga")      },
+      { GST_TAG_GENRE    , "Rock"                 },
+      { GST_TAG_TITLE    , "Do You Wanna Dance?"  },
+      { NULL, NULL }
+    };
+
+    gint i;
+    for (i = 0; string_tags[i][0]; i++) {
+        g_print("%d\n", i);
+      GValue *value = g_new0(GValue, 1);
+      g_value_init(value, G_TYPE_STRING);
+      g_value_set_static_string(value, string_tags[i][1]);
+      g_hash_table_insert(dummy_tags, string_tags[i][0], value);
+    }
+
+    GValue *value = g_new0(GValue, 1);
+    g_value_init(value, G_TYPE_UINT);
+    g_value_set_uint(value, 1965);
+    g_hash_table_insert(dummy_tags, GST_TAG_DATE, value);
 
     GValue *track_count = g_new0(GValue, 1);
     g_value_init(track_count, G_TYPE_UINT);
diff --git a/src/gnac-properties.c b/src/gnac-properties.c
index f15a10f..81ea6a1 100644
--- a/src/gnac-properties.c
+++ b/src/gnac-properties.c
@@ -437,7 +437,7 @@ gnac_properties_dup_bitrate(const GValue *value)
 static gchar *
 gnac_properties_dup_rate(const GValue *value)
 {
-  gint val = g_value_get_int(value);
+  guint val = g_value_get_uint(value);
   if (val == 0) return NULL;
 
   /* Translators: rate */
@@ -459,7 +459,7 @@ gnac_properties_dup_framerate(const GValue *value)
 static gchar *
 gnac_properties_dup_channels(const GValue *value)
 {
-  gint val = g_value_get_int(value);
+  guint val = g_value_get_uint(value);
   if (val == 0) return NULL;
 
   /* Translators: channels */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]