[tracker] Fixes: GB#608395, Flac extractor
- From: Martyn James Russell <mr src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [tracker] Fixes: GB#608395, Flac extractor
- Date: Tue, 2 Feb 2010 15:48:13 +0000 (UTC)
commit 7cee56e7bfe1e81acff8078742d16b234a68f254
Author: Iain Holmes <iain openedhand com>
Date: Tue Feb 2 14:13:37 2010 +0000
Fixes: GB#608395, Flac extractor
Add support for Flac files.
configure.ac | 34 +++
src/tracker-extract/Makefile.am | 12 +
src/tracker-extract/tracker-extract-flac.c | 336 ++++++++++++++++++++++++++++
3 files changed, 382 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index fbb9d1c..39d6043 100644
--- a/configure.ac
+++ b/configure.ac
@@ -146,6 +146,7 @@ POPPLER_GLIB_REQUIRED=0.4.5
CAIRO_REQUIRED=1.0
GDK_REQUIRED=1.0
LIBVORBIS_REQUIRED=0.22
+LIBFLAC_REQUIRED=1.2.1
LIBEXIF_REQUIRED=0.6
LIBGSF_REQUIRED=1.13
EXEMPI_REQUIRED=2.1.0
@@ -1301,6 +1302,38 @@ fi
AM_CONDITIONAL(HAVE_LIBVORBIS, test "x$have_libvorbis" = "xyes")
####################################################################
+# Check for flac
+####################################################################
+
+AC_ARG_ENABLE(libflac,
+ AS_HELP_STRING([--enable-libflac],
+ [enable extractor for flac data [[default=auto]]]),,
+ [enable_libflac=auto])
+
+if test "x$enable_libflac" != "xno" ; then
+ PKG_CHECK_MODULES(LIBFLAC,
+ [flac >= $LIBFLAC_REQUIRED],
+ [have_libflac=yes],
+ [have_libflac=no])
+ AC_SUBST(LIBFLAC_CFLAGS)
+ AC_SUBST(LIBFLAC_LIBS)
+
+ if test "x$have_libflac" = "xyes"; then
+ AC_DEFINE(HAVE_LIBFLAC, [], [Define if we have libflac])
+ fi
+else
+ have_libflac="no (disabled)"
+fi
+
+if test "x$enable_libflac" = "xyes"; then
+ if test "x$have_libflac" != "xyes"; then
+ AC_MSG_ERROR([Couldn't find libflac >= $LIBFLAC_REQUIRED.])
+ fi
+fi
+
+AM_CONDITIONAL(HAVE_LIBFLAC, test "x$have_libflac" = "xyes")
+
+####################################################################
# Check ioprio support
####################################################################
@@ -1720,6 +1753,7 @@ Metadata Extractors:
Support JPEG: $have_libjpeg (xmp: $have_exempi, exif: $have_libexif, iptc: $have_libiptcdata)
Support TIFF: $have_libtiff (xmp: $have_exempi, exif: yes, iptc: $have_libiptcdata)
Support Vorbis (ogg/etc): $have_libvorbis
+ Support Flac: $have_libflac
Support MS & Open Office: $have_libgsf
Support XML / HTML: $have_libxml2
Support embedded / sidecar XMP: $have_exempi
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index f3bc51d..240566f 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -45,6 +45,10 @@ if HAVE_LIBVORBIS
modules_LTLIBRARIES += libextract-vorbis.la
endif
+if HAVE_LIBFLAC
+modules_LTLIBRARIES += libextract-flac.la
+endif
+
if HAVE_EXEMPI
modules_LTLIBRARIES += libextract-xmp.la
endif
@@ -124,6 +128,14 @@ libextract_vorbis_la_LIBADD = \
$(GLIB2_LIBS) \
$(GCOV_LIBS)
+# Flac
+libextract_flac_la_SOURCES = tracker-extract-flac.c $(escape_sources)
+libextract_flac_la_LDFLAGS = $(module_flags)
+libextract_flac_la_LIBADD = \
+ $(LIBFLAC_LIBS) \
+ $(GLIB2_LIBS) \
+ $(GCOV_LIBS)
+
# MPlayer
libextract_mplayer_la_SOURCES = tracker-extract-mplayer.c
libextract_mplayer_la_LDFLAGS = $(module_flags)
diff --git a/src/tracker-extract/tracker-extract-flac.c b/src/tracker-extract/tracker-extract-flac.c
new file mode 100644
index 0000000..dbe7b63
--- /dev/null
+++ b/src/tracker-extract/tracker-extract-flac.c
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2010 Intel Corporation
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <glib.h>
+
+#include <FLAC/metadata.h>
+
+#include <libtracker-common/tracker-file-utils.h>
+#include <libtracker-common/tracker-ontology.h>
+#include <libtracker-common/tracker-utils.h>
+
+#include <libtracker-extract/tracker-extract.h>
+
+typedef struct {
+ gchar *title;
+ gchar *artist;
+ gchar *album;
+ gchar *albumartist;
+ gchar *trackcount;
+ gchar *tracknumber;
+ gchar *discno;
+ gchar *performer;
+ gchar *trackgain;
+ gchar *trackpeakgain;
+ gchar *albumgain;
+ gchar *albumpeakgain;
+ gchar *date;
+ gchar *comment;
+ gchar *genre;
+ gchar *mbalbumid;
+ gchar *mbartistid;
+ gchar *mbalbumartistid;
+ gchar *mbtrackid;
+ gchar *lyrics;
+ gchar *copyright;
+ gchar *license;
+ gchar *organisation;
+ gchar *location;
+ gchar *publisher;
+
+ guint samplerate;
+ guint channels;
+ guint bps;
+ guint64 total;
+} FlacData;
+
+static void extract_flac (const char *uri,
+ TrackerSparqlBuilder *metadata);
+
+static TrackerExtractData extract_data[] = {
+ { "audio/x-flac", extract_flac },
+ { NULL, NULL }
+};
+
+static void
+parse_vorbis_comments (FLAC__StreamMetadata_VorbisComment *comment,
+ FlacData *fd)
+{
+ gint i;
+
+ /* FIXME: I hate the amount of duplicating this does, complete
+ memory fragmentation. We should be able to use some
+ GStringChunks */
+ for (i = 0; i < comment->num_comments; i++) {
+ FLAC__StreamMetadata_VorbisComment_Entry entry;
+
+ entry = comment->comments[i];
+
+ /* entry.entry is the format NAME=metadata */
+ if (g_ascii_strncasecmp (entry.entry, "title", 5) == 0) {
+ fd->title = g_strdup (entry.entry + 6);
+ } else if (g_ascii_strncasecmp (entry.entry, "artist", 6) == 0) {
+ /* FIXME: Handle multiple instances of artist */
+ if (fd->artist == NULL) {
+ fd->artist = g_strdup (entry.entry + 7);
+ }
+ } else if (g_ascii_strncasecmp (entry.entry, "album", 5) == 0) {
+ fd->album = g_strdup (entry.entry + 6);
+ } else if (g_ascii_strncasecmp (entry.entry, "albumartist", 11) == 0) {
+ fd->albumartist = g_strdup (entry.entry + 12);
+ } else if (g_ascii_strncasecmp (entry.entry, "trackcount", 10) == 0) {
+ fd->trackcount = g_strdup (entry.entry + 11);
+ } else if (g_ascii_strncasecmp (entry.entry, "tracknumber", 11) == 0) {
+ fd->tracknumber = g_strdup (entry.entry + 12);
+ } else if (g_ascii_strncasecmp (entry.entry, "discno", 6) == 0) {
+ fd->discno = g_strdup (entry.entry + 7);
+ } else if (g_ascii_strncasecmp (entry.entry, "performer", 9) == 0) {
+ /* FIXME: Handle multiple instances of performer */
+ if (fd->performer == NULL) {
+ fd->performer = g_strdup (entry.entry + 10);
+ }
+ } else if (g_ascii_strncasecmp (entry.entry, "trackgain", 9) == 0) {
+ fd->trackgain = g_strdup (entry.entry + 10);
+ } else if (g_ascii_strncasecmp (entry.entry, "trackpeakgain", 13) == 0) {
+ fd->trackpeakgain = g_strdup (entry.entry + 14);
+ } else if (g_ascii_strncasecmp (entry.entry, "albumgain", 9) == 0) {
+ fd->albumgain = g_strdup (entry.entry + 10);
+ } else if (g_ascii_strncasecmp (entry.entry, "albumpeakgain", 13) == 0) {
+ fd->albumpeakgain = g_strdup (entry.entry + 14);
+ } else if (g_ascii_strncasecmp (entry.entry, "date", 4) == 0) {
+ fd->date = g_strdup (entry.entry + 5);
+ } else if (g_ascii_strncasecmp (entry.entry, "comment", 7) == 0) {
+ fd->comment = g_strdup (entry.entry + 8);
+ } else if (g_ascii_strncasecmp (entry.entry, "genre", 5) == 0) {
+ fd->genre = g_strdup (entry.entry + 6);
+ } else if (g_ascii_strncasecmp (entry.entry, "mbalbumid", 9) == 0) {
+ fd->mbalbumid = g_strdup (entry.entry + 10);
+ } else if (g_ascii_strncasecmp (entry.entry, "mbartistid", 10) == 0) {
+ fd->mbartistid = g_strdup (entry.entry + 11);
+ } else if (g_ascii_strncasecmp (entry.entry, "mbalbumartistid", 15) == 0) {
+ fd->mbalbumartistid = g_strdup (entry.entry + 16);
+ } else if (g_ascii_strncasecmp (entry.entry, "mbtrackid", 9) == 0) {
+ fd->mbtrackid = g_strdup (entry.entry + 10);
+ } else if (g_ascii_strncasecmp (entry.entry, "lyrics", 6) == 0) {
+ fd->lyrics = g_strdup (entry.entry + 7);
+ } else if (g_ascii_strncasecmp (entry.entry, "copyright", 9) == 0) {
+ fd->copyright = g_strdup (entry.entry + 10);
+ } else if (g_ascii_strncasecmp (entry.entry, "license", 8) == 0) {
+ fd->license = g_strdup (entry.entry + 9);
+ } else if (g_ascii_strncasecmp (entry.entry, "organization", 12) == 0) {
+ fd->organisation = g_strdup (entry.entry + 13);
+ } else if (g_ascii_strncasecmp (entry.entry, "location", 8) == 0) {
+ fd->location = g_strdup (entry.entry + 9);
+ } else if (g_ascii_strncasecmp (entry.entry, "publisher", 9) == 0) {
+ fd->publisher = g_strdup (entry.entry + 10);
+ }
+ }
+}
+
+static void
+add_tuple (TrackerSparqlBuilder *metadata,
+ const char *predicate,
+ const char *object)
+{
+ if (object) {
+ tracker_sparql_builder_predicate (metadata, predicate);
+ tracker_sparql_builder_object_unvalidated (metadata, object);
+ }
+}
+
+static void
+extract_flac (const gchar *uri,
+ TrackerSparqlBuilder *metadata)
+{
+ FLAC__Metadata_SimpleIterator *iter;
+ FLAC__StreamMetadata *stream = NULL, *vorbis, *picture;
+ FLAC__bool success;
+ FlacData fd = { 0 };
+ gchar *filename, *creator, *artist_uri = NULL, *album_uri = NULL;
+ goffset size;
+
+ filename = g_filename_from_uri (uri, NULL, NULL);
+
+ size = tracker_file_get_size (filename);
+
+ if (size < 18) {
+ g_free (filename);
+ return;
+ }
+
+ iter = FLAC__metadata_simple_iterator_new ();
+ success = FLAC__metadata_simple_iterator_init (iter, filename, TRUE, FALSE);
+ g_free (filename);
+
+ if (!success) {
+ FLAC__metadata_simple_iterator_delete (iter);
+ return;
+ }
+
+ while (!FLAC__metadata_simple_iterator_is_last (iter)) {
+ switch (FLAC__metadata_simple_iterator_get_block_type (iter)) {
+ case FLAC__METADATA_TYPE_STREAMINFO:
+ stream = FLAC__metadata_simple_iterator_get_block (iter);
+ break;
+
+ case FLAC__METADATA_TYPE_VORBIS_COMMENT:
+ vorbis = FLAC__metadata_simple_iterator_get_block (iter);
+ parse_vorbis_comments (&(vorbis->data.vorbis_comment), &fd);
+ FLAC__metadata_object_delete (vorbis);
+ break;
+
+ case FLAC__METADATA_TYPE_PICTURE:
+ picture = FLAC__metadata_simple_iterator_get_block (iter);
+ /* Deal with picture */
+ FLAC__metadata_object_delete (picture);
+ break;
+
+ default:
+ break;
+ }
+
+ FLAC__metadata_simple_iterator_next (iter);
+ }
+
+ /* This will find the first non-NULL and then free the rest */
+ creator = tracker_coalesce (3, fd.artist, fd.albumartist,
+ fd.performer);
+ if (creator) {
+ artist_uri = tracker_uri_printf_escaped ("urn:artist:%s",
+ creator);
+ tracker_sparql_builder_subject_iri (metadata, artist_uri);
+ tracker_sparql_builder_predicate (metadata, "a");
+ tracker_sparql_builder_object (metadata, "nmm:Artist");
+ tracker_sparql_builder_predicate (metadata, "nmm:artistName");
+ tracker_sparql_builder_object_unvalidated (metadata, creator);
+ g_free (creator);
+ }
+
+ if (fd.album) {
+ album_uri = tracker_uri_printf_escaped ("urn:album:%s",
+ fd.album);
+ tracker_sparql_builder_subject_iri (metadata, album_uri);
+ tracker_sparql_builder_predicate (metadata, "a");
+ tracker_sparql_builder_object (metadata, "nmm:MusicAlbum");
+ tracker_sparql_builder_predicate (metadata, "nmm:albumTitle");
+ tracker_sparql_builder_object_unvalidated (metadata,
+ fd.album);
+
+ if (fd.trackcount) {
+ tracker_sparql_builder_predicate (metadata, "nmm:albumTrackCount");
+ tracker_sparql_builder_object_unvalidated (metadata,
+ fd.trackcount);
+ }
+ }
+
+ tracker_sparql_builder_subject_iri (metadata, uri);
+ tracker_sparql_builder_predicate (metadata, "a");
+ tracker_sparql_builder_object (metadata, "nmm:MusicPiece");
+ tracker_sparql_builder_object (metadata, "nfo:Audio");
+
+ add_tuple (metadata, "nmm:performer", artist_uri);
+ g_free (artist_uri);
+
+ add_tuple (metadata, "nmm:musicAlbum", album_uri);
+ g_free (album_uri);
+
+ add_tuple (metadata, "nie:title", fd.title);
+ add_tuple (metadata, "nmm:trackNumber", fd.tracknumber);
+
+ /* FIXME: This is commented out in vorbis extractor... */
+ add_tuple (metadata, "nmm:setNumber", fd.discno);
+
+ /* FIXME: Trackgain/Trackpeakgain: commented out in vorbis */
+
+ add_tuple (metadata, "nmm:albumGain", fd.albumgain);
+ add_tuple (metadata, "nmm:albumPeakGain", fd.albumpeakgain);
+ add_tuple (metadata, "nie:comment", fd.comment);
+ add_tuple (metadata, "nie:contentCreated", "2003-08-22T19:52:10Z");
+ add_tuple (metadata, "nfo:genre", fd.genre);
+ add_tuple (metadata, "nie:plainTextContent", fd.lyrics);
+ add_tuple (metadata, "nie:copyright", fd.copyright);
+ add_tuple (metadata, "nie:license", fd.license);
+
+ if (fd.publisher) {
+ tracker_sparql_builder_predicate (metadata, "dc:publisher");
+
+ tracker_sparql_builder_object_blank_open (metadata);
+ tracker_sparql_builder_predicate (metadata, "a");
+ tracker_sparql_builder_object (metadata, "nco:Contact");
+
+ tracker_sparql_builder_predicate (metadata, "nco:fullname");
+ tracker_sparql_builder_object_unvalidated (metadata,
+ fd.publisher);
+ tracker_sparql_builder_object_blank_close (metadata);
+ }
+
+ if (stream) {
+ tracker_sparql_builder_predicate (metadata, "nfo:sampleRate");
+ tracker_sparql_builder_object_int64 (metadata,
+ stream->data.stream_info.sample_rate);
+
+ tracker_sparql_builder_predicate (metadata, "nfo:channels");
+ tracker_sparql_builder_object_int64 (metadata,
+ stream->data.stream_info.channels);
+
+ tracker_sparql_builder_predicate (metadata,
+ "nfo:averageBitrate");
+ tracker_sparql_builder_object_int64 (metadata,
+ stream->data.stream_info.bits_per_sample);
+
+ tracker_sparql_builder_predicate (metadata, "nfo:duration");
+ tracker_sparql_builder_object_int64 (metadata,
+ stream->data.stream_info.total_samples /
+ stream->data.stream_info.sample_rate);
+ }
+
+ g_free (fd.title);
+ g_free (fd.trackcount);
+ g_free (fd.tracknumber);
+ g_free (fd.discno);
+ g_free (fd.trackgain);
+ g_free (fd.trackpeakgain);
+ g_free (fd.albumgain);
+ g_free (fd.albumpeakgain);
+ g_free (fd.date);
+ g_free (fd.comment);
+ g_free (fd.genre);
+ g_free (fd.mbalbumid);
+ g_free (fd.mbartistid);
+ g_free (fd.mbalbumartistid);
+ g_free (fd.mbtrackid);
+ g_free (fd.lyrics);
+ g_free (fd.copyright);
+ g_free (fd.license);
+ g_free (fd.organisation);
+ g_free (fd.location);
+ g_free (fd.publisher);
+}
+
+TrackerExtractData *
+tracker_extract_get_data (void)
+{
+ return extract_data;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]