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..7274b66 100644 --- a/src/libtracker-common/tracker-albumart.c +++ b/src/libtracker-common/tracker-albumart.c @@ -23,6 +23,8 @@ #include "config.h" +#define _GNU_SOURCE + #include #include #include @@ -41,6 +43,8 @@ #include #include +#include +#include #include "tracker-albumart.h" @@ -54,62 +58,29 @@ #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; +} TrackerAlbumArtPrivate; -static gboolean no_more_requesting = FALSE; - -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; - } - } +typedef struct { + gchar *dirname; + gchar *album; + gchar *artist; + gchar *count; +} QueuedAlbumArtScanRequest; - return NULL; -} +typedef struct { + gchar *album; + gchar *artist; + gchar *dirname; +} GetFileInfo; -#endif /* HAVE_STRCASESTR */ +static GStaticPrivate private_key = G_STATIC_PRIVATE_INIT; /* 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 +146,167 @@ 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 *basename_; + GFile *file, *parent, *dirf; + + /* 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); + dirf = g_file_get_child (parent, ".mediaartlocal"); + g_object_unref (parent); + + /* Ensure directory is made */ + make_directory_with_parents (dirf, NULL, &error); + + if (!error) { + GFile *local_file; + + local_file = g_file_get_child (dirf, basename_); + + 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_object_unref (dirf); + 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_; + GFile *file, *parent, *local_file, *dirf; + + file = g_file_new_for_path (album_art_file); + basename_ = g_file_get_basename (file); + + parent = g_file_new_for_path (dirname); + dirf = g_file_get_child (parent, ".mediaartlocal"); + g_object_unref (parent); + + local_file = g_file_get_child (dirf, basename_); + + 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_object_unref (dirf); + 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 +374,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 +453,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 +476,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 +484,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 +505,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 +559,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 +573,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 +622,6 @@ tracker_albumart_get_path (const gchar *a, *path = NULL; } - if (local_uri) { - *local_uri = NULL; - } - if (!a && !b) { return; } @@ -628,58 +663,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 +700,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..3f6f2a5 100644 --- a/src/tracker-extract/tracker-extract.h +++ b/src/tracker-extract/tracker-extract.h @@ -47,6 +47,15 @@ struct TrackerExtract { struct TrackerExtractClass { GObjectClass parent; + + void (*to_scan_for_albumart) (TrackerExtract *extract, + const gchar *dirname, + const gchar *artist, + const gchar *album, + const gchar *count); + void (*to_copy_to_local_if) (TrackerExtract *extract, + const gchar *filename, + const gchar *dirname); }; GType tracker_extract_get_type (void); @@ -60,11 +69,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() */ }