[tracker/writeback: 7/8] Implemented writeback for MP3's Title field using id3lib



commit 5ddd5c9b6132cd5530d0f0eb1fd956a32bb958ca
Author: Philip Van Hoof <philip codeminded be>
Date:   Wed Nov 11 18:06:56 2009 +0100

    Implemented writeback for MP3's Title field using id3lib
    
    This is a prototype implementation

 configure.ac                                       |   51 ++++++++
 data/ontologies/30-nie.ontology                    |    3 +-
 data/ontologies/90-tracker.ontology                |    7 -
 src/tracker-writeback/Makefile.am                  |   17 ++-
 .../tracker-writeback-dispatcher.c                 |   56 ++++-----
 src/tracker-writeback/tracker-writeback-dummy.c    |  103 ---------------
 src/tracker-writeback/tracker-writeback-mp3.c      |  132 ++++++++++++++++++++
 src/tracker-writeback/tracker-writeback.c          |    4 +-
 src/tracker-writeback/tracker-writeback.h          |    2 -
 9 files changed, 222 insertions(+), 153 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index d087078..11c15dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -154,6 +154,7 @@ EDS_REQUIRED=2.25.5
 # Unlikely version for now, Nepomuk integration isn't finished in streamanalyzer atm
 LIBSTREAMANALYZER_REQUIRED=0.7.0
 GEE_REQUIRED=0.3
+ID3LIB_REQUIRED=3.8.3
 
 # Library Checks
 PKG_CHECK_MODULES(GLIB2, [glib-2.0 >= $GLIB_REQUIRED])
@@ -229,6 +230,52 @@ fi
 GLIB_GENMARSHAL=`$PKG_CONFIG glib-2.0 --variable=glib_genmarshal`
 AC_SUBST(GLIB_GENMARSHAL)
 
+####################################################################
+# ID3lib for MP3 writeback support
+####################################################################
+
+# FIXME This should be package based. Unfortunately in several main
+# distros, it is not.
+
+OLD_CFLAGS="$CFLAGS"
+OLD_LIBS="$LIBS"
+CFLAGS=""
+LIBS=""
+
+AC_ARG_ENABLE(id3lib, 
+	      AS_HELP_STRING([--enable-id3lib], 
+	                     [enable writeback for MP3 data [[default=auto]]]),,
+	      [enable_id3lib=auto])
+
+if test "x$enable_id3lib" != "xno" ; then
+   AC_CHECK_HEADER(id3.h,
+   AC_CHECK_LIB(id3, ID3Tag_New))
+
+   have_id3lib=${ac_cv_lib_id3_ID3Tag_New:-no}
+
+   ID3LIB_CFLAGS="$CFLAGS"
+   ID3LIB_LIBS="$LIBS"
+
+   AC_SUBST(ID3LIB_CFLAGS)
+   AC_SUBST(ID3LIB_LIBS)
+
+   if test "x$have_libjpeg" = "xyes"; then
+      AC_DEFINE(HAVE_ID3LIB, [], [Define if we have id3lib])
+   fi
+else
+   have_id3lib="no  (disabled)"
+fi
+
+if test "x$enable_id3lib" = "xyes"; then
+   if test "x$have_id3lib" != "xyes"; then
+      AC_MSG_ERROR([Couldn't find id3lib >= $ID3LIB_REQUIRED.])
+   fi
+fi
+
+AM_CONDITIONAL(HAVE_ID3LIB, test "x$have_id3lib" = "xyes")
+
+CFLAGS="$OLD_CFLAGS"
+LIBS="$OLD_LIBS"
 
 ####################################################################
 # Stream Analyzer
@@ -1557,6 +1604,10 @@ Plugins:
 	Evolution plugin    (data-push):	$have_evolution_plugin
 	KMail plugin        (data-push):	$enable_kmail_push_module
 
+Writeback:
+
+	MP3 writeback:                          $have_id3lib
+
 Warning:
 
         You must make sure SQLite is compiled with --enable-threadsafe
diff --git a/data/ontologies/30-nie.ontology b/data/ontologies/30-nie.ontology
index a7b493e..4d77380 100644
--- a/data/ontologies/30-nie.ontology
+++ b/data/ontologies/30-nie.ontology
@@ -29,7 +29,8 @@ nie:title a rdf:Property ;
 	rdfs:domain nie:InformationElement ;
 	rdfs:range xsd:string ;
 	tracker:fulltextIndexed true ;
-	tracker:weight 10 .
+	tracker:weight 10 ;
+	tracker:writeback true .
 
 nie:subject a rdf:Property ;
 	rdfs:label "Subject" ;
diff --git a/data/ontologies/90-tracker.ontology b/data/ontologies/90-tracker.ontology
index 709a9a1..88e9936 100644
--- a/data/ontologies/90-tracker.ontology
+++ b/data/ontologies/90-tracker.ontology
@@ -49,12 +49,5 @@ tracker:writeback a rdf:Property ;
 	rdfs:domain rdf:Property ;
 	rdfs:range xsd:boolean .
 
-# Remove this afterward
-tracker:writebackTestField a rdf:Property ;
-	nrl:maxCardinality 1 ;
-	tracker:writeback true ;
-	rdfs:domain rdfs:Resource ;
-	rdfs:range xsd:string .
-
 fts: a tracker:Namespace ;
 	tracker:prefix "fts" .
diff --git a/src/tracker-writeback/Makefile.am b/src/tracker-writeback/Makefile.am
index 9e9d6aa..3c20f99 100644
--- a/src/tracker-writeback/Makefile.am
+++ b/src/tracker-writeback/Makefile.am
@@ -14,15 +14,18 @@ INCLUDES = 								\
 	$(GLIB2_CFLAGS)							\
 	$(GCOV_CFLAGS)							\
 	$(GMODULE_CFLAGS) 						\
-	$(DBUS_CFLAGS)
-
-modules_LTLIBRARIES = 							\
-	libwriteback-dummy.la
-
-# dummy
-libwriteback_dummy_la_SOURCES = tracker-writeback-dummy.c
-libwriteback_dummy_la_LDFLAGS = $(module_flags)
-libwriteback_dummy_la_LIBADD = $(GLIB2_LIBS) $(GCOV_LIBS)
+	$(DBUS_CFLAGS)							\
+	$(ID3LIB_CFLAGS)
+
+modules_LTLIBRARIES =
+
+# MP3
+if HAVE_ID3LIB
+modules_LTLIBRARIES+=libwriteback-mp3.la
+libwriteback_mp3_la_SOURCES = tracker-writeback-mp3.c
+libwriteback_mp3_la_LDFLAGS = $(module_flags)
+libwriteback_mp3_la_LIBADD = $(GLIB2_LIBS) $(GCOV_LIBS) $(ID3LIB_LIBS)
+endif
 
 #
 # Binaries
diff --git a/src/tracker-writeback/tracker-writeback-dispatcher.c b/src/tracker-writeback/tracker-writeback-dispatcher.c
index beeaa4a..2e0dabd 100644
--- a/src/tracker-writeback/tracker-writeback-dispatcher.c
+++ b/src/tracker-writeback/tracker-writeback-dispatcher.c
@@ -39,8 +39,7 @@ typedef struct {
 } TrackerWritebackDispatcherPrivate;
 
 typedef struct {
-        TrackerWritebackDispatcher *dispatcher;
-        GFile *file;
+	TrackerWritebackDispatcher *dispatcher;
 } QueryData;
 
 #define TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_WRITEBACK_DISPATCHER, TrackerWritebackDispatcherPrivate))
@@ -260,33 +259,30 @@ on_sparql_result_received (GPtrArray *result,
                            gpointer   user_data)
 {
 	TrackerWritebackDispatcherPrivate *priv;
-        TrackerWritebackModule *module;
-        TrackerWriteback *writeback;
-	gchar *subject = user_data;
-        GHashTableIter iter;
-        gpointer key, value;
-        QueryData *data;
+	TrackerWritebackModule *module;
+	TrackerWriteback *writeback;
+	GHashTableIter iter;
+	gpointer key, value;
+	QueryData *data;
 
-        data = user_data;
-        priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (data->dispatcher);
+	data = user_data;
+	priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (data->dispatcher);
 
-        /* FIXME: Lookup module by mimetype */
-        g_hash_table_iter_init (&iter, priv->modules);
+	/* FIXME: Lookup module by mimetype */
+	g_hash_table_iter_init (&iter, priv->modules);
 
-        if (!g_hash_table_iter_next (&iter, &key, &value)) {
-                return;
-        }
+	if (!g_hash_table_iter_next (&iter, &key, &value)) {
+		return;
+	}
 
-        module = value;
-        writeback = tracker_writeback_module_create (module);
+	module = value;
+	writeback = tracker_writeback_module_create (module);
 
-        tracker_writeback_update_metadata (writeback, data->file, result);
+	tracker_writeback_update_metadata (writeback, result);
 
-        g_object_unref (writeback);
+	g_object_unref (writeback);
 
-        g_object_unref (data->file);
-        g_slice_free (QueryData, data);
-	g_free (subject);
+	g_slice_free (QueryData, data);
 }
 
 static void
@@ -295,7 +291,7 @@ on_writeback_cb (DBusGProxy                 *proxy,
                  TrackerWritebackDispatcher *object)
 {
 	TrackerWritebackDispatcherPrivate *priv;
-        QueryData *data;
+	QueryData *data;
 	guint n;
 
 	priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (object);
@@ -303,20 +299,20 @@ on_writeback_cb (DBusGProxy                 *proxy,
 	for (n = 0; subjects[n] != NULL; n++) {
 		gchar *query;
 
-
-		query = g_strdup_printf ("SELECT ?predicate ?object { "
-		                                "<%s> ?predicate ?object . "
+		query = g_strdup_printf ("SELECT ?url ?predicate ?object { "
+		                                "<%s> ?predicate ?object ; "
+		                                     "nie:isStoredAs ?url . "
 		                                "?predicate tracker:writeback true "
 		                         "}", subjects[n]);
 
-                data = g_slice_new (QueryData);
-                data->dispatcher = object;
-                data->file = g_file_new_for_uri (subjects[n]);
+		data = g_slice_new (QueryData);
+		data->dispatcher = object;
 
 		tracker_resources_sparql_query_async (priv->client,
 		                                      query,
 		                                      on_sparql_result_received,
-                                                      data);
+		                                      data);
+
 		g_free (query);
 	}
 }
diff --git a/src/tracker-writeback/tracker-writeback-mp3.c b/src/tracker-writeback/tracker-writeback-mp3.c
new file mode 100644
index 0000000..6bb78e7
--- /dev/null
+++ b/src/tracker-writeback/tracker-writeback-mp3.c
@@ -0,0 +1,132 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008, Nokia
+ *
+ * This library 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 library 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 library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ *
+ * Authors: Philip Van Hoof <philip codeminded be>
+ */
+
+#include <id3.h>
+
+#include <libtracker-common/tracker-ontology.h>
+
+#include "tracker-writeback.h"
+
+#define TRACKER_TYPE_WRITEBACK_MP3    (tracker_writeback_mp3_get_type ())
+
+typedef struct TrackerWritebackMP3 TrackerWritebackMP3;
+typedef struct TrackerWritebackMP3Class TrackerWritebackMP3Class;
+
+struct TrackerWritebackMP3 {
+        TrackerWriteback parent_instance;
+};
+
+struct TrackerWritebackMP3Class {
+        TrackerWritebackClass parent_class;
+};
+
+static GType    tracker_writeback_mp3_get_type        (void) G_GNUC_CONST;
+static gboolean tracker_writeback_mp3_update_metadata (TrackerWriteback *writeback,
+                                                         GPtrArray        *values);
+
+G_DEFINE_DYNAMIC_TYPE (TrackerWritebackMP3, tracker_writeback_mp3, TRACKER_TYPE_WRITEBACK);
+
+static void
+tracker_writeback_mp3_class_init (TrackerWritebackMP3Class *klass)
+{
+        TrackerWritebackClass *writeback_class = TRACKER_WRITEBACK_CLASS (klass);
+
+        writeback_class->update_metadata = tracker_writeback_mp3_update_metadata;
+}
+
+static void
+tracker_writeback_mp3_class_finalize (TrackerWritebackMP3Class *klass)
+{
+}
+
+static void
+tracker_writeback_mp3_init (TrackerWritebackMP3 *mp3)
+{
+}
+
+static gboolean
+tracker_writeback_mp3_update_metadata (TrackerWriteback *writeback,
+                                         GPtrArray        *values)
+{
+	guint n;
+	const gchar *uri = NULL;
+	GFile *file = NULL;
+	gchar *path = NULL;
+
+	for (n = 0; n < values->len; n++) {
+		const GStrv row = g_ptr_array_index (values, n);
+
+		if (uri == NULL) {
+			uri = row[0];
+			file = g_file_new_for_uri (uri);
+			path = g_file_get_path (file);
+		}
+
+		if (g_strcmp0 (row[1], TRACKER_NIE_PREFIX "title") == 0) {
+			ID3Tag *tag = ID3Tag_New ();
+			ID3Frame *frame;
+
+			ID3Tag_Link (tag, path);
+
+ 			frame = ID3Tag_FindFrameWithID (tag, ID3FID_TITLE);
+			if (frame) {
+				ID3Field *field;
+				field = ID3Frame_GetField (frame, ID3FN_TEXT);
+				ID3Field_SetASCII (field, row[2]);
+			} else {
+				ID3Field *field;
+				frame = ID3Frame_NewID (ID3FID_TITLE);
+				field = ID3Frame_GetField (frame, ID3FN_TEXT);
+				ID3Field_SetASCII (field, row[2]);
+				ID3Tag_AddFrame (tag, frame);
+			}
+
+			ID3Tag_Update (tag);
+			// ID3Frame_Delete (frame);
+			ID3Tag_Delete (tag);
+		}
+	}
+
+	if (path)
+		g_free (path);
+
+	if (file)
+		g_object_unref (file);
+
+	return TRUE;
+}
+
+TrackerWriteback *
+writeback_module_create (GTypeModule *module)
+{
+	tracker_writeback_mp3_register_type (module);
+
+	return g_object_new (TRACKER_TYPE_WRITEBACK_MP3, NULL);
+}
+
+const GStrv
+writeback_module_get_mimetypes (void)
+{
+	static const gchar *mimetypes[] = { "*", NULL };
+
+	return (GStrv) mimetypes;
+}
diff --git a/src/tracker-writeback/tracker-writeback.c b/src/tracker-writeback/tracker-writeback.c
index 09e64a2..0ee37ea 100644
--- a/src/tracker-writeback/tracker-writeback.c
+++ b/src/tracker-writeback/tracker-writeback.c
@@ -36,15 +36,13 @@ tracker_writeback_init (TrackerWriteback *writeback)
 
 gboolean
 tracker_writeback_update_metadata (TrackerWriteback *writeback,
-                                   GFile            *file,
                                    GPtrArray        *values)
 {
         g_return_val_if_fail (TRACKER_IS_WRITEBACK (writeback), FALSE);
-        g_return_val_if_fail (G_IS_FILE (file), FALSE);
         g_return_val_if_fail (values != NULL, FALSE);
 
         if (TRACKER_WRITEBACK_GET_CLASS (writeback)->update_metadata) {
-                return TRACKER_WRITEBACK_GET_CLASS (writeback)->update_metadata (writeback, file, values);
+                return TRACKER_WRITEBACK_GET_CLASS (writeback)->update_metadata (writeback, values);
         }
 
         return FALSE;
diff --git a/src/tracker-writeback/tracker-writeback.h b/src/tracker-writeback/tracker-writeback.h
index 337115c..ab3bd53 100644
--- a/src/tracker-writeback/tracker-writeback.h
+++ b/src/tracker-writeback/tracker-writeback.h
@@ -44,7 +44,6 @@ struct TrackerWritebackClass {
         GObjectClass parent_class;
 
         gboolean (* update_metadata) (TrackerWriteback *writeback,
-                                      GFile            *file,
                                       GPtrArray        *values);
 };
 
@@ -55,7 +54,6 @@ TrackerWriteback * writeback_module_create        (GTypeModule *module);
 const GStrv        writeback_module_get_mimetypes (void);
 
 gboolean tracker_writeback_update_metadata (TrackerWriteback *writeback,
-                                            GFile            *file,
                                             GPtrArray        *values);
 
 



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