summaryrefslogtreecommitdiff
path: root/libmediaart
diff options
context:
space:
mode:
authorMartyn Russell <martyn@lanedo.com>2014-09-10 11:26:11 +0100
committerMartyn Russell <martyn@lanedo.com>2014-10-17 11:23:44 +0100
commitcdc1168b4fadeb2f8bb37c34c2b533eb2837934c (patch)
tree4f0922f9b0ff3c812e5807264c936a934e166873 /libmediaart
parent969517fa94c76e300b4cbaeb8d03e23204907917 (diff)
downloadlibmediaart-cdc1168b4fadeb2f8bb37c34c2b533eb2837934c.tar.gz
cache: Added media_art_remove_async() and _finish()
Part of this API changes makes the media_art_get_{path|file}() APIs not do i/o operations like creating the cache directory. This is now done in media_art_process_new(). https://bugzilla.gnome.org/show_bug.cgi?id=724879
Diffstat (limited to 'libmediaart')
-rw-r--r--libmediaart/cache.c167
-rw-r--r--libmediaart/cache.h15
-rw-r--r--libmediaart/extract.c32
-rw-r--r--libmediaart/extract.h7
4 files changed, 199 insertions, 22 deletions
diff --git a/libmediaart/cache.c b/libmediaart/cache.c
index 3492683..a145931 100644
--- a/libmediaart/cache.c
+++ b/libmediaart/cache.c
@@ -22,6 +22,7 @@
#include <string.h>
#include <glib.h>
+#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
@@ -271,6 +272,9 @@ media_art_checksum_for_data (GChecksumType checksum_type,
* When done, both #GFile<!-- -->s must be freed with g_object_unref() if
* non-%NULL.
*
+ * This operation should not use i/o, but it depends on the backend
+ * GFile implementation.
+ *
* Returns: %TRUE if @cache_file or @local_file were returned, otherwise %FALSE.
*
* Since: 0.2.0
@@ -332,10 +336,6 @@ media_art_get_file (const gchar *artist,
"media-art",
NULL);
- if (!g_file_test (dir, G_FILE_TEST_EXISTS)) {
- g_mkdir_with_parents (dir, 0770);
- }
-
if (artist) {
a = artist_checksum;
b = title ? title_checksum : space_checksum;
@@ -470,18 +470,22 @@ media_art_remove_foreach (gpointer data,
* media_art_remove:
* @artist: artist the media art belongs to
* @album: (allow-none): album the media art belongs or %NULL
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to ignore.
+ * @error: location to store the error occurring, or %NULL to ignore
*
* Removes media art for given album/artist provided.
*
- * Returns: #TRUE on success, otherwise #FALSE.
+ * Returns: #TRUE on success, otherwise #FALSE where @error will be set.
*
* Since: 0.2.0
*/
gboolean
-media_art_remove (const gchar *artist,
- const gchar *album)
+media_art_remove (const gchar *artist,
+ const gchar *album,
+ GCancellable *cancellable,
+ GError **error)
{
- GError *error = NULL;
+ GError *local_error = NULL;
GHashTable *table = NULL;
const gchar *name;
GDir *dir;
@@ -494,13 +498,14 @@ media_art_remove (const gchar *artist,
dirname = g_build_filename (g_get_user_cache_dir (), "media-art", NULL);
- dir = g_dir_open (dirname, 0, &error);
- if (!dir || error) {
+ dir = g_dir_open (dirname, 0, &local_error);
+ if (!dir || local_error) {
/* Nothing to do if there is no directory in the first place. */
g_debug ("Removing media-art for artist:'%s', album:'%s': directory could not be opened, %s",
- artist, album, error ? error->message : "no error given");
+ artist, album, local_error ? local_error->message : "no error given");
+
+ g_clear_error (&local_error);
- g_clear_error (&error);
if (dir) {
g_dir_close (dir);
}
@@ -553,6 +558,13 @@ media_art_remove (const gchar *artist,
g_list_foreach (to_remove, media_art_remove_foreach, &success);
g_list_free (to_remove);
+ if (!success) {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ _("Could not remove one or more files from media art cache"));
+ }
+
g_hash_table_unref (table);
g_dir_close (dir);
@@ -560,3 +572,134 @@ media_art_remove (const gchar *artist,
return success;
}
+
+typedef struct {
+ gchar *artist;
+ gchar *album;
+} RemoveData;
+
+static RemoveData *
+remove_data_new (const gchar *artist,
+ const gchar *album)
+{
+ RemoveData *data;
+
+ data = g_slice_new0 (RemoveData);
+ data->artist = g_strdup (artist);
+ data->album = g_strdup (album);
+
+ return data;
+}
+
+static void
+remove_data_free (RemoveData *data)
+{
+ if (!data) {
+ return;
+ }
+
+ g_free (data->artist);
+ g_free (data->album);
+ g_slice_free (RemoveData, data);
+}
+
+static void
+remove_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ RemoveData *data = task_data;
+ GError *error = NULL;
+ gboolean success = FALSE;
+
+ if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) {
+ success = media_art_remove (data->artist,
+ data->album,
+ cancellable,
+ &error);
+ }
+
+ if (error) {
+ g_task_return_error (task, error);
+ } else {
+ g_task_return_boolean (task, success);
+ }
+}
+
+/**
+ * media_art_remove_async:
+ * @artist: artist the media art belongs to
+ * @album: (allow-none): album the media art belongs or %NULL
+ * @source_object: (allow-none): the #GObject this task belongs to,
+ * can be %NULL.
+ * @io_priority: the [I/O priority][io-priority] of the request
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to
+ * ignore
+ * @callback: (scope async): a #GAsyncReadyCallback to call when the
+ * request is satisfied
+ * @user_data: (closure): the data to pass to callback function
+ *
+ * Removes media art for given album/artist provided. Precisely the
+ * same operation as media_art_remove() is performing, but
+ * asynchronously.
+ *
+ * When all i/o for the operation is finished the @callback will be
+ * called.
+ *
+ * In case of a partial error the callback will be called with any
+ * succeeding items and no error, and on the next request the error
+ * will be reported. If a request is cancelled the callback will be
+ * called with %G_IO_ERROR_CANCELLED.
+ *
+ * During an async request no other sync and async calls are allowed,
+ * and will result in %G_IO_ERROR_PENDING errors.
+ *
+ * Any outstanding i/o request with higher priority (lower numerical
+ * value) will be executed before an outstanding request with lower
+ * priority. Default priority is %G_PRIORITY_DEFAULT.
+ *
+ * Since: 0.7.0
+ */
+void
+media_art_remove_async (const gchar *artist,
+ const gchar *album,
+ gint io_priority,
+ GObject *source_object,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (source_object, cancellable, callback, user_data);
+ g_task_set_task_data (task, remove_data_new (artist, album), (GDestroyNotify) remove_data_free);
+ g_task_set_priority (task, io_priority);
+ g_task_run_in_thread (task, remove_thread);
+ g_object_unref (task);
+}
+
+/**
+ * media_art_remove_finish:
+ * @source_object: (allow-none): the #GObject this task belongs to,
+ * can be %NULL.
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occurring, or %NULL
+ * to ignore.
+ *
+ * Finishes the asynchronous operation started with
+ * media_art_remove_async().
+ *
+ * Returns: %TRUE on success, otherwise %FALSE when @error will be set.
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+media_art_remove_finish (GObject *source_object,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, source_object), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
diff --git a/libmediaart/cache.h b/libmediaart/cache.h
index e5bf6b8..be18e04 100644
--- a/libmediaart/cache.h
+++ b/libmediaart/cache.h
@@ -37,7 +37,6 @@ gboolean media_art_get_path (const gchar *artist,
const gchar *uri,
gchar **cache_path,
gchar **local_uri);
-
gboolean media_art_get_file (const gchar *artist,
const gchar *title,
const gchar *prefix,
@@ -46,7 +45,19 @@ gboolean media_art_get_file (const gchar *artist,
GFile **local_file);
gboolean media_art_remove (const gchar *artist,
- const gchar *album);
+ const gchar *album,
+ GCancellable *cancellable,
+ GError **error);
+void media_art_remove_async (const gchar *artist,
+ const gchar *album,
+ gint io_priority,
+ GObject *source_object,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean media_art_remove_finish (GObject *source_object,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/libmediaart/extract.c b/libmediaart/extract.c
index 692a3ee..faaf994 100644
--- a/libmediaart/extract.c
+++ b/libmediaart/extract.c
@@ -24,6 +24,7 @@
#include <errno.h>
#include <glib/gstdio.h>
+#include <glib/gi18n.h>
#include <gio/gio.h>
#include "extractgeneric.h"
@@ -146,6 +147,8 @@ media_art_process_initable_init (GInitable *initable,
MediaArtProcessPrivate *private;
MediaArtProcess *process;
GError *local_error = NULL;
+ gchar *dir;
+ gboolean retval;
process = MEDIA_ART_PROCESS (initable);
private = media_art_process_get_instance_private (process);
@@ -174,17 +177,32 @@ media_art_process_initable_init (GInitable *initable,
private->storage = storage_new ();
if (!private->storage) {
g_critical ("Could not start storage module for removable media detection");
+ g_set_error_literal (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_NO_STORAGE,
+ _("Could not initialize storage module"));
+ return FALSE;
+ }
- if (error) {
- *error = g_error_new (media_art_error_quark (),
- MEDIA_ART_ERROR_NO_STORAGE,
- "Could not initialize storage module");
- }
+ /* Returns 0 if already exists, so we don't check if directory
+ * existed before, it's an additional stat() call we just
+ * don't need.
+ */
+ dir = g_build_filename (g_get_user_cache_dir (), "media-art", NULL);
+ retval = g_mkdir_with_parents (dir, 0770);
- return FALSE;
+ if (retval == -1) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_NO_CACHE_DIR,
+ _("Could not create cache directory '%s', %d returned by g_mkdir_with_parents()"),
+ dir,
+ retval);
}
- return TRUE;
+ g_free (dir);
+
+ return retval == 0 ? TRUE : FALSE;
}
static void
diff --git a/libmediaart/extract.h b/libmediaart/extract.h
index 0cc56c8..2356790 100644
--- a/libmediaart/extract.h
+++ b/libmediaart/extract.h
@@ -69,6 +69,10 @@ typedef enum {
* @MEDIA_ART_ERROR_SYMLINK_FAILED: A call to symlink() failed
* resulting in the incorrect storage of media art.
* @MEDIA_ART_ERROR_RENAME_FAILED: File could not be renamed.
+ * @MEDIA_ART_ERROR_NO_CACHE_DIR: This is given when the
+ * XDG_CACHE_HOME directory could not be used to create the
+ * 'media-art' subdirectory used for caching media art. This is
+ * usually an initiation error.
*
* Enumeration values used in errors returned by the
* #MediaArtError API.
@@ -79,7 +83,8 @@ typedef enum {
MEDIA_ART_ERROR_NO_STORAGE,
MEDIA_ART_ERROR_NO_TITLE,
MEDIA_ART_ERROR_SYMLINK_FAILED,
- MEDIA_ART_ERROR_RENAME_FAILED
+ MEDIA_ART_ERROR_RENAME_FAILED,
+ MEDIA_ART_ERROR_NO_CACHE_DIR
} MediaArtError;