diff --git a/configure.ac b/configure.ac
index 3620111..8403846 100644
--- a/configure.ac
+++ b/configure.ac
@@ -108,6 +108,7 @@ AC_CHECK_DECLS(posix_fadvise, [], [], [
# Checks for functions
AC_CHECK_FUNCS([posix_fadvise])
AC_CHECK_FUNCS([getline])
+AC_CHECK_FUNCS([strcasestr])
# Check for defines we expect
AC_TRY_COMPILE(,
diff --git a/data/dbus/tracker-extract.xml b/data/dbus/tracker-extract.xml
index 4d9de37..91b3e7b 100644
--- a/data/dbus/tracker-extract.xml
+++ b/data/dbus/tracker-extract.xml
@@ -21,5 +21,15 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libtracker-common/tracker-albumart.c b/src/libtracker-common/tracker-albumart.c
index fb0fe7e..5ed9da5 100644
--- a/src/libtracker-common/tracker-albumart.c
+++ b/src/libtracker-common/tracker-albumart.c
@@ -41,6 +41,8 @@
#include
#include
+#include
+#include
#include "tracker-albumart.h"
@@ -54,62 +56,33 @@
#define THUMBNAILER_PATH "/org/freedesktop/thumbnailer/Generic"
#define THUMBNAILER_INTERFACE "org.freedesktop.thumbnailer.Generic"
+#define ALBUMART_HEURISTIC_SCAN_TIMEOUT 30
+
typedef struct {
+ gboolean no_more_requesting;
+ GHashTable *queue;
+ guint queue_timeout;
TrackerHal *hal;
- gchar *art_path;
- gchar *local_uri;
-} GetFileInfo;
-
-static gboolean no_more_requesting = FALSE;
+} TrackerAlbumArtPrivate;
-static gchar *
-my_compute_checksum_for_data (GChecksumType checksum_type,
- const guchar *data,
- gsize length)
-{
- GChecksum *checksum;
- gchar *retval;
-
- checksum = g_checksum_new (checksum_type);
- if (!checksum)
- return NULL;
-
- g_checksum_update (checksum, data, length);
- retval = g_strdup (g_checksum_get_string (checksum));
- g_checksum_free (checksum);
-
- return retval;
-}
-
-#ifndef HAVE_STRCASESTR
-
-static gchar *
-strcasestr (const gchar *haystack,
- const gchar *needle)
-{
- gchar *p;
- gchar *startn = NULL;
- gchar *np = NULL;
+typedef struct {
+ gchar *dirname;
+ gchar *album;
+ gchar *artist;
+ gchar *count;
+} QueuedAlbumArtScanRequest;
- for (p = (gchar *) haystack; *p; p++) {
- if (np) {
- if (toupper (*p) == toupper (*np)) {
- if (!*++np) {
- return startn;
- }
- } else {
- np = 0;
- }
- } else if (toupper (*p) == toupper (*needle)) {
- np = (gchar *) needle + 1;
- startn = p;
- }
- }
+typedef struct {
+ gchar *album;
+ gchar *artist;
+ gchar *dirname;
+} GetFileInfo;
- return NULL;
-}
+static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT;
-#endif /* HAVE_STRCASESTR */
+#ifdef HAVE_STRCASESTR
+gchar * strcasestr (const gchar *haystack, const gchar *needle);
+#endif
/* NOTE: This function was stolen from GLib 2.18.x. Since upstream and
* the Maemo branch don't have this in circulation yet, we have copied
@@ -175,6 +148,180 @@ make_directory_with_parents (GFile *file,
return g_file_make_directory (file, cancellable, error);
}
+void
+tracker_albumart_copy_to_local_if (const gchar *album_art_file,
+ const gchar *dirname)
+{
+ GList *removable_roots, *l;
+ gboolean on_removable_device = FALSE;
+ TrackerAlbumArtPrivate *private;
+ guint flen = dirname ? strlen (dirname) : 0;
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ /* Determining if we are on a removable device */
+#ifdef HAVE_HAL
+ removable_roots = tracker_hal_get_removable_device_roots (private->hal);
+#else
+ removable_roots = g_list_append (removable_roots, "/media");
+ removable_roots = g_list_append (removable_roots, "/mnt");
+#endif
+
+ for (l = removable_roots; l; l = l->next) {
+ guint len;
+
+ len = strlen (l->data);
+
+ if (flen >= len && strncmp (dirname, l->data, len) == 0) {
+ on_removable_device = TRUE;
+ break;
+ }
+ }
+
+#ifdef HAVE_HAL
+ g_list_foreach (removable_roots, (GFunc) g_free, NULL);
+#endif
+
+ g_list_free (removable_roots);
+
+ /* Going to copy to .mediaartlocal if file is on a removable device */
+
+ if (on_removable_device) {
+ GError *error = NULL;
+ gchar *local_dir, *basename, *local_uri;
+ GFile *file, *parent;
+
+ /* album_art_file points to the newly made album-art */
+ file = g_file_new_for_path (album_art_file);
+ basename = g_file_get_basename (file);
+
+ /* dirname points to the dir where the album is located */
+ parent = g_file_new_for_path (dirname);
+ local_dir = g_file_get_uri (parent);
+ g_object_unref (parent);
+
+ local_uri = g_strdup_printf ("%s/.mediaartlocal", local_dir);
+ parent = g_file_new_for_uri (local_uri);
+
+ g_free (local_uri);
+
+ /* Ensure directory is made */
+ make_directory_with_parents (parent, NULL, &error);
+
+ if (!error) {
+ GFile *local_file;
+
+ /* This is a URI, don't use g_build_filename here */
+ local_uri = g_strdup_printf ("%s/.mediaartlocal/%s",
+ local_dir, basename);
+ local_file = g_file_new_for_uri (local_uri);
+ g_free (local_uri);
+
+ g_file_copy_async (file, local_file, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ g_object_unref (local_file);
+ } else {
+ /* Removable media probably not writable, ignore */
+ g_error_free (error);
+ }
+
+ g_free (local_dir);
+ g_free (basename);
+ g_object_unref (file);
+ }
+}
+
+
+static gboolean
+tracker_albumart_copy_from_local_if (const gchar *album_art_file,
+ const gchar *dirname)
+{
+ gboolean retval = FALSE;
+ gchar *basename, *local_dir, *local_uri;
+ GFile *file, *parent, *local_file;
+
+ file = g_file_new_for_path (album_art_file);
+ basename = g_file_get_basename (file);
+
+ parent = g_file_new_for_path (dirname);
+ local_dir = g_file_get_uri (parent);
+ g_object_unref (parent);
+
+ /* This is a URI, don't use g_build_filename here */
+ local_uri = g_strdup_printf ("%s/.mediaartlocal/%s", local_dir, basename);
+ local_file = g_file_new_for_uri (local_uri);
+ g_free (local_uri);
+
+ if (g_file_query_exists (local_file, NULL)) {
+ g_file_copy_async (local_file, file, 0, 0,
+ NULL, NULL, NULL, NULL, NULL);
+
+ tracker_thumbnailer_queue_file (album_art_file, "image/jpeg");
+
+ retval = TRUE;
+ }
+
+ g_object_unref (local_file);
+
+ g_free (local_dir);
+ g_free (basename);
+ g_object_unref (file);
+
+ return retval;
+}
+
+static gchar *
+my_compute_checksum_for_data (GChecksumType checksum_type,
+ const guchar *data,
+ gsize length)
+{
+ GChecksum *checksum;
+ gchar *retval;
+
+ checksum = g_checksum_new (checksum_type);
+ if (!checksum)
+ return NULL;
+
+ g_checksum_update (checksum, data, length);
+ retval = g_strdup (g_checksum_get_string (checksum));
+ g_checksum_free (checksum);
+
+ return retval;
+}
+
+#ifndef HAVE_STRCASESTR
+
+static gchar *
+strcasestr (const gchar *haystack,
+ const gchar *needle)
+{
+ gchar *p;
+ gchar *startn = NULL;
+ gchar *np = NULL;
+
+ for (p = (gchar *) haystack; *p; p++) {
+ if (np) {
+ if (toupper (*p) == toupper (*np)) {
+ if (!*++np) {
+ return startn;
+ }
+ } else {
+ np = 0;
+ }
+ } else if (toupper (*p) == toupper (*needle)) {
+ np = (gchar *) needle + 1;
+ startn = p;
+ }
+ }
+
+ return NULL;
+}
+
+#endif /* HAVE_STRCASESTR */
+
+
static gchar*
strip_characters (const gchar *original)
{
@@ -242,162 +389,73 @@ strip_characters (const gchar *original)
return retval;
}
-void
-tracker_albumart_copy_to_local (TrackerHal *hal,
- const gchar *filename,
- const gchar *local_uri)
-{
- GList *removable_roots, *l;
- gboolean on_removable_device = FALSE;
- guint flen;
-
- g_return_if_fail (filename != NULL);
- g_return_if_fail (local_uri != NULL);
-
- flen = strlen (filename);
-
- /* Determining if we are on a removable device */
-#ifdef HAVE_HAL
- g_return_if_fail (hal != NULL);
- removable_roots = tracker_hal_get_removable_device_roots (hal);
-#else
- removable_roots = g_list_append (removable_roots, "/media");
- removable_roots = g_list_append (removable_roots, "/mnt");
-#endif
-
- for (l = removable_roots; l; l = l->next) {
- guint len;
-
- len = strlen (l->data);
-
- if (flen >= len && strncmp (filename, l->data, len)) {
- on_removable_device = TRUE;
- break;
- }
- }
-
-#ifdef HAVE_HAL
- g_list_foreach (removable_roots, (GFunc) g_free, NULL);
-#endif
-
- g_list_free (removable_roots);
-
- if (on_removable_device) {
- GFile *local_file, *from;
-
- from = g_file_new_for_path (filename);
- local_file = g_file_new_for_uri (local_uri);
-
- /* We don't try to overwrite, but we also ignore all errors.
- * Such an error could be that the removable device is
- * read-only. Well that's fine then ... ignore */
-
- if (!g_file_query_exists (local_file, NULL)) {
- GFile *dirf;
-
- dirf = g_file_get_parent (local_file);
- make_directory_with_parents (dirf, NULL, NULL);
- g_object_unref (dirf);
-
- g_file_copy_async (from, local_file, 0, 0,
- NULL, NULL, NULL, NULL, NULL);
- }
-
- g_object_unref (local_file);
- g_object_unref (from);
- }
-}
-
-gboolean
+static gboolean
tracker_albumart_heuristic (const gchar *artist_,
const gchar *album_,
const gchar *tracks_str,
- const gchar *filename,
- const gchar *local_uri,
- gboolean *copied)
+ const gchar *dirname)
{
- GFile *file;
GDir *dir;
struct stat st;
gchar *target = NULL;
- gchar *basename;
const gchar *name;
gboolean retval;
gint tracks;
gint count;
gchar *artist = NULL;
gchar *album = NULL;
+ GFile *file;
- /* Copy from local album art (.mediaartlocal) to spec */
- if (local_uri) {
- GFile *local_file;
-
- local_file = g_file_new_for_uri (local_uri);
-
- if (g_file_query_exists (local_file, NULL)) {
- tracker_albumart_get_path (artist, album,
- "album", NULL,
- &target, NULL);
-
- file = g_file_new_for_path (target);
-
- g_file_copy_async (local_file, file, 0, 0,
- NULL, NULL, NULL, NULL, NULL);
-
- g_object_unref (file);
- g_object_unref (local_file);
-
- *copied = TRUE;
- g_free (target);
-
- return TRUE;
- }
-
- g_object_unref (local_file);
- }
+ dir = g_dir_open (dirname, 0, NULL);
- *copied = FALSE;
+ if (!dir) {
+ return FALSE;
+ }
- file = g_file_new_for_path (filename);
- basename = g_file_get_basename (file);
- g_object_unref (file);
+ if (artist_) {
+ artist = strip_characters (artist_);
+ }
- if (!basename) {
- return FALSE;
+ if (album_) {
+ album = strip_characters (album_);
}
- dir = g_dir_open (basename, 0, NULL);
+ tracker_albumart_get_path (artist, album, "album", &target);
- if (!dir) {
- g_free (basename);
+ if (!target) {
+ g_dir_close (dir);
+ g_free (artist);
+ g_free (album);
return FALSE;
}
+ if (tracker_albumart_copy_from_local_if (target, dirname)) {
+ g_dir_close (dir);
+ g_free (target);
+ g_free (artist);
+ g_free (album);
+ return TRUE;
+ }
+
retval = FALSE;
file = NULL;
- g_stat (basename, &st);
- count = st.st_nlink;
-
+ g_stat (dirname, &st);
+ count = st.st_nlink + st.st_ino;
+
if (tracks_str) {
tracks = atoi (tracks_str);
+ if (tracks == 0)
+ tracks = -1;
} else {
tracks = -1;
}
- if (artist_) {
- artist = strip_characters (artist_);
- }
-
- if (album_) {
- album = strip_characters (album_);
- }
-
/* If amount of files and amount of tracks in the album somewhat match */
if ((tracks != -1 && tracks < count + 3 && tracks > count - 3) ||
- (tracks == -1 && count > 8 && count < 50)) {
+ (tracks == -1 && count >= 8 && count < 50)) {
gchar *found = NULL;
/* Try to find cover art in the directory */
@@ -410,22 +468,16 @@ tracker_albumart_heuristic (const gchar *artist_,
if (g_str_has_suffix (name, "jpeg") ||
g_str_has_suffix (name, "jpg")) {
GFile *file_found;
-
- if (!target) {
- tracker_albumart_get_path (artist, album,
- "album", NULL,
- &target, NULL);
- }
-
+
if (!file) {
file = g_file_new_for_path (target);
}
- found = g_build_filename (basename, name, NULL);
+ found = g_build_filename (dirname, name, NULL);
file_found = g_file_new_for_path (found);
-
+
g_file_copy (file_found, file, 0, NULL, NULL, NULL, &error);
-
+
if (!error) {
retval = TRUE;
} else {
@@ -439,7 +491,7 @@ tracker_albumart_heuristic (const gchar *artist_,
#ifdef HAVE_GDKPIXBUF
GdkPixbuf *pixbuf;
- found = g_build_filename (basename, name, NULL);
+ found = g_build_filename (dirname, name, NULL);
pixbuf = gdk_pixbuf_new_from_file (found, &error);
if (error) {
@@ -447,16 +499,12 @@ tracker_albumart_heuristic (const gchar *artist_,
retval = FALSE;
} else {
if (!target) {
- tracker_albumart_get_path (artist,
- album,
- "album",
- NULL,
- &target,
- NULL);
+ tracker_albumart_get_path (artist, album,
+ "album", &target);
}
gdk_pixbuf_save (pixbuf, target, "jpeg", &error, NULL);
-
+
if (!error) {
retval = TRUE;
} else {
@@ -472,21 +520,22 @@ tracker_albumart_heuristic (const gchar *artist_,
}
if (retval) {
+ tracker_thumbnailer_queue_file (target, "image/jpeg");
+ tracker_albumart_copy_to_local_if (target, dirname);
break;
}
}
}
}
-
+
g_dir_close (dir);
-
+
if (file) {
g_object_unref (file);
}
g_free (target);
- g_free (basename);
g_free (artist);
g_free (album);
@@ -525,6 +574,11 @@ tracker_albumart_queue_cb (DBusGProxy *proxy,
GError *error = NULL;
guint handle;
GetFileInfo *info;
+ gchar *art_path;
+ TrackerAlbumArtPrivate *private;
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
info = user_data;
@@ -534,43 +588,43 @@ tracker_albumart_queue_cb (DBusGProxy *proxy,
if (error) {
if (error->code == DBUS_GERROR_SERVICE_UNKNOWN)
- no_more_requesting = TRUE;
+ private->no_more_requesting = TRUE;
else
g_warning ("%s", error->message);
g_clear_error (&error);
+
+ return;
}
- if (info->art_path &&
- g_file_test (info->art_path, G_FILE_TEST_EXISTS)) {
+ tracker_albumart_get_path (info->artist, info->album,
+ "album", &art_path);
+
+ if (art_path && g_file_test (art_path, G_FILE_TEST_EXISTS)) {
gchar *uri;
-
- uri = g_filename_to_uri (info->art_path, NULL, NULL);
+
+ uri = g_filename_to_uri (art_path, NULL, NULL);
tracker_thumbnailer_queue_file (uri, "image/jpeg");
g_free (uri);
- tracker_albumart_copy_to_local (info->hal,
- info->art_path,
- info->local_uri);
+ tracker_albumart_copy_to_local_if (art_path, info->dirname);
}
- g_free (info->art_path);
- g_free (info->local_uri);
+ g_free (art_path);
- if (info->hal) {
- g_object_unref (info->hal);
- }
+ g_free (info->artist);
+ g_free (info->album);
+ g_free (info->dirname);
g_slice_free (GetFileInfo, info);
}
void
-tracker_albumart_get_path (const gchar *a,
- const gchar *b,
+tracker_albumart_get_path (const gchar *album,
+ const gchar *artist,
const gchar *prefix,
- const gchar *uri,
- gchar **path,
- gchar **local_uri)
+ gchar **path)
{
+ const gchar *a = album, *b = artist;
gchar *art_filename;
gchar *dir;
gchar *down1, *down2;
@@ -583,10 +637,6 @@ tracker_albumart_get_path (const gchar *a,
*path = NULL;
}
- if (local_uri) {
- *local_uri = NULL;
- }
-
if (!a && !b) {
return;
}
@@ -628,58 +678,32 @@ tracker_albumart_get_path (const gchar *a,
*path = g_build_filename (dir, art_filename, NULL);
- if (local_uri) {
- gchar *local_dir;
- GFile *file, *parent;
-
- if (strchr (uri, ':')) {
- file = g_file_new_for_uri (uri);
- } else {
- file = g_file_new_for_path (uri);
- }
-
- parent = g_file_get_parent (file);
- local_dir = g_file_get_uri (parent);
-
- /* This is a URI, don't use g_build_filename here */
- *local_uri = g_strdup_printf ("%s/.mediaartlocal/%s", local_dir, art_filename);
-
- g_free (local_dir);
- g_object_unref (file);
- g_object_unref (parent);
- }
-
g_free (dir);
g_free (art_filename);
g_free (str1);
g_free (str2);
}
-void
-tracker_albumart_request_download (TrackerHal *hal,
- const gchar *album,
- const gchar *artist,
- const gchar *local_uri,
- const gchar *art_path)
+static void
+tracker_albumart_request_download (const gchar *album,
+ const gchar *artist,
+ const gchar *dirname)
{
GetFileInfo *info;
+ TrackerAlbumArtPrivate *private;
- g_return_if_fail (hal != NULL);
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
- if (no_more_requesting) {
+ if (private->no_more_requesting) {
return;
}
info = g_slice_new (GetFileInfo);
-#ifdef HAVE_HAL
- info->hal = g_object_ref (hal);
-#else
- info->hal = NULL;
-#endif
-
- info->local_uri = g_strdup (local_uri);
- info->art_path = g_strdup (art_path);
+ info->album = g_strdup (album);
+ info->artist = g_strdup (artist);
+ info->dirname = g_strdup (dirname);
dbus_g_proxy_begin_call (get_albumart_requester (),
"Queue",
@@ -691,3 +715,154 @@ tracker_albumart_request_download (TrackerHal *hal,
G_TYPE_UINT, 0,
G_TYPE_INVALID);
}
+
+
+static void
+queued_album_art_scan_request_free (QueuedAlbumArtScanRequest *info)
+{
+ g_free (info->dirname);
+ g_free (info->album);
+ g_free (info->artist);
+ g_free (info->count);
+ g_slice_free (QueuedAlbumArtScanRequest, info);
+}
+
+static gboolean
+on_queue_timeout (gpointer user_data)
+{
+ if (!g_source_is_destroyed (g_main_current_source ())) {
+ TrackerAlbumArtPrivate *private;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ private = g_static_private_get (&private_key);
+ g_return_val_if_fail (private != NULL, FALSE);
+
+ g_hash_table_iter_init (&iter, private->queue);
+
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ QueuedAlbumArtScanRequest *info = value;
+
+ if (!tracker_albumart_heuristic (info->artist,
+ info->album,
+ info->count,
+ info->dirname)) {
+
+ /* If the heuristic failed, we request the download
+ * of the media-art to the media-art downloaders */
+
+ tracker_albumart_request_download (info->artist,
+ info->album,
+ info->dirname);
+ }
+
+ /* Once handled, we remove from the queue */
+ g_hash_table_iter_remove (&iter);
+ }
+
+ }
+
+ return FALSE;
+}
+
+void
+tracker_albumart_heuristic_queue (const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count)
+{
+ TrackerAlbumArtPrivate *private;
+ gchar *key;
+ QueuedAlbumArtScanRequest *info;
+
+ private = g_static_private_get (&private_key);
+ g_return_if_fail (private != NULL);
+
+ key = g_strdup_printf ("%s%s%s", dirname, album, artist);
+ info = g_slice_new (QueuedAlbumArtScanRequest);
+
+ /* This method is typically called-for by the extractors. It's a request
+ * for us (we're the delegate here) to do a heuristic scan for album-art.
+ *
+ * This is a non-urgent request and these can happen rapidly with the
+ * same directory/album/artist combination many times in a row.
+ *
+ * We are allowed to merge such requests together and perform it delayed */
+
+ info->dirname = g_strdup (dirname);
+ info->album = g_strdup (album);
+ info->artist = g_strdup (artist);
+ info->count = g_strdup (count);
+
+ g_hash_table_replace (private->queue, key, info);
+
+ /* If there's a queue-run already enqueued, then we'll remove that one
+ * and we'll start a new one. */
+
+ if (private->queue_timeout != 0) {
+ g_source_remove (private->queue_timeout);
+ }
+
+ /* We hope to collect all requests for a album-art heuristic scan for
+ * a given combination of album, artist and directory within 30 seconds.
+ *
+ * If a request comes after 30 seconds then that's too bad, we'll just
+ * do a new heuristic scan in that case.*/
+
+ private->queue_timeout = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
+ ALBUMART_HEURISTIC_SCAN_TIMEOUT,
+ on_queue_timeout, NULL,
+ NULL);
+}
+
+
+static void
+private_free (gpointer data)
+{
+ TrackerAlbumArtPrivate *private;
+
+ private = data;
+
+ if (private->queue_timeout != 0) {
+ g_source_remove (private->queue_timeout);
+ }
+
+ on_queue_timeout (private->queue);
+
+ g_hash_table_destroy (private->queue);
+ g_object_unref (private->hal);
+
+ g_free (private);
+}
+
+
+void
+tracker_albumart_init (void)
+{
+ TrackerAlbumArtPrivate *private;
+
+ private = g_new0 (TrackerAlbumArtPrivate, 1);
+
+ private->queue_timeout = 0;
+ private->no_more_requesting = FALSE;
+
+#ifdef HAVE_HAL
+ private->hal = tracker_hal_new ();
+#else
+ private->hal = NULL;
+#endif
+
+ private->queue = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) queued_album_art_scan_request_free);
+
+ g_static_private_set (&private_key,
+ private,
+ private_free);
+}
+
+void
+tracker_albumart_shutdown (void)
+{
+ g_static_private_set (&private_key, NULL, NULL);
+}
diff --git a/src/libtracker-common/tracker-albumart.h b/src/libtracker-common/tracker-albumart.h
index 9e7e15a..152dd35 100644
--- a/src/libtracker-common/tracker-albumart.h
+++ b/src/libtracker-common/tracker-albumart.h
@@ -32,26 +32,22 @@ G_BEGIN_DECLS
#include "tracker-hal.h"
-gboolean tracker_albumart_heuristic (const gchar *artist_,
- const gchar *album_,
- const gchar *tracks_str,
- const gchar *filename,
- const gchar *local_uri,
- gboolean *copied);
-void tracker_albumart_copy_to_local (TrackerHal *hal,
- const gchar *filename,
- const gchar *local_uri);
-void tracker_albumart_get_path (const gchar *a,
- const gchar *b,
+void tracker_albumart_heuristic_queue (const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count);
+
+void tracker_albumart_get_path (const gchar *album,
+ const gchar *artist,
const gchar *prefix,
- const gchar *uri,
- gchar **path,
- gchar **local);
-void tracker_albumart_request_download (TrackerHal *hal,
- const gchar *album,
- const gchar *artist,
- const gchar *local_uri,
- const gchar *art_path);
+ gchar **path);
+
+void tracker_albumart_copy_to_local_if (const gchar *album_art_file,
+ const gchar *dirname);
+
+void tracker_albumart_init (void);
+void tracker_albumart_shutdown (void);
+
G_END_DECLS
diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am
index 0a660cb..7ad0a70 100644
--- a/src/tracker-extract/Makefile.am
+++ b/src/tracker-extract/Makefile.am
@@ -211,6 +211,7 @@ libextract_playlist_la_LIBADD = $(GLIB2_LIBS) $(TOTEM_PL_PARSER_LIBS) $(GCOV_LIB
libexec_PROGRAMS = tracker-extract
tracker_extract_SOURCES = \
+ tracker-marshal-main.c \
tracker-dbus.c \
tracker-dbus.h \
tracker-extract.c \
@@ -231,7 +232,23 @@ dbus_sources = \
%-glue.h: $(top_srcdir)/data/dbus/%.xml
$(DBUSBINDINGTOOL) --mode=glib-server --output=$@ --prefix=$(subst -,_,$*) $^
+tracker-marshal.h: tracker-marshal.list
+ $(GLIB_GENMARSHAL) $< --prefix=tracker_marshal --header > $@
+
+tracker-marshal.c: tracker-marshal.list
+ $(GLIB_GENMARSHAL) $< --prefix=tracker_marshal --body > $@
+
+tracker-marshal-main.c: tracker-marshal.c tracker-marshal.h
+
+marshal_sources = \
+ tracker-marshal.h \
+ tracker-marshal.c
+
BUILT_SOURCES = \
- $(dbus_sources)
+ $(dbus_sources) \
+ $(marshal_sources)
CLEANFILES = $(BUILT_SOURCES)
+
+EXTRA_DIST = tracker-marshal.list
+
diff --git a/src/tracker-extract/tracker-extract-albumart.c b/src/tracker-extract/tracker-extract-albumart.c
index 206a836..9ddfea4 100644
--- a/src/tracker-extract/tracker-extract-albumart.c
+++ b/src/tracker-extract/tracker-extract-albumart.c
@@ -42,6 +42,7 @@
#include "tracker-main.h"
#include "tracker-extract-albumart.h"
+#include "tracker-extract.h"
#ifdef HAVE_GDKPIXBUF
@@ -64,7 +65,7 @@ set_albumart (const unsigned char *buffer,
return FALSE;
}
- tracker_albumart_get_path (artist, album, "album", NULL, &filename, NULL);
+ tracker_albumart_get_path (artist, album, "album", &filename);
loader = gdk_pixbuf_loader_new ();
@@ -99,6 +100,7 @@ set_albumart (const unsigned char *buffer,
}
tracker_thumbnailer_queue_file (filename, "image/jpeg");
+
g_free (filename);
return TRUE;
@@ -116,89 +118,37 @@ tracker_process_albumart (const unsigned char *buffer,
{
gchar *art_path;
gboolean retval = TRUE;
- gchar *local_uri = NULL;
- gchar *filename_uri;
- gboolean lcopied = FALSE;
-
- if (strchr (filename, ':')) {
- filename_uri = g_strdup (filename);
- } else {
- filename_uri = g_filename_to_uri (filename, NULL, NULL);
- }
- tracker_albumart_get_path (artist,
- album,
- "album",
- filename_uri,
- &art_path,
- &local_uri);
+ tracker_albumart_get_path (artist, album, "album", &art_path);
if (!art_path) {
- g_free (filename_uri);
- g_free (local_uri);
-
return FALSE;
}
if (!g_file_test (art_path, G_FILE_TEST_EXISTS)) {
+
#ifdef HAVE_GDKPIXBUF
/* If we have embedded album art */
if (buffer && len) {
- retval = set_albumart (buffer,
- len,
- artist,
- album,
- filename);
-
- lcopied = !retval;
-
+ gchar *dirname = g_path_get_dirname (filename);
+ retval = set_albumart (buffer, len, artist, album, filename);
+ tracker_extract_emit_copy_to_local_if (filename, dirname);
+ g_free (dirname);
} else {
#endif /* HAVE_GDK_PIXBUF */
- /* If not, we perform a heuristic on the dir */
- if (!tracker_albumart_heuristic (artist, album,
- trackercnt_str,
- filename,
- local_uri,
- &lcopied)) {
-
- /* If the heuristic failed, we request the download
- * of the media-art to the media-art downloaders */
- lcopied = TRUE;
- tracker_albumart_request_download (tracker_main_get_hal (),
- artist,
- album,
- local_uri,
- art_path);
+ if (album) {
+ gchar *dirname = g_path_get_dirname (filename);
+ tracker_extract_emit_scan_for_albumart (dirname, artist,
+ album, trackercnt_str);
+ g_free (dirname);
}
#ifdef HAVE_GDKPIXBUF
}
#endif /* HAVE_GDKPIXBUF */
- /* If the heuristic didn't copy from the .mediaartlocal, then
- * we'll perhaps copy it to .mediaartlocal (perhaps because this
- * only copies in case the media is located on a removable
- * device */
-
- if (g_file_test (art_path, G_FILE_TEST_EXISTS)) {
- gchar *as_uri;
-
- as_uri = g_filename_to_uri (art_path, NULL, NULL);
- tracker_thumbnailer_queue_file (as_uri, "image/jpeg");
- g_free (as_uri);
- }
-
- }
-
- if (local_uri && !g_file_test (local_uri, G_FILE_TEST_EXISTS)) {
- if (g_file_test (art_path, G_FILE_TEST_EXISTS))
- tracker_albumart_copy_to_local (tracker_main_get_hal (),
- art_path,
- local_uri);
}
g_free (art_path);
- g_free (filename_uri);
- g_free (local_uri);
return retval;
}
diff --git a/src/tracker-extract/tracker-extract.c b/src/tracker-extract/tracker-extract.c
index 648ed8b..25392f4 100644
--- a/src/tracker-extract/tracker-extract.c
+++ b/src/tracker-extract/tracker-extract.c
@@ -30,7 +30,11 @@
#include "tracker-main.h"
#include "tracker-dbus.h"
+#include "tracker-marshal.h"
+
+#define TRACKER_EXTRACT_C
#include "tracker-extract.h"
+#undef TRACKER_EXTRACT_C
#define MAX_EXTRACT_TIME 5
#define TRACKER_EXTRACT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EXTRACT, TrackerExtractPrivate))
@@ -39,10 +43,22 @@ typedef struct {
GArray *extractors;
} TrackerExtractPrivate;
+
+enum {
+ TO_SCAN_FOR_ALBUMART,
+ TO_COPY_TO_LOCAL_IF,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0, };
+
+
static void tracker_extract_finalize (GObject *object);
G_DEFINE_TYPE(TrackerExtract, tracker_extract, G_TYPE_OBJECT)
+TrackerExtract *dbus_object = NULL;
+
static void
tracker_extract_class_init (TrackerExtractClass *klass)
{
@@ -50,6 +66,32 @@ tracker_extract_class_init (TrackerExtractClass *klass)
object_class = G_OBJECT_CLASS (klass);
+ signals[TO_SCAN_FOR_ALBUMART] =
+ g_signal_new ("to-scan-for-albumart",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerExtractClass, to_scan_for_albumart),
+ NULL, NULL,
+ tracker_marshal_VOID__STRING_STRING_STRING_STRING,
+ G_TYPE_NONE,
+ 4,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
+ signals[TO_COPY_TO_LOCAL_IF] =
+ g_signal_new ("to-copy-to-local-if",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (TrackerExtractClass, to_copy_to_local_if),
+ NULL, NULL,
+ tracker_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
+
object_class->finalize = tracker_extract_finalize;
g_type_class_add_private (object_class, sizeof (TrackerExtractPrivate));
@@ -60,6 +102,29 @@ tracker_extract_init (TrackerExtract *object)
{
}
+void
+tracker_extract_emit_scan_for_albumart (const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count)
+{
+ if (dbus_object) {
+ g_signal_emit (dbus_object, signals[TO_SCAN_FOR_ALBUMART], 0,
+ dirname, artist, album, count);
+ }
+}
+
+
+void
+tracker_extract_emit_copy_to_local_if (const gchar *filename,
+ const gchar *dirname)
+{
+ if (dbus_object) {
+ g_signal_emit (dbus_object, signals[TO_COPY_TO_LOCAL_IF], 0,
+ filename, dirname);
+ }
+}
+
static void
tracker_extract_finalize (GObject *object)
{
@@ -166,6 +231,8 @@ tracker_extract_new (void)
priv->extractors = extractors;
+ dbus_object = object;
+
return object;
}
diff --git a/src/tracker-extract/tracker-extract.h b/src/tracker-extract/tracker-extract.h
index 8cc031f..5837ed2 100644
--- a/src/tracker-extract/tracker-extract.h
+++ b/src/tracker-extract/tracker-extract.h
@@ -47,6 +47,13 @@ struct TrackerExtract {
struct TrackerExtractClass {
GObjectClass parent;
+
+ void (*to_scan_for_albumart) (const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count);
+ void (*to_copy_to_local_if) (const gchar *filename,
+ const gchar *dirname);
};
GType tracker_extract_get_type (void);
@@ -60,11 +67,20 @@ void tracker_extract_get_metadata (TrackerExtract
DBusGMethodInvocation *context,
GError **error);
+void tracker_extract_emit_scan_for_albumart (const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count);
+void tracker_extract_emit_copy_to_local_if (const gchar *filename,
+ const gchar *dirname);
+
/* Not DBus API, convenience for command line */
void tracker_extract_get_metadata_by_cmdline (TrackerExtract *object,
const gchar *path,
const gchar *mime);
+
+
G_END_DECLS
#endif /* __TRACKERD_EXTRACT_H__ */
diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c
index 45cb892..9f44018 100644
--- a/src/tracker-extract/tracker-main.c
+++ b/src/tracker-extract/tracker-main.c
@@ -68,7 +68,6 @@
static GMainLoop *main_loop;
static guint quit_timeout_id = 0;
-static TrackerHal *hal;
static gboolean version;
static gint verbosity = -1;
@@ -118,19 +117,6 @@ tracker_main_quit_timeout_reset (void)
NULL);
}
-TrackerHal *
-tracker_main_get_hal (void)
-{
- if (!hal) {
-#ifdef HAVE_HAL
- hal = tracker_hal_new ();
-#else
- hal = NULL;
-#endif
- }
-
- return hal;
-}
static void
initialize_priority (void)
@@ -354,9 +340,6 @@ main (int argc, char *argv[])
tracker_thumbnailer_shutdown ();
tracker_log_shutdown ();
- if (hal) {
- g_object_unref (hal);
- }
g_free (log_filename);
g_object_unref (config);
diff --git a/src/tracker-extract/tracker-main.h b/src/tracker-extract/tracker-main.h
index ed23470..6d40d9d 100644
--- a/src/tracker-extract/tracker-main.h
+++ b/src/tracker-extract/tracker-main.h
@@ -24,8 +24,6 @@
#include
-#include
-
#include "tracker-escape.h"
G_BEGIN_DECLS
@@ -44,12 +42,6 @@ struct TrackerExtractData {
/* This is defined in each extract */
TrackerExtractData *tracker_get_extract_data (void);
-/* Some modules need to use the albumart API which requires HAL. To
- * avoid creating new HAL objects constantly, we initialize it once
- * and it is available using this API.
- */
-TrackerHal * tracker_main_get_hal (void);
-
/* This is used to not shutdown after the default of 30 seconds if we
* get more work to do.
*/
diff --git a/src/tracker-extract/tracker-marshal.list b/src/tracker-extract/tracker-marshal.list
index 0e62e59..a3d054a 100644
--- a/src/tracker-extract/tracker-marshal.list
+++ b/src/tracker-extract/tracker-marshal.list
@@ -1 +1,2 @@
VOID:STRING,STRING,STRING,STRING
+VOID:STRING,STRING
diff --git a/src/tracker-indexer/tracker-main.c b/src/tracker-indexer/tracker-main.c
index 8106af4..720c6cd 100644
--- a/src/tracker-indexer/tracker-main.c
+++ b/src/tracker-indexer/tracker-main.c
@@ -42,6 +42,7 @@
#include
#include
#include
+#include
#include
#include
@@ -391,6 +392,7 @@ main (gint argc, gchar *argv[])
/* Set up connections to the thumbnailer if supported */
tracker_thumbnailer_init (config);
+ tracker_albumart_init ();
if (process_all) {
/* Tell the indexer to process all configured modules */
@@ -431,6 +433,7 @@ main (gint argc, gchar *argv[])
tracker_push_shutdown ();
+ tracker_albumart_shutdown ();
tracker_thumbnailer_shutdown ();
tracker_dbus_shutdown ();
tracker_db_index_manager_shutdown ();
diff --git a/src/tracker-indexer/tracker-marshal.list b/src/tracker-indexer/tracker-marshal.list
index f17b920..2cc716c 100644
--- a/src/tracker-indexer/tracker-marshal.list
+++ b/src/tracker-indexer/tracker-marshal.list
@@ -1,3 +1,5 @@
VOID:DOUBLE,UINT,UINT,BOOL
VOID:DOUBLE,STRING,UINT,UINT,UINT
VOID:STRING,BOOL
+VOID:STRING,STRING,STRING,STRING
+VOID:STRING,STRING
diff --git a/src/tracker-indexer/tracker-module-metadata-utils.c b/src/tracker-indexer/tracker-module-metadata-utils.c
index b830efd..00c1fcd 100644
--- a/src/tracker-indexer/tracker-module-metadata-utils.c
+++ b/src/tracker-indexer/tracker-module-metadata-utils.c
@@ -37,10 +37,12 @@
#include
#include
#include
+#include
#include "tracker-module-metadata-utils.h"
#include "tracker-extract-client.h"
#include "tracker-dbus.h"
+#include "tracker-marshal.h"
#define METADATA_FILE_NAME_DELIMITED "File:NameDelimited"
#define METADATA_FILE_EXT "File:Ext"
@@ -73,6 +75,27 @@ typedef struct {
GPid pid;
} ExtractorContext;
+
+static void
+extractor_asks_to_scan_for_albumart (DBusGProxy *proxy,
+ const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count,
+ gpointer user_data)
+{
+ tracker_albumart_heuristic_queue (dirname, artist, album, count);
+}
+
+static void
+extractor_asks_to_copy_to_local_if (DBusGProxy *proxy,
+ const gchar *filename,
+ const gchar *dirname,
+ gpointer user_data)
+{
+ tracker_albumart_copy_to_local_if (filename, dirname);
+}
+
static DBusGProxy *
get_dbus_extract_proxy (void)
{
@@ -104,6 +127,33 @@ get_dbus_extract_proxy (void)
g_critical ("Could not create a DBusGProxy to the extract service");
}
+ dbus_g_object_register_marshaller (tracker_marshal_VOID__STRING_STRING_STRING_STRING,
+ G_TYPE_NONE,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ dbus_g_object_register_marshaller (tracker_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (proxy,
+ "ToCopyToLocalIf",
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ dbus_g_proxy_connect_signal (proxy, "ToScanForAlbumart",
+ G_CALLBACK (extractor_asks_to_scan_for_albumart),
+ NULL, NULL);
+
+ dbus_g_proxy_connect_signal (proxy, "ToCopyToLocalIf",
+ G_CALLBACK (extractor_asks_to_copy_to_local_if),
+ NULL, NULL);
+
return proxy;
}
diff --git a/tests/tracker-extract/tracker-extract-test-utils.c b/tests/tracker-extract/tracker-extract-test-utils.c
index ba3cdd5..ef76ed7 100644
--- a/tests/tracker-extract/tracker-extract-test-utils.c
+++ b/tests/tracker-extract/tracker-extract-test-utils.c
@@ -327,11 +327,19 @@ tracker_test_extract_file_access (const TrackerExtractData *data,
}
}
-/* This is added because tracker-main.c includes this file and so
- * should we otherwise it is missing when we try to build the tests.
- */
-TrackerHal *
-tracker_main_get_hal (void)
+void
+tracker_extract_emit_scan_for_albumart (const gchar *dirname,
+ const gchar *artist,
+ const gchar *album,
+ const gchar *count)
{
- return NULL;
+ /* To avoid linking problems in the test tools during dlopen() */
+}
+
+
+void
+tracker_extract_emit_copy_to_local_if (const gchar *filename,
+ const gchar *dirname)
+{
+ /* To avoid linking problems in the test tools during dlopen() */
}