diff options
author | Mikael Ottela <mikael.ottela@ixonos.com> | 2010-08-12 17:12:47 +0300 |
---|---|---|
committer | Mikael Ottela <mikael.ottela@ixonos.com> | 2010-08-12 18:22:22 +0300 |
commit | 1405ee26b152b7a62a64d1584a4c5b2e55c32f79 (patch) | |
tree | 251d2cb413091ae89932fef0d32d8589231b79f8 | |
parent | fefe77ce85e736158c9a3b9aec3d92d2bfe39e1d (diff) | |
download | tracker-1405ee26b152b7a62a64d1584a4c5b2e55c32f79.tar.gz |
Add an extractor that uses gupnp-dlna for gstreamer based metadata extraction.
-rw-r--r-- | configure.ac | 33 | ||||
-rw-r--r-- | src/tracker-extract/Makefile.am | 14 | ||||
-rw-r--r-- | src/tracker-extract/tracker-extract-gupnp-dlna.c | 999 |
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; +} + |