summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Ottela <mikael.ottela@ixonos.com>2010-08-12 17:12:47 +0300
committerMikael Ottela <mikael.ottela@ixonos.com>2010-08-12 18:22:22 +0300
commit1405ee26b152b7a62a64d1584a4c5b2e55c32f79 (patch)
tree251d2cb413091ae89932fef0d32d8589231b79f8
parentfefe77ce85e736158c9a3b9aec3d92d2bfe39e1d (diff)
downloadtracker-1405ee26b152b7a62a64d1584a4c5b2e55c32f79.tar.gz
Add an extractor that uses gupnp-dlna for gstreamer based metadata extraction.
-rw-r--r--configure.ac33
-rw-r--r--src/tracker-extract/Makefile.am14
-rw-r--r--src/tracker-extract/tracker-extract-gupnp-dlna.c999
3 files changed, 1043 insertions, 3 deletions
diff --git a/configure.ac b/configure.ac
index 72c60ff48..39f1ad0a7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -584,9 +584,17 @@ AM_CONDITIONAL(HAVE_GDKPIXBUF, test "x$have_gdkpixbuf" = "xyes")
AC_ARG_ENABLE(video-extractor,
AS_HELP_STRING([--enable-video-extractor=ARG],
- [enables one of the (gstreamer, xine, external, auto) video extractor backends [[default=auto]]]),,
+ [enables one of the (gupnp-dlna, gstreamer, xine, external, auto) video extractor backends [[default=auto]]]),,
[enable_video_extractor=auto])
+PKG_CHECK_MODULES(GUPNP_DLNA,
+ [gupnp-dlna-1.0],
+ [have_gupnp_dlna=yes],
+ [have_gupnp_dlna=no])
+
+AC_SUBST(GUPNP_DLNA_CFLAGS)
+AC_SUBST(GUPNP_DLNA_LIBS)
+
PKG_CHECK_MODULES(GSTREAMER,
[gstreamer-0.10 >= 0.10.12 gstreamer-tag-0.10 >= 0.10.12],
[have_libgstreamer=yes],
@@ -604,7 +612,10 @@ AC_SUBST(XINE_CFLAGS)
AC_SUBST(XINE_LIBS)
if test "x$enable_video_extractor" = "xauto"; then
- if test "$have_libgstreamer" = "yes"; then
+ if test "$have_gupnp_dlna" = "yes"; then
+ have_video_handler_app="GUPnP-DLNA"
+ have_video_handler="yes"
+ elif test "$have_libgstreamer" = "yes"; then
have_video_handler_app="GStreamer"
have_video_handler="yes"
elif test "$have_libxine" = "yes"; then
@@ -614,6 +625,13 @@ if test "x$enable_video_extractor" = "xauto"; then
have_video_handler="?"
have_video_handler_app="An external video player will be called"
fi
+elif test "x$enable_video_extractor" = "xgupnp-dlna"; then
+ if test "$have_gupnp_dlna" = "yes"; then
+ have_video_handler_app="GUPnP-DLNA"
+ have_video_handler="yes"
+ else
+ AC_MSG_ERROR([Couldn't find GUPnP-DLNA])
+ fi
elif test "x$enable_video_extractor" = "xgstreamer"; then
if test "$have_libgstreamer" = "yes"; then
have_video_handler_app="GStreamer"
@@ -633,19 +651,28 @@ else
have_video_handler_app="An external video player will be called"
fi
-if test "$have_video_handler_app" = "GStreamer"; then
+if test "$have_video_handler_app" = "GUPnP-DLNA"; then
+ AC_DEFINE(HAVE_GUPNP_DLNA, [], [Define if we have GUPnP-DLNA])
+ AM_CONDITIONAL(HAVE_GUPNP_DLNA, true)
+ AM_CONDITIONAL(HAVE_GSTREAMER, false)
+ AM_CONDITIONAL(HAVE_LIBXINE, false)
+ AM_CONDITIONAL(USING_EXTERNAL_VIDEO_PLAYER, false)
+elif test "$have_video_handler_app" = "GStreamer"; then
AC_DEFINE(HAVE_GSTREAMER, [], [Define if we have GStreamer])
AM_CONDITIONAL(HAVE_GSTREAMER, true)
+ AM_CONDITIONAL(HAVE_GUPNP_DLNA, false)
AM_CONDITIONAL(HAVE_LIBXINE, false)
AM_CONDITIONAL(USING_EXTERNAL_VIDEO_PLAYER, false)
elif test "$have_video_handler_app" = "Xine"; then
AC_DEFINE(HAVE_LIBXINE, [], [Define if we have Libxine])
AM_CONDITIONAL(HAVE_LIBXINE, true)
+ AM_CONDITIONAL(HAVE_GUPNP_DLNA, false)
AM_CONDITIONAL(HAVE_GSTREAMER, false)
AM_CONDITIONAL(USING_EXTERNAL_VIDEO_PLAYER, false)
else
AC_DEFINE(USING_EXTERNAL_VIDEO_PLAYER, [], [Define that Tracker will try to use external video players])
AM_CONDITIONAL(USING_EXTERNAL_VIDEO_PLAYER, true)
+ AM_CONDITIONAL(HAVE_GUPNP_DLNA, false)
AM_CONDITIONAL(HAVE_GSTREAMER, false)
AM_CONDITIONAL(HAVE_LIBXINE, false)
fi
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index faf5c840f..b6b94a7ca 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -29,6 +29,7 @@ INCLUDES = \
$(POPPLER_CFLAGS) \
$(GSTREAMER_CFLAGS) \
$(XINE_CFLAGS) \
+ $(GUPNP_DLNA_CFLAGS) \
$(TOTEM_PL_PARSER_CFLAGS)
if HAVE_LIBSTREAMANALYZER
@@ -91,6 +92,10 @@ if HAVE_GSTREAMER
modules_LTLIBRARIES += libextract-gstreamer.la
endif
+if HAVE_GUPNP_DLNA
+modules_LTLIBRARIES += libextract-gupnp-dlna.la
+endif
+
if HAVE_GSTREAMER_HELIX
modules_LTLIBRARIES += libextract-gstreamer-helix.la
endif
@@ -251,6 +256,15 @@ libextract_gstreamer_helix_la_LIBADD = \
$(GLIB2_LIBS) \
$(GCOV_LIBS)
+# GUPnP DLNA
+libextract_gupnp_dlna_la_SOURCES = tracker-extract-gupnp-dlna.c
+libextract_gupnp_dlna_la_LDFLAGS = $(module_flags) $(albumart_flags)
+libextract_gupnp_dlna_la_LIBADD = \
+ $(top_builddir)/src/libtracker-extract/libtracker-extract-@TRACKER_API_VERSION@.la \
+ $(GUPNP_DLNA_LIBS) \
+ $(GLIB2_LIBS) \
+ $(GCOV_LIBS)
+
# Xine
libextract_xine_la_SOURCES = tracker-extract-libxine.c
libextract_xine_la_LDFLAGS = $(module_flags)
diff --git a/src/tracker-extract/tracker-extract-gupnp-dlna.c b/src/tracker-extract/tracker-extract-gupnp-dlna.c
new file mode 100644
index 000000000..481f163b1
--- /dev/null
+++ b/src/tracker-extract/tracker-extract-gupnp-dlna.c
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2010, Nokia <ivan.frade@nokia.com>
+ *
+ * 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 02110-1301, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* I don't know why, but this prototype ain't in my math.h */
+long long int llroundl(long double x);
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#define GST_USE_UNSTABLE_API
+#include <libgupnp-dlna/gupnp-dlna-discoverer.h>
+
+#include <gst/tag/tag.h>
+
+#include <libtracker-client/tracker.h>
+
+#include <libtracker-extract/tracker-extract.h>
+
+#include "tracker-albumart.h"
+#include "tracker-dbus.h"
+
+/* An additional tag in gstreamer for the content source. Remove when in upstream */
+#ifndef GST_TAG_CLASSIFICATION
+#define GST_TAG_CLASSIFICATION "classification"
+#endif
+
+/* Some additional tagreadbin tags (FIXME until they are defined upstream)*/
+#ifndef GST_TAG_CHANNEL
+#define GST_TAG_CHANNEL "channels"
+#endif
+
+#ifndef GST_TAG_RATE
+#define GST_TAG_RATE "rate"
+#endif
+
+#ifndef GST_TAG_WIDTH
+#define GST_TAG_WIDTH "width"
+#endif
+
+#ifndef GST_TAG_HEIGHT
+#define GST_TAG_HEIGHT "height"
+#endif
+
+#ifndef GST_TAG_PIXEL_RATIO
+#define GST_TAG_PIXEL_RATIO "pixel-aspect-ratio"
+#endif
+
+#ifndef GST_TAG_FRAMERATE
+#define GST_TAG_FRAMERATE "framerate"
+#endif
+
+#ifndef GST_TAG_DEVICE_MODEL
+#define GST_TAG_DEVICE_MODEL "device-model"
+#endif
+
+#ifndef GST_TAG_DEVICE_MANUFACTURER
+#define GST_TAG_DEVICE_MANUFACTURER "device-manufacturer"
+#endif
+
+#ifndef GST_TAG_DEVICE_MAKE
+#define GST_TAG_DEVICE_MAKE "device-make"
+#endif
+
+static void extract_gupnp_dlna_audio (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata);
+static void extract_gupnp_dlna_video (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata);
+static void extract_gupnp_dlna_image (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata);
+static void extract_gupnp_dlna_guess (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata);
+
+static TrackerExtractData data[] = {
+ { "audio/*", extract_gupnp_dlna_audio },
+ { "video/*", extract_gupnp_dlna_video },
+ { "image/*", extract_gupnp_dlna_image },
+ { "dlna/*", extract_gupnp_dlna_guess },
+ { "video/3gpp", extract_gupnp_dlna_guess },
+ { "video/mp4", extract_gupnp_dlna_guess },
+ { "video/x-ms-asf", extract_gupnp_dlna_guess },
+ { NULL, NULL }
+};
+
+typedef enum {
+ CONTENT_NONE,
+ CONTENT_GUESS,
+ CONTENT_VIDEO,
+ CONTENT_AUDIO,
+ CONTENT_IMAGE,
+} ContentType;
+
+typedef struct {
+ ContentType content;
+
+ gboolean has_image;
+ gboolean has_audio;
+ gboolean has_video;
+
+ const gchar *dlna_profile;
+
+ GstTagList *tags;
+
+ guint width;
+ guint height;
+ gfloat frame_rate;
+ gfloat aspect_ratio;
+
+ guint sample_rate;
+ guint bitrate;
+ guint channels;
+
+ guint duration;
+
+ gboolean is_content_encrypted;
+
+ unsigned char *album_art_data;
+ guint album_art_size;
+ const gchar *album_art_mime;
+
+} MetadataExtractor;
+
+static void
+add_int64_info (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ gint64 info)
+{
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_int64 (metadata, info);
+}
+
+static void
+add_uint_info (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ guint info)
+{
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_int64 (metadata, info);
+}
+
+static void
+add_string_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gchar *s;
+ gboolean ret;
+
+ s = NULL;
+ ret = gst_tag_list_get_string (tag_list, tag, &s);
+
+ if (s) {
+ if (ret && s[0] != '\0') {
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_unvalidated (metadata, s);
+ }
+
+ g_free (s);
+ }
+}
+
+static void
+add_uint_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ guint n;
+
+ ret = gst_tag_list_get_uint (tag_list, tag, &n);
+
+ if (ret) {
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_int64 (metadata, n);
+ }
+}
+
+static void
+add_int_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ gint n;
+
+ ret = gst_tag_list_get_int (tag_list, tag, &n);
+
+ if (ret) {
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_int64 (metadata, n);
+ }
+}
+
+static void
+add_double_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ gdouble n;
+
+ ret = gst_tag_list_get_double (tag_list, tag, &n);
+
+ if (ret) {
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_int64 (metadata, (gint64) n);
+ }
+}
+
+static void
+add_fraction_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ GValue n = {0,};
+ gfloat f;
+
+ ret = gst_tag_list_copy_value (&n, tag_list, tag);
+
+ if (ret) {
+ f = (gfloat)gst_value_get_fraction_numerator (&n)/
+ gst_value_get_fraction_denominator (&n);
+
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_double (metadata, (gdouble) f);
+
+ g_value_unset (&n);
+ }
+}
+
+static void
+add_y_date_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ GDate *date;
+ gboolean ret;
+
+ date = NULL;
+ ret = gst_tag_list_get_date (tag_list, tag, &date);
+
+ if (ret) {
+ if (date && g_date_valid (date)) {
+ if (date->julian)
+ ret = g_date_valid_julian (date->julian_days);
+ if (date->dmy)
+ ret = g_date_valid_dmy (date->day, date->month, date->year);
+ } else
+ ret = FALSE;
+ }
+
+ if (ret) {
+ gchar buf[25];
+
+ if (g_date_strftime (buf, 25, "%Y-%m-%dT%H:%M:%S%z", date)) {
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_unvalidated (metadata, buf);
+ }
+ }
+
+ if (date) {
+ g_date_free (date);
+ }
+}
+
+static void
+add_time_gst_tag (TrackerSparqlBuilder *metadata,
+ const gchar *uri,
+ const gchar *key,
+ GstTagList *tag_list,
+ const gchar *tag)
+{
+ gboolean ret;
+ guint64 n;
+
+ ret = gst_tag_list_get_uint64 (tag_list, tag, &n);
+
+ if (ret) {
+ gint64 duration;
+
+ duration = llroundl ((long double) n / (long double) GST_SECOND);
+
+ tracker_sparql_builder_predicate (metadata, key);
+ tracker_sparql_builder_object_int64 (metadata, duration);
+ }
+}
+
+static void
+add_keywords_gst_tag (TrackerSparqlBuilder *metadata,
+ GstTagList *tag_list)
+{
+ gboolean ret;
+ gchar *str;
+
+ ret = gst_tag_list_get_string (tag_list, GST_TAG_KEYWORDS, &str);
+
+ if (ret) {
+ GStrv keywords;
+ gint i = 0;
+
+ keywords = g_strsplit_set (str, " ,", -1);
+
+ while (keywords[i]) {
+ tracker_sparql_builder_predicate (metadata, "nie:keyword");
+ tracker_sparql_builder_object_unvalidated (metadata, g_strstrip (keywords[i]));
+ i++;
+ }
+
+ g_strfreev (keywords);
+ g_free (str);
+ }
+}
+
+/* static gboolean */
+/* get_embedded_album_art(MetadataExtractor *extractor) */
+/* { */
+/* const GValue *value; */
+/* guint lindex; */
+
+/* lindex = 0; */
+
+/* do { */
+/* value = gst_tag_list_get_value_index (extractor->tags, GST_TAG_IMAGE, lindex); */
+
+/* if (value) { */
+/* GstBuffer *buffer; */
+/* GstCaps *caps; */
+/* GstStructure *caps_struct; */
+/* gint type; */
+
+/* buffer = gst_value_get_buffer (value); */
+/* caps = gst_buffer_get_caps (buffer); */
+/* caps_struct = gst_caps_get_structure (buffer->caps, 0); */
+
+/* gst_structure_get_enum (caps_struct, */
+/* "image-type", */
+/* GST_TYPE_TAG_IMAGE_TYPE, */
+/* &type); */
+
+/* if ((type == GST_TAG_IMAGE_TYPE_FRONT_COVER)|| */
+/* ((type == GST_TAG_IMAGE_TYPE_UNDEFINED)&&(extractor->album_art_size == 0))) { */
+/* extractor->album_art_data = buffer->data; */
+/* extractor->album_art_size = buffer->size; */
+/* extractor->album_art_mime = gst_structure_get_name (caps_struct); */
+/* gst_caps_unref (caps); */
+/* return TRUE; */
+/* } */
+
+/* gst_caps_unref (caps); */
+
+/* lindex++; */
+/* } */
+/* } while (value); */
+
+/* value = gst_tag_list_get_value_index (extractor->tags, GST_TAG_PREVIEW_IMAGE, lindex); */
+
+/* if (value) { */
+/* GstBuffer *buffer; */
+/* GstStructure *caps_struct; */
+
+/* buffer = gst_value_get_buffer (value); */
+/* caps_struct = gst_caps_get_structure (buffer->caps, 0); */
+
+/* extractor->album_art_data = buffer->data; */
+/* extractor->album_art_size = buffer->size; */
+/* extractor->album_art_mime = gst_structure_get_name (caps_struct); */
+
+
+/* return TRUE; */
+/* } */
+
+/* return FALSE; */
+/* } */
+
+static void
+extract_metadata (MetadataExtractor *extractor,
+ const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata,
+ gchar **artist,
+ gchar **album,
+ gchar **scount)
+{
+ const gchar *temp;
+ gchar *s, *make = NULL, *model = NULL, *manuf = NULL, *make_model = NULL;
+ gboolean ret;
+ gint count;
+ gboolean needs_audio = FALSE;
+
+ g_return_if_fail (metadata != NULL);
+
+ if (extractor->tags) {
+ gchar *artist_uri = NULL;
+ gchar *performer_uri = NULL;
+ gchar *composer_uri = NULL;
+ gchar *album_uri = NULL;
+
+ /* General */
+ if (extractor->content == CONTENT_AUDIO || extractor->content == CONTENT_VIDEO) {
+ gchar *performer = NULL, *artist_local = NULL;
+
+ gst_tag_list_get_string (extractor->tags, GST_TAG_PERFORMER, &performer);
+ gst_tag_list_get_string (extractor->tags, GST_TAG_ARTIST, &artist_local);
+
+ if (artist_local) {
+ artist_uri = tracker_uri_printf_escaped ("urn:artist:%s", artist_local);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+ tracker_sparql_builder_subject_iri (preupdate, artist_uri);
+ tracker_sparql_builder_predicate (preupdate, "a");
+ tracker_sparql_builder_object (preupdate, "nmm:Artist");
+ tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
+ tracker_sparql_builder_object_unvalidated (preupdate, artist_local);
+ tracker_sparql_builder_insert_close (preupdate);
+ }
+
+ temp = tracker_coalesce_strip (2, performer, artist_local);
+
+ if (temp) {
+ performer_uri = tracker_uri_printf_escaped ("urn:artist:%s", temp);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+ tracker_sparql_builder_subject_iri (preupdate, performer_uri);
+ tracker_sparql_builder_predicate (preupdate, "a");
+ tracker_sparql_builder_object (preupdate, "nmm:Artist");
+ tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
+ tracker_sparql_builder_object_unvalidated (preupdate, temp);
+ tracker_sparql_builder_insert_close (preupdate);
+
+ *artist = g_strdup (temp);
+ }
+
+ g_free (performer);
+ g_free (artist_local);
+
+ s = NULL;
+ gst_tag_list_get_string (extractor->tags, GST_TAG_COMPOSER, &s);
+
+ if (s) {
+ composer_uri = tracker_uri_printf_escaped ("urn:artist:%s", s);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+
+ tracker_sparql_builder_subject_iri (preupdate, composer_uri);
+ tracker_sparql_builder_predicate (preupdate, "a");
+ tracker_sparql_builder_object (preupdate, "nmm:Artist");
+
+ tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
+ tracker_sparql_builder_object_unvalidated (preupdate, s);
+
+ tracker_sparql_builder_insert_close (preupdate);
+
+ g_free (s);
+ }
+
+ }
+
+ /* Audio */
+ s = NULL;
+ gst_tag_list_get_string (extractor->tags, GST_TAG_ALBUM, &s);
+ if (s) {
+ gboolean has_it;
+ guint count;
+ gdouble gain;
+
+ needs_audio = TRUE;
+
+ album_uri = tracker_uri_printf_escaped ("urn:album:%s", s);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "a");
+ tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum");
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle");
+ tracker_sparql_builder_object_unvalidated (preupdate, s);
+
+ if (artist_uri) {
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumArtist");
+ tracker_sparql_builder_object_iri (preupdate, artist_uri);
+ }
+
+ tracker_sparql_builder_insert_close (preupdate);
+
+ has_it = gst_tag_list_get_uint (extractor->tags,
+ GST_TAG_TRACK_COUNT,
+ &count);
+
+ if (has_it) {
+ tracker_sparql_builder_delete_open (preupdate, NULL);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_delete_close (preupdate);
+
+ tracker_sparql_builder_where_open (preupdate);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_where_close (preupdate);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
+ tracker_sparql_builder_object_int64 (preupdate, count);
+
+ tracker_sparql_builder_insert_close (preupdate);
+ }
+
+ has_it = gst_tag_list_get_uint (extractor->tags,
+ GST_TAG_ALBUM_VOLUME_NUMBER,
+ &count);
+
+ if (has_it) {
+ tracker_sparql_builder_delete_open (preupdate, NULL);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_delete_close (preupdate);
+
+ tracker_sparql_builder_where_open (preupdate);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_where_close (preupdate);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
+ tracker_sparql_builder_object_int64 (preupdate, count);
+
+ tracker_sparql_builder_insert_close (preupdate);
+ }
+
+ has_it = gst_tag_list_get_double (extractor->tags,
+ GST_TAG_ALBUM_GAIN,
+ &gain);
+
+ if (has_it) {
+ tracker_sparql_builder_delete_open (preupdate, NULL);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_delete_close (preupdate);
+
+ tracker_sparql_builder_where_open (preupdate);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_where_close (preupdate);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
+ tracker_sparql_builder_object_double (preupdate, gain);
+
+ tracker_sparql_builder_insert_close (preupdate);
+ }
+
+ has_it = gst_tag_list_get_double (extractor->tags,
+ GST_TAG_ALBUM_PEAK,
+ &gain);
+
+ if (has_it) {
+ tracker_sparql_builder_delete_open (preupdate, NULL);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_delete_close (preupdate);
+
+ tracker_sparql_builder_where_open (preupdate);
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
+ tracker_sparql_builder_object_variable (preupdate, "unknown");
+ tracker_sparql_builder_where_close (preupdate);
+
+ tracker_sparql_builder_insert_open (preupdate, NULL);
+
+ tracker_sparql_builder_subject_iri (preupdate, album_uri);
+ tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
+ tracker_sparql_builder_object_double (preupdate, gain);
+
+ tracker_sparql_builder_insert_close (preupdate);
+ }
+
+ *album = s;
+
+ }
+
+ if (extractor->content == CONTENT_AUDIO)
+ needs_audio = TRUE;
+
+ tracker_sparql_builder_predicate (metadata, "a");
+
+ if (needs_audio) {
+ tracker_sparql_builder_object (metadata, "nmm:MusicPiece");
+ tracker_sparql_builder_object (metadata, "nfo:Audio");
+ }
+
+ if (extractor->content == CONTENT_VIDEO) {
+ tracker_sparql_builder_object (metadata, "nmm:Video");
+ } else if (!needs_audio) {
+ tracker_sparql_builder_object (metadata, "nfo:Image");
+ }
+
+ s = NULL;
+ gst_tag_list_get_string (extractor->tags, GST_TAG_GENRE, &s);
+ if (s && strcmp (s, "Unknown") != 0) {
+ tracker_sparql_builder_predicate (metadata, "nfo:genre");
+ tracker_sparql_builder_object_unvalidated (metadata, s);
+ }
+ g_free (s);
+
+ add_string_gst_tag (metadata, uri, "nie:title", extractor->tags, GST_TAG_TITLE);
+ add_string_gst_tag (metadata, uri, "nie:copyright", extractor->tags, GST_TAG_COPYRIGHT);
+ add_string_gst_tag (metadata, uri, "nie:license", extractor->tags, GST_TAG_LICENSE);
+ add_string_gst_tag (metadata, uri, "dc:coverage", extractor->tags, GST_TAG_LOCATION);
+ add_y_date_gst_tag (metadata, uri, "nie:contentCreated", extractor->tags, GST_TAG_DATE);
+ add_string_gst_tag (metadata, uri, "nie:comment", extractor->tags, GST_TAG_COMMENT);
+
+ gst_tag_list_get_string (extractor->tags, GST_TAG_DEVICE_MODEL, &model);
+ gst_tag_list_get_string (extractor->tags, GST_TAG_DEVICE_MAKE, &make);
+ gst_tag_list_get_string (extractor->tags, GST_TAG_DEVICE_MANUFACTURER, &manuf);
+
+ if (make && model && manuf) {
+ make_model = tracker_merge_const (" ", 3, manuf, make, model);
+ } else if (make && model) {
+ make_model = tracker_merge_const (" ", 2, make, model);
+ } else if (make && manuf) {
+ make_model = tracker_merge_const (" ", 2, manuf, make);
+ } else if (model && manuf) {
+ make_model = tracker_merge_const (" ", 2, manuf, model);
+ } else if (model) {
+ make_model = g_strdup (model);
+ } else if (make) {
+ make_model = g_strdup (make);
+ } else if (manuf) {
+ make_model = g_strdup (manuf);
+ }
+
+ if (make_model) {
+ tracker_sparql_builder_predicate (metadata, "nfo:device");
+ tracker_sparql_builder_object_unvalidated (metadata, make_model);
+ g_free (make_model);
+ }
+
+ g_free (make);
+ g_free (model);
+ g_free (manuf);
+
+ /* FIXME add this stuff */
+ /* if (extractor->is_content_encrypted) { */
+ /* tracker_sparql_builder_predicate (metadata, "nfo:isContentEncrypted"); */
+ /* tracker_sparql_builder_object_boolean (metadata, TRUE); */
+ /* } */
+
+ if (extractor->content == CONTENT_VIDEO) {
+ add_string_gst_tag (metadata, uri, "dc:source", extractor->tags, GST_TAG_CLASSIFICATION);
+
+ if (performer_uri) {
+ tracker_sparql_builder_predicate (metadata, "nmm:leadActor");
+ tracker_sparql_builder_object_iri (metadata, performer_uri);
+ }
+
+ if (composer_uri) {
+ tracker_sparql_builder_predicate (metadata, "nmm:director");
+ tracker_sparql_builder_object_iri (metadata, composer_uri);
+ }
+
+ add_keywords_gst_tag (metadata, extractor->tags);
+ }
+
+ if (needs_audio) {
+ /* Audio */
+ ret = gst_tag_list_get_uint (extractor->tags, GST_TAG_TRACK_COUNT, &count);
+ if (ret) {
+ *scount = g_strdup_printf ("%d", count);
+ }
+
+ add_uint_gst_tag (metadata, uri, "nmm:trackNumber", extractor->tags, GST_TAG_TRACK_NUMBER);
+
+ add_double_gst_tag (metadata, uri, "nfo:gain", extractor->tags, GST_TAG_TRACK_GAIN);
+ add_double_gst_tag (metadata, uri, "nfo:peakGain", extractor->tags, GST_TAG_TRACK_PEAK);
+
+ if (performer_uri) {
+ tracker_sparql_builder_predicate (metadata, "nmm:performer");
+ tracker_sparql_builder_object_iri (metadata, performer_uri);
+ }
+
+ if (composer_uri) {
+ tracker_sparql_builder_predicate (metadata, "nmm:composer");
+ tracker_sparql_builder_object_iri (metadata, composer_uri);
+ }
+
+ if (album_uri) {
+ tracker_sparql_builder_predicate (metadata, "nmm:musicAlbum");
+ tracker_sparql_builder_object_iri (metadata, album_uri);
+ }
+ }
+
+ g_free (artist_uri);
+ g_free (performer_uri);
+ g_free (composer_uri);
+ g_free (album_uri);
+
+ add_string_gst_tag (metadata, uri, "nfo:codec", extractor->tags, GST_TAG_AUDIO_CODEC);
+ } else {
+ if (extractor->content == CONTENT_AUDIO)
+ needs_audio = TRUE;
+
+ tracker_sparql_builder_predicate (metadata, "a");
+
+ if (needs_audio) {
+ tracker_sparql_builder_object (metadata, "nmm:MusicPiece");
+ tracker_sparql_builder_object (metadata, "nfo:Audio");
+ }
+
+ if (extractor->content == CONTENT_VIDEO) {
+ tracker_sparql_builder_object (metadata, "nmm:Video");
+ } else if (extractor->content == CONTENT_IMAGE) {
+ tracker_sparql_builder_object (metadata, "nfo:Image");
+ }
+ }
+
+ if (extractor->content != CONTENT_IMAGE) {
+ if (extractor->channels) {
+ tracker_sparql_builder_predicate (metadata, "nfo.channels");
+ tracker_sparql_builder_object_int64 (metadata, extractor->channels);
+ }
+
+ if (extractor->sample_rate) {
+ tracker_sparql_builder_predicate (metadata, "nfo:sampleRate");
+ tracker_sparql_builder_object_int64 (metadata, extractor->sample_rate);
+ }
+
+ if (extractor->duration) {
+ tracker_sparql_builder_predicate (metadata, "nfo:duration");
+ tracker_sparql_builder_object_int64 (metadata, extractor->duration);
+ }
+ }
+
+ if (extractor->content == CONTENT_VIDEO) {
+ if (extractor->width) {
+ tracker_sparql_builder_predicate (metadata, "nfo:width");
+ tracker_sparql_builder_object_int64 (metadata, extractor->width);
+ }
+
+ if (extractor->height) {
+ tracker_sparql_builder_predicate (metadata, "nfo:height");
+ tracker_sparql_builder_object_int64 (metadata, extractor->height);
+ }
+
+ if (extractor->frame_rate) {
+ tracker_sparql_builder_predicate (metadata, "nfo:frameRate");
+ tracker_sparql_builder_object_double (metadata, extractor->frame_rate);
+ }
+
+ if (extractor->aspect_ratio) {
+ tracker_sparql_builder_predicate (metadata, "nfo:aspectRatio");
+ tracker_sparql_builder_object_double (metadata, extractor->aspect_ratio);
+ }
+ }
+
+ if (extractor->dlna_profile) {
+ tracker_sparql_builder_predicate (metadata, "nmm:dlnaProfile");
+ tracker_sparql_builder_object_string (metadata, extractor->dlna_profile);
+ }
+
+ /* if (extractor->content == CONTENT_AUDIO) { */
+ /* get_embedded_album_art (extractor); */
+ /* } */
+}
+
+static void
+extract_gupnp_dlna (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata,
+ ContentType content)
+{
+ GUPnPDLNADiscoverer *discoverer = NULL;
+ GUPnPDLNAInformation *dlna_info = NULL;
+ GError *error = NULL;
+ MetadataExtractor extractor;
+
+ gst_init (NULL, NULL);
+
+ extractor.has_image = FALSE;
+ extractor.has_video = FALSE;
+ extractor.has_audio = FALSE;
+
+ extractor.tags = NULL;
+
+ extractor.width = 0;
+ extractor.height = 0;
+ extractor.frame_rate = 0;
+ extractor.aspect_ratio = 0;
+
+ extractor.sample_rate = 0;
+ extractor.bitrate = 0;
+ extractor.channels = 0;
+
+ extractor.duration = 0;
+
+ extractor.is_content_encrypted = FALSE;
+
+ extractor.album_art_data = NULL;
+ extractor.album_art_size = 0;
+ extractor.album_art_mime = NULL;
+
+ discoverer = gupnp_dlna_discoverer_new (5*GST_SECOND);
+ dlna_info = gupnp_dlna_discoverer_discover_uri_sync (discoverer,
+ uri,
+ &error);
+
+ if (error) {
+ g_warning ("Error in gst-discovery: %s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ if (dlna_info) {
+ GstDiscovererInformation *info = NULL;
+ GList *iter;
+
+ gchar *artist, *album, *scount;
+
+ album = NULL;
+ scount = NULL;
+ artist = NULL;
+
+ info = gupnp_dlna_information_get_info (dlna_info);
+
+ iter = g_list_first (info->stream_list);
+
+ while (iter != NULL) {
+ GstStreamInformation *stream = NULL;
+ GstTagList *tmp = NULL;
+
+ stream = iter->data;
+
+ if (stream->misc == NULL) {
+ g_debug ("misc NULL");
+ }
+
+ switch (stream->streamtype) {
+ case GST_STREAM_AUDIO:
+ extractor.has_audio = TRUE;
+ extractor.sample_rate = ((GstStreamAudioInformation *)stream)->sample_rate;
+ extractor.bitrate = ((GstStreamAudioInformation *)stream)->bitrate;
+ extractor.channels = ((GstStreamAudioInformation *)stream)->channels;
+ break;
+ case GST_STREAM_VIDEO:
+ extractor.has_video = TRUE;
+ extractor.frame_rate = (gfloat)gst_value_get_fraction_numerator (&((GstStreamVideoInformation *)stream)->frame_rate)/
+ gst_value_get_fraction_denominator (&((GstStreamVideoInformation *)stream)->frame_rate);
+ extractor.width = ((GstStreamVideoInformation *)stream)->width;
+ extractor.height = ((GstStreamVideoInformation *)stream)->height;
+ extractor.aspect_ratio = (gfloat)gst_value_get_fraction_numerator (&((GstStreamVideoInformation *)stream)->pixel_aspect_ratio)/
+ gst_value_get_fraction_denominator (&((GstStreamVideoInformation *)stream)->pixel_aspect_ratio);
+ break;
+ case GST_STREAM_IMAGE:
+ extractor.has_image = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ tmp = gst_tag_list_merge (extractor.tags, stream->tags, GST_TAG_MERGE_APPEND);
+ if (extractor.tags) {
+ gst_tag_list_free (extractor.tags);
+ }
+ extractor.tags = tmp;
+
+ iter = g_list_next (iter);
+ }
+
+ extractor.duration = info->duration / GST_SECOND;
+
+ extractor.dlna_profile = gupnp_dlna_information_get_name (dlna_info);
+
+ if (content != CONTENT_GUESS) {
+ extractor.content = content;
+ } else {
+ if (extractor.has_video) {
+ extractor.content = CONTENT_VIDEO;
+ } else if (extractor.has_audio) {
+ extractor.content = CONTENT_AUDIO;
+ } else if (extractor.has_image) {
+ extractor.content = CONTENT_IMAGE;
+ } else {
+ extractor.content = CONTENT_NONE;
+ }
+ }
+
+ extract_metadata (&extractor, uri, preupdate, metadata, &artist, &album, &scount);
+
+ /* tracker_albumart_process (extractor.album_art_data, */
+ /* extractor.album_art_size, */
+ /* extractor.album_art_mime, */
+ /* artist, */
+ /* album, */
+ /* uri); */
+
+ gst_tag_list_free (extractor.tags);
+ g_free (artist);
+ g_free (album);
+ g_free (scount);
+
+ }
+
+ g_object_unref (discoverer);
+ g_object_unref (dlna_info);
+
+}
+
+static void
+extract_gupnp_dlna_audio (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata)
+{
+ extract_gupnp_dlna (uri, preupdate, metadata, CONTENT_AUDIO);
+}
+
+static void
+extract_gupnp_dlna_video (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata)
+{
+ extract_gupnp_dlna (uri, preupdate, metadata, CONTENT_VIDEO);
+}
+
+static void
+extract_gupnp_dlna_image (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata)
+{
+ extract_gupnp_dlna (uri, preupdate, metadata, CONTENT_IMAGE);
+}
+
+static void
+extract_gupnp_dlna_guess (const gchar *uri,
+ TrackerSparqlBuilder *preupdate,
+ TrackerSparqlBuilder *metadata)
+{
+ extract_gupnp_dlna (uri, preupdate, metadata, CONTENT_GUESS);
+}
+
+
+TrackerExtractData *
+tracker_extract_get_data (void)
+{
+ return data;
+}
+