summaryrefslogtreecommitdiff
path: root/libmediaart
diff options
context:
space:
mode:
authorMartyn Russell <martyn@lanedo.com>2014-09-10 15:27:33 +0100
committerMartyn Russell <martyn@lanedo.com>2014-10-17 11:23:44 +0100
commit150878c84ae93915bdf5909c826b4c9fe4a1b392 (patch)
treeade02b3cfd80e92f568e54ffe5775592b12e931a /libmediaart
parent03a525989ec55d7c62be59bef2c352f396a2a5d2 (diff)
downloadlibmediaart-150878c84ae93915bdf5909c826b4c9fe4a1b392.tar.gz
extract: Add async APIs for all functionsasync-api
https://bugzilla.gnome.org/show_bug.cgi?id=724879
Diffstat (limited to 'libmediaart')
-rw-r--r--libmediaart/extract.c895
-rw-r--r--libmediaart/extract.h98
2 files changed, 769 insertions, 224 deletions
diff --git a/libmediaart/extract.c b/libmediaart/extract.c
index faaf994..a82b007 100644
--- a/libmediaart/extract.c
+++ b/libmediaart/extract.c
@@ -103,6 +103,21 @@ typedef enum {
IMAGE_MATCH_TYPE_COUNT
} ImageMatchType;
+typedef struct {
+ MediaArtType type;
+ MediaArtProcessFlags flags;
+
+ GFile *file;
+ gchar *uri;
+
+ unsigned char *buffer;
+ size_t len;
+ gchar *mime;
+
+ gchar *artist;
+ gchar *title;
+} ProcessData;
+
static void media_art_queue_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data);
@@ -304,63 +319,86 @@ file_get_checksum_if_exists (GChecksumType checksum_type,
const gchar *path,
gchar **md5,
gboolean check_jpeg,
- gboolean *is_jpeg)
+ gboolean *is_jpeg,
+ GError **error)
{
- GFile *file = g_file_new_for_path (path);
+ GFile *file;
GFileInputStream *stream;
GChecksum *checksum;
- gboolean retval;
+ GError *local_error = NULL;
+ gssize rsize;
+ guchar buffer[1024];
+ gboolean stop;
+
+ file = g_file_new_for_path (path);
+ stream = g_file_read (file, NULL, &local_error);
+
+ if (local_error) {
+ g_object_unref (file);
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
+ if (!stream) {
+ g_set_error (error,
+ g_io_error_quark (),
+ G_IO_ERROR_FAILED,
+ "Could not calculate MD5 checksum for '%s', g_file_read() gave no error either?!",
+ path);
+ g_object_unref (file);
+ return FALSE;
+ }
checksum = g_checksum_new (checksum_type);
if (!checksum) {
- g_debug ("Can't create checksum engine");
+ g_set_error (error,
+ g_io_error_quark (),
+ G_IO_ERROR_FAILED,
+ "Could not calculate MD5 checksum for '%s', g_checksum_new() failed",
+ path);
g_object_unref (file);
+ g_object_unref (stream);
return FALSE;
}
- stream = g_file_read (file, NULL, NULL);
-
- if (stream) {
- gssize rsize;
- guchar buffer[1024];
-
- /* File exists & readable always means true retval */
- retval = TRUE;
-
- if (check_jpeg) {
- if (g_input_stream_read_all (G_INPUT_STREAM (stream),
- buffer,
- 3,
- (gsize *) &rsize,
- NULL,
- NULL)) {
- if (rsize >= 3 &&
- buffer[0] == 0xff &&
- buffer[1] == 0xd8 &&
- buffer[2] == 0xff) {
- if (is_jpeg) {
- *is_jpeg = TRUE;
- }
-
- /* Add the read bytes to the checksum */
- g_checksum_update (checksum, buffer, rsize);
- } else {
- /* Larger than 3 bytes but incorrect jpeg header */
- if (is_jpeg) {
- *is_jpeg = FALSE;
- }
- goto end;
+ /* File exists & readable always means true retval */
+ if (check_jpeg) {
+ if (g_input_stream_read_all (G_INPUT_STREAM (stream),
+ buffer,
+ 3,
+ (gsize *) &rsize,
+ NULL,
+ NULL)) {
+ if (rsize >= 3 &&
+ buffer[0] == 0xff &&
+ buffer[1] == 0xd8 &&
+ buffer[2] == 0xff) {
+ if (is_jpeg) {
+ *is_jpeg = TRUE;
}
+
+ /* Add the read bytes to the checksum */
+ g_checksum_update (checksum, buffer, rsize);
} else {
- /* Smaller than 3 bytes, not a jpeg */
+ /* Larger than 3 bytes but incorrect jpeg header */
if (is_jpeg) {
*is_jpeg = FALSE;
}
- goto end;
+
+ stop = TRUE;
}
+ } else {
+ /* Smaller than 3 bytes, not a jpeg */
+ if (is_jpeg) {
+ *is_jpeg = FALSE;
+ }
+
+ stop = TRUE;
}
+ }
+ if (!stop) {
while ((rsize = g_input_stream_read (G_INPUT_STREAM (stream),
buffer,
1024,
@@ -372,22 +410,13 @@ file_get_checksum_if_exists (GChecksumType checksum_type,
if (md5) {
*md5 = g_strdup (g_checksum_get_string (checksum));
}
-
- } else {
- g_debug ("%s isn't readable while calculating MD5 checksum", path);
- /* File doesn't exist or isn't readable */
- retval = FALSE;
- }
-
-end:
- if (stream) {
- g_object_unref (stream);
}
+ g_object_unref (stream);
g_checksum_free (checksum);
g_object_unref (file);
- return retval;
+ return TRUE;
}
static gboolean
@@ -397,17 +426,24 @@ convert_from_other_format (const gchar *found,
const gchar *artist,
GError **error)
{
+ GError *local_error = NULL;
gboolean retval;
gchar *sum1 = NULL;
+ gchar *sum2 = NULL;
gchar *target_temp;
target_temp = g_strdup_printf ("%s-tmp", target);
- if (!media_art_file_to_jpeg (found, target_temp, error)) {
+ media_art_file_to_jpeg (found, target_temp, &local_error);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ g_unlink (target_temp);
g_free (target_temp);
return FALSE;
}
+ /* If artist doesn't exist, try to rename temp file to album path */
if (artist == NULL || g_strcmp0 (artist, " ") == 0) {
retval = g_rename (target_temp, album_path) == 0;
@@ -419,72 +455,68 @@ convert_from_other_format (const gchar *found,
target_temp,
album_path,
g_strerror (errno));
+ g_unlink (target_temp);
}
- g_debug ("rename(%s, %s) error: %s",
+ g_debug ("Renaming ('%s' --> '%s'), %s",
target_temp,
album_path,
- g_strerror (errno));
- } else if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
- target_temp,
- &sum1,
- FALSE,
- NULL)) {
- gchar *sum2 = NULL;
-
- if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
- album_path,
- &sum2,
- FALSE,
- NULL)) {
- if (g_strcmp0 (sum1, sum2) == 0) {
-
- /* If album-space-md5.jpg is the same as found,
- * make a symlink */
- retval = symlink (album_path, target) == 0;
-
- if (!retval) {
- g_set_error (error,
- media_art_error_quark (),
- MEDIA_ART_ERROR_RENAME_FAILED,
- "Could not rename '%s' to '%s': %s",
- album_path,
- target,
- g_strerror (errno));
- }
+ !retval ? g_strerror (errno) : "no error given");
- g_debug ("symlink(%s, %s) error: %s",
- album_path,
- target,
- g_strerror (errno));
+ g_free (target_temp);
- g_unlink (target_temp);
- } else {
+ return retval;
+ }
- /* If album-space-md5.jpg isn't the same as found,
- * make a new album-md5-md5.jpg (found -> target) */
- retval = g_rename (target_temp, album_path) == 0;
-
- if (!retval) {
- g_set_error (error,
- media_art_error_quark (),
- MEDIA_ART_ERROR_RENAME_FAILED,
- "Could not rename '%s' to '%s': %s",
- target_temp,
- album_path,
- g_strerror (errno));
- }
+ /* Checksum both temp file and album path and decide what to
+ * do base on what we find...
+ */
+ file_get_checksum_if_exists (G_CHECKSUM_MD5,
+ target_temp,
+ &sum1,
+ FALSE,
+ NULL,
+ &local_error);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ g_unlink (target_temp);
+ g_free (target_temp);
+ return FALSE;
+ }
+
+ file_get_checksum_if_exists (G_CHECKSUM_MD5,
+ album_path,
+ &sum2,
+ FALSE,
+ NULL,
+ &local_error);
- g_debug ("rename(%s, %s) error: %s",
- target_temp,
- album_path,
- g_strerror (errno));
+ if (!local_error) {
+ if (g_strcmp0 (sum1, sum2) == 0) {
+ /* If album-space-md5.jpg is the same as found,
+ * make a symlink */
+ retval = symlink (album_path, target) == 0;
+
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_RENAME_FAILED,
+ "Could not rename '%s' to '%s': %s",
+ album_path,
+ target,
+ g_strerror (errno));
}
- g_free (sum2);
+ g_debug ("Creating symlink ('%s' --> '%s'), %s",
+ album_path,
+ target,
+ !retval ? g_strerror (errno) : "no error given");
+
+ g_unlink (target_temp);
} else {
- /* If there's not yet a album-space-md5.jpg, make one,
- * and symlink album-md5-md5.jpg to it */
+ /* If album-space-md5.jpg isn't the same as found,
+ * make a new album-md5-md5.jpg (found -> target) */
retval = g_rename (target_temp, album_path) == 0;
if (!retval) {
@@ -492,36 +524,56 @@ convert_from_other_format (const gchar *found,
media_art_error_quark (),
MEDIA_ART_ERROR_RENAME_FAILED,
"Could not rename '%s' to '%s': %s",
+ target_temp,
album_path,
- target,
g_strerror (errno));
- } else {
- retval = symlink (album_path, target) == 0;
-
- if (!retval) {
- g_set_error (error,
- media_art_error_quark (),
- MEDIA_ART_ERROR_SYMLINK_FAILED,
- "Could not rename '%s' to '%s': %s",
- album_path,
- target,
- g_strerror (errno));
- }
-
- g_debug ("symlink(%s,%s) error: %s",
- album_path,
- target,
- g_strerror (errno));
}
+
+ g_debug ("Renaming ('%s' --> '%s'), %s",
+ target_temp,
+ album_path,
+ !retval ? g_strerror (errno) : "no error given");
}
- g_free (sum1);
+ g_free (sum2);
} else {
- g_debug ("Can't read %s while calculating checksum", target_temp);
- /* Can't read the file that it was converted to, strange ... */
- g_unlink (target_temp);
+ g_clear_error (&local_error);
+
+ /* If there's not yet a album-space-md5.jpg, make one,
+ * and symlink album-md5-md5.jpg to it */
+ retval = g_rename (target_temp, album_path) == 0;
+
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_RENAME_FAILED,
+ "Could not rename '%s' to '%s': %s",
+ album_path,
+ target,
+ g_strerror (errno));
+
+ g_unlink (target_temp);
+ } else {
+ retval = symlink (album_path, target) == 0;
+
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_SYMLINK_FAILED,
+ "Could not rename '%s' to '%s': %s",
+ album_path,
+ target,
+ g_strerror (errno));
+ }
+
+ g_debug ("Creating symlink ('%s' --> '%s'), %s",
+ album_path,
+ target,
+ !retval ? g_strerror (errno) : "no error given");
+ }
}
+ g_free (sum1);
g_free (target_temp);
return retval;
@@ -798,6 +850,7 @@ get_heuristic (MediaArtType type,
if (g_str_has_suffix (art_file_path, "jpeg") ||
g_str_has_suffix (art_file_path, "jpg")) {
+ GError *local_error = NULL;
gboolean is_jpeg = FALSE;
gchar *sum1 = NULL;
@@ -805,7 +858,6 @@ get_heuristic (MediaArtType type,
(artist == NULL || g_strcmp0 (artist, " ") == 0)) {
GFile *art_file;
GFile *target_file;
- GError *local_error = NULL;
g_debug ("Album art (JPEG) found in same directory being used:'%s'",
art_file_path);
@@ -832,7 +884,8 @@ get_heuristic (MediaArtType type,
art_file_path,
&sum1,
TRUE,
- &is_jpeg)) {
+ &is_jpeg,
+ &local_error)) {
/* Avoid duplicate artwork for each track in an album */
media_art_get_path (NULL,
title_stripped,
@@ -850,7 +903,8 @@ get_heuristic (MediaArtType type,
album_art_file_path,
&sum2,
FALSE,
- NULL)) {
+ NULL,
+ &local_error)) {
if (g_strcmp0 (sum1, sum2) == 0) {
/* If album-space-md5.jpg is the same as found,
* make a symlink */
@@ -860,13 +914,13 @@ get_heuristic (MediaArtType type,
g_set_error (error,
media_art_error_quark (),
MEDIA_ART_ERROR_SYMLINK_FAILED,
- "Could not link '%s' to '%s': %s",
+ "Could not symlink '%s' to '%s', %s",
album_art_file_path,
target,
g_strerror (errno));
}
- g_debug ("symlink(%s, %s) error: %s",
+ g_debug ("symlink('%s' --> '%s'), %s",
album_art_file_path,
target,
g_strerror (errno));
@@ -884,7 +938,11 @@ get_heuristic (MediaArtType type,
NULL,
NULL,
NULL,
- error);
+ &local_error);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ }
g_object_unref (art_file);
g_object_unref (target_file);
@@ -895,6 +953,8 @@ get_heuristic (MediaArtType type,
GFile *art_file;
GFile *album_art_file;
+ g_clear_error (&local_error);
+
/* If there's not yet a album-space-md5.jpg, make one,
* and symlink album-md5-md5.jpg to it */
album_art_file = g_file_new_for_path (album_art_file_path);
@@ -905,22 +965,24 @@ get_heuristic (MediaArtType type,
NULL,
NULL,
NULL,
- error);
+ &local_error);
- if (retval) {
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ } else {
retval = symlink (album_art_file_path, target) == 0;
if (!retval) {
g_set_error (error,
media_art_error_quark (),
MEDIA_ART_ERROR_SYMLINK_FAILED,
- "Could not link '%s' to '%s': %s",
+ "Could not symlink '%s' to '%s', %s",
album_art_file_path,
target,
g_strerror (errno));
}
- g_debug ("symlink(%s, %s) error: %s",
+ g_debug ("symlink('%s' --> '%s'), %s",
album_art_file_path, target,
g_strerror (errno));
}
@@ -940,6 +1002,7 @@ get_heuristic (MediaArtType type,
g_free (sum1);
} else {
/* Can't read contents of the cover.jpg file ... */
+ g_propagate_error (error, local_error);
retval = FALSE;
}
} else if (g_str_has_suffix (art_file_path, "png")) {
@@ -1002,6 +1065,7 @@ media_art_set (const unsigned char *buffer,
const gchar *title,
GError **error)
{
+ GError *local_error = NULL;
gchar *local_path;
gchar *album_path;
gchar *md5_album = NULL;
@@ -1048,10 +1112,19 @@ media_art_set (const unsigned char *buffer,
* i) save buffer to jpeg only.
*/
if (type != MEDIA_ART_ALBUM || (artist == NULL || g_strcmp0 (artist, " ") == 0)) {
- retval = media_art_buffer_to_jpeg (buffer, len, mime, local_path, error);
- g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s'", len, local_path);
+ retval = media_art_buffer_to_jpeg (buffer, len, mime, local_path, &local_error);
+
+ g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s', %s",
+ len,
+ local_path,
+ local_error ? local_error->message : "no error given");
g_free (local_path);
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ return FALSE;
+ }
+
return retval;
}
@@ -1067,11 +1140,17 @@ media_art_set (const unsigned char *buffer,
NULL);
if (!g_file_test (album_path, G_FILE_TEST_EXISTS)) {
- retval = TRUE;
+ media_art_buffer_to_jpeg (buffer, len, mime, album_path, &local_error);
- if (media_art_buffer_to_jpeg (buffer, len, mime, album_path, error)) {
- g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s'", len, album_path);
+ g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s', %s",
+ len,
+ local_path,
+ local_error ? local_error->message : "no error given");
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ retval = FALSE;
+ } else {
/* If album-space-md5.jpg doesn't
* exist, make one and make a symlink
* to album-md5-md5.jpg
@@ -1082,7 +1161,7 @@ media_art_set (const unsigned char *buffer,
g_set_error (error,
media_art_error_quark (),
MEDIA_ART_ERROR_SYMLINK_FAILED,
- "Could not link '%s' to '%s': %s",
+ "Could not symlink '%s' to '%s', %s",
album_path,
local_path,
g_strerror (errno));
@@ -1100,16 +1179,21 @@ media_art_set (const unsigned char *buffer,
return retval;
}
- if (!file_get_checksum_if_exists (G_CHECKSUM_MD5,
- album_path,
- &md5_album,
- FALSE,
- NULL)) {
- g_debug ("No MD5 checksum found for album path:'%s'", album_path);
+ file_get_checksum_if_exists (G_CHECKSUM_MD5,
+ album_path,
+ &md5_album,
+ FALSE,
+ NULL,
+ &local_error);
+
+ if (local_error) {
+ g_debug ("%s", local_error->message);
+ g_propagate_error (error, local_error);
g_free (album_path);
g_free (local_path);
+ /* FIXME: Is it right to return TRUE here ?*/
return TRUE;
}
@@ -1133,7 +1217,7 @@ media_art_set (const unsigned char *buffer,
g_set_error (error,
media_art_error_quark (),
MEDIA_ART_ERROR_SYMLINK_FAILED,
- "Could not link '%s' to '%s': %s",
+ "Could not symlink '%s' to '%s', %s",
album_path,
local_path,
g_strerror (errno));
@@ -1147,8 +1231,17 @@ media_art_set (const unsigned char *buffer,
/* If album-space-md5.jpg isn't the same as
* buffer, make a new album-md5-md5.jpg
*/
- retval = media_art_buffer_to_jpeg (buffer, len, mime, local_path, error);
- g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s'", len, local_path);
+ retval = media_art_buffer_to_jpeg (buffer, len, mime, local_path, &local_error);
+
+ g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s', %s",
+ len,
+ local_path,
+ local_error ? local_error->message : "no error given");
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ retval = FALSE;
+ }
}
g_free (md5_data);
@@ -1166,10 +1259,18 @@ media_art_set (const unsigned char *buffer,
* cache, unlink it...
*/
temp = g_strdup_printf ("%s-tmp", album_path);
+ media_art_buffer_to_jpeg (buffer, len, mime, temp, &local_error);
- /* If buffer isn't a JPEG */
- if (!media_art_buffer_to_jpeg (buffer, len, mime, temp, error)) {
- /* Can't read temp file ... */
+ g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s', %s",
+ len,
+ local_path,
+ local_error ? local_error->message : "no error given");
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+
+ /* Unlink in case there was some error and half the
+ * job was done. */
g_unlink (temp);
g_free (temp);
@@ -1180,11 +1281,14 @@ media_art_set (const unsigned char *buffer,
return FALSE;
}
- if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
- temp,
- &md5_tmp,
- FALSE,
- NULL)) {
+ file_get_checksum_if_exists (G_CHECKSUM_MD5,
+ temp,
+ &md5_tmp,
+ FALSE,
+ NULL,
+ &local_error);
+
+ if (!local_error) {
if (g_strcmp0 (md5_tmp, md5_album) == 0) {
/* If album-space-md5.jpg is the same as
* buffer, make a symlink to album-md5-md5.jpg
@@ -1195,7 +1299,7 @@ media_art_set (const unsigned char *buffer,
g_set_error (error,
media_art_error_quark (),
MEDIA_ART_ERROR_SYMLINK_FAILED,
- "Could not link '%s' to '%s': %s",
+ "Could not symlink '%s' to '%s', %s",
album_path,
local_path,
g_strerror (errno));
@@ -1215,7 +1319,7 @@ media_art_set (const unsigned char *buffer,
g_set_error (error,
media_art_error_quark (),
MEDIA_ART_ERROR_RENAME_FAILED,
- "Could not rename '%s' to '%s': %s",
+ "Could not rename '%s' to '%s', %s",
temp,
local_path,
g_strerror (errno));
@@ -1228,6 +1332,10 @@ media_art_set (const unsigned char *buffer,
}
g_free (md5_tmp);
+ } else {
+ g_debug ("%s", local_error->message);
+ g_propagate_error (error, local_error);
+ retval = FALSE;
}
/* Clean up */
@@ -1507,6 +1615,113 @@ get_heuristic_for_parent_path (GFile *file,
return key;
}
+static ProcessData *
+process_data_new (MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *file,
+ const gchar *uri,
+ const unsigned char *buffer,
+ size_t len,
+ const gchar *mime,
+ const gchar *artist,
+ const gchar *title)
+{
+ ProcessData *data;
+
+ data = g_slice_new0 (ProcessData);
+ data->type = type;
+ data->flags = flags;
+
+ if (file) {
+ data->file = g_object_ref (file);
+ }
+
+ data->uri = g_strdup (uri);
+
+ data->buffer = g_memdup (buffer, data->len);
+ data->len = len;
+ data->mime = g_strdup (mime);
+
+ data->artist = g_strdup (artist);
+ data->title = g_strdup (title);
+
+ return data;
+}
+
+static void
+process_data_free (ProcessData *data)
+{
+ if (!data) {
+ return;
+ }
+
+ if (data->file) {
+ g_object_unref (data->file);
+ }
+
+ g_free (data->uri);
+
+ g_free (data->buffer);
+ g_free (data->mime);
+
+ g_free (data->artist);
+ g_free (data->title);
+
+ g_slice_free (ProcessData, data);
+}
+
+static void
+process_thread (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ MediaArtProcess *process = MEDIA_ART_PROCESS (source_object);
+ ProcessData *data = task_data;
+ GError *error = NULL;
+ gboolean success = FALSE;
+
+ if (!g_cancellable_set_error_if_cancelled (cancellable, &error)) {
+ if (data->file) {
+ success = media_art_process_file (process,
+ data->type,
+ data->flags,
+ data->file,
+ data->artist,
+ data->title,
+ cancellable,
+ &error);
+ } else if (data->uri) {
+ success = media_art_process_uri (process,
+ data->type,
+ data->flags,
+ data->uri,
+ data->artist,
+ data->title,
+ cancellable,
+ &error);
+ } else {
+ success = media_art_process_buffer (process,
+ data->type,
+ data->flags,
+ data->file,
+ data->buffer,
+ data->len,
+ data->mime,
+ data->artist,
+ data->title,
+ cancellable,
+ &error);
+ }
+ }
+
+ if (error) {
+ g_task_return_error (task, error);
+ } else {
+ g_task_return_boolean (task, success);
+ }
+}
+
/**
* media_art_process_buffer:
* @process: Media art process object
@@ -1518,7 +1733,10 @@ get_heuristic_for_parent_path (GFile *file,
* @mime: MIME type of @buffer, or %NULL
* @artist: (allow-none): The artist name @file or %NULL
* @title: (allow-none): The title for @file or %NULL
- * @error: Pointer to potential GLib / MediaArt error, or %NULL
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to
+ * ignore
+ * @error: a #GError location to store the error occurring, or %NULL
+ * to ignore.
*
* Processes a memory buffer represented by @buffer and @len. If you
* have extracted any embedded media art and passed this in as
@@ -1544,6 +1762,7 @@ media_art_process_buffer (MediaArtProcess *process,
const gchar *mime,
const gchar *artist,
const gchar *title,
+ GCancellable *cancellable,
GError **error)
{
GFile *cache_art_file, *local_art_file;
@@ -1591,6 +1810,11 @@ media_art_process_buffer (MediaArtProcess *process,
cache_mtime = get_mtime (cache_art_file, &local_error);
+ if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ g_free (uri);
+ return FALSE;
+ }
+
if (local_error &&
local_error->domain == g_io_error_quark () &&
local_error->code == G_IO_ERROR_NOT_FOUND) {
@@ -1636,16 +1860,18 @@ media_art_process_buffer (MediaArtProcess *process,
processed = TRUE;
}
- if (local_art_file && !g_file_query_exists (local_art_file, NULL)) {
- /* We can't reuse art_exists here because the
- * situation might have changed
- */
- if (g_file_query_exists (cache_art_file, NULL)) {
- gchar *local_art_uri;
+ if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ if (local_art_file && !g_file_query_exists (local_art_file, NULL)) {
+ /* We can't reuse art_exists here because the
+ * situation might have changed
+ */
+ if (g_file_query_exists (cache_art_file, NULL)) {
+ gchar *local_art_uri;
- local_art_uri = g_file_get_uri (local_art_file);
- media_art_copy_to_local (process, cache_art_path, local_art_uri);
- g_free (local_art_uri);
+ local_art_uri = g_file_get_uri (local_art_file);
+ media_art_copy_to_local (process, cache_art_path, local_art_uri);
+ g_free (local_art_uri);
+ }
}
}
@@ -1660,10 +1886,102 @@ media_art_process_buffer (MediaArtProcess *process,
g_free (cache_art_path);
g_free (uri);
+ if (g_cancellable_is_cancelled (cancellable)) {
+ processed = FALSE;
+ }
+
return processed;
}
/**
+ * media_art_process_buffer_async:
+ * @process: Media art process object
+ * @type: The type of media
+ * @flags: The options given for how to process the media art
+ * @related_file: File related to the media art
+ * @buffer: (array length=len)(allow-none): a buffer containing @file
+ * data, or %NULL
+ * @len: length of @buffer, or 0
+ * @mime: MIME type of @buffer, or %NULL
+ * @artist: (allow-none): The artist name @file or %NULL
+ * @title: (allow-none): The title for @file or %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
+ *
+ * Processes media art. Precisely the same operation as
+ * media_art_process_buffer() 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.
+ *
+ * Dbufferng 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_process_buffer_async (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *related_file,
+ const guchar *buffer,
+ gsize len,
+ const gchar *mime,
+ const gchar *artist,
+ const gchar *title,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (process, cancellable, callback, user_data);
+ g_task_set_task_data (task, process_data_new (type, flags, related_file, NULL, buffer, len, mime, artist, title), (GDestroyNotify) process_data_free);
+ g_task_set_priority (task, io_priority);
+ g_task_run_in_thread (task, process_thread);
+ g_object_unref (task);
+}
+
+/**
+ * media_art_process_buffer_finish:
+ * @process: the #MediaArtProcess
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occurring, or %NULL
+ * to ignore.
+ *
+ * Finishes the asynchronous operation started with
+ * media_art_process_file_async().
+ *
+ * Returns: %TRUE on success, otherwise %FALSE when @error will be set.
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+media_art_process_buffer_finish (MediaArtProcess *process,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, process), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+
+}
+
+/**
* media_art_process_file:
* @process: Media art process object
* @type: The type of media
@@ -1671,7 +1989,10 @@ media_art_process_buffer (MediaArtProcess *process,
* @file: File to be processed
* @artist: (allow-none): The artist name @file or %NULL
* @title: (allow-none): The title for @file or %NULL
- * @error: Pointer to potential GLib / MediaArt error, or %NULL
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to
+ * ignore
+ * @error: a #GError location to store the error occurring, or %NULL
+ * to ignore.
*
* Process @file and check if media art exists and if it is up to date
* with @artist and @title provided. Either @artist OR @title can be
@@ -1712,6 +2033,7 @@ media_art_process_file (MediaArtProcess *process,
GFile *file,
const gchar *artist,
const gchar *title,
+ GCancellable *cancellable,
GError **error)
{
MediaArtProcessPrivate *private;
@@ -1747,6 +2069,11 @@ media_art_process_file (MediaArtProcess *process,
return FALSE;
}
+ if (g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ g_free (uri);
+ return FALSE;
+ }
+
media_art_get_file (artist,
title,
media_art_type_name[type],
@@ -1766,32 +2093,37 @@ media_art_process_file (MediaArtProcess *process,
key = get_heuristic_for_parent_path (file, type, artist, title);
if (!g_hash_table_lookup (private->media_art_cache, key)) {
- gchar *local_art_uri;
-
- local_art_uri = g_file_get_uri (local_art_file);
-
- if (!get_heuristic (type, uri, local_art_uri, artist, title, error)) {
- /* If the heuristic failed, we
- * request the download the
- * media-art to the media-art
- * downloaders
- */
- media_art_request_download (process,
- type,
- artist,
- title,
- local_art_uri,
- cache_art_path);
-
- /* FIXME: Should return TRUE or FALSE? */
- }
+ /* Check we're not cancelled before
+ * potentially trying a download operation.
+ */
+ if (!g_cancellable_set_error_if_cancelled (cancellable, error)) {
+ gchar *local_art_uri;
+
+ local_art_uri = g_file_get_uri (local_art_file);
+
+ if (!get_heuristic (type, uri, local_art_uri, artist, title, error)) {
+ /* If the heuristic failed, we
+ * request the download the
+ * media-art to the media-art
+ * downloaders
+ */
+ media_art_request_download (process,
+ type,
+ artist,
+ title,
+ local_art_uri,
+ cache_art_path);
+
+ /* FIXME: Should return TRUE or FALSE? */
+ }
- set_mtime (cache_art_path, mtime);
+ set_mtime (cache_art_path, mtime);
- g_hash_table_insert (private->media_art_cache,
- key,
- GINT_TO_POINTER(TRUE));
- g_free (local_art_uri);
+ g_hash_table_insert (private->media_art_cache,
+ key,
+ GINT_TO_POINTER(TRUE));
+ g_free (local_art_uri);
+ }
} else {
g_free (key);
}
@@ -1812,7 +2144,89 @@ media_art_process_file (MediaArtProcess *process,
g_free (cache_art_path);
g_free (uri);
- return TRUE;
+ return !g_cancellable_is_cancelled (cancellable);
+}
+
+
+/**
+ * media_art_process_file_async:
+ * @process: Media art process object
+ * @type: The type of media
+ * @flags: The options given for how to process the media art
+ * @file: File to be processed
+ * @artist: (allow-none): The artist name @file or %NULL
+ * @title: (allow-none): The title for @file or %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
+ *
+ * Processes media art. Precisely the same operation as
+ * media_art_process_file() 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_process_file_async (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *file,
+ const gchar *artist,
+ const gchar *title,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (process, cancellable, callback, user_data);
+ g_task_set_task_data (task, process_data_new (type, flags, file, NULL, NULL, 0, NULL, artist, title), (GDestroyNotify) process_data_free);
+ g_task_set_priority (task, io_priority);
+ g_task_run_in_thread (task, process_thread);
+ g_object_unref (task);
+}
+
+/**
+ * media_art_process_file_finish:
+ * @process: the #MediaArtProcess
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occurring, or %NULL
+ * to ignore.
+ *
+ * Finishes the asynchronous operation started with
+ * media_art_process_file_async().
+ *
+ * Returns: %TRUE on success, otherwise %FALSE when @error will be set.
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+media_art_process_file_finish (MediaArtProcess *process,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, process), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+
}
/**
@@ -1823,6 +2237,8 @@ media_art_process_file (MediaArtProcess *process,
* @uri: URI of the media file that contained the data
* @artist: (allow-none): The artist name @uri or %NULL
* @title: (allow-none): The title for @uri or %NULL
+ * @cancellable: (allow-none): optional #GCancellable object, %NULL to
+ * ignore
* @error: Pointer to potential GLib / MediaArt error, or %NULL
*
* This function calls media_art_process_file(), but takes the @uri as
@@ -1840,6 +2256,7 @@ media_art_process_uri (MediaArtProcess *process,
const gchar *uri,
const gchar *artist,
const gchar *title,
+ GCancellable *cancellable,
GError **error)
{
GFile *file;
@@ -1858,9 +2275,91 @@ media_art_process_uri (MediaArtProcess *process,
file,
artist,
title,
+ cancellable,
error);
g_object_unref (file);
return result;
}
+
+/**
+ * media_art_process_uri_async:
+ * @process: Media art process object
+ * @type: The type of media
+ * @flags: The options given for how to process the media art
+ * @uri: A string representing a URI to be processed
+ * @artist: (allow-none): The artist name @file or %NULL
+ * @title: (allow-none): The title for @file or %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
+ *
+ * Processes media art. Precisely the same operation as
+ * media_art_process_uri() 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_process_uri_async (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ const gchar *uri,
+ const gchar *artist,
+ const gchar *title,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+
+ task = g_task_new (process, cancellable, callback, user_data);
+ g_task_set_task_data (task, process_data_new (type, flags, NULL, uri, NULL, 0, NULL, artist, title), (GDestroyNotify) process_data_free);
+ g_task_set_priority (task, io_priority);
+ g_task_run_in_thread (task, process_thread);
+ g_object_unref (task);
+}
+
+/**
+ * media_art_process_uri_finish:
+ * @process: the #MediaArtProcess
+ * @result: a #GAsyncResult.
+ * @error: a #GError location to store the error occurring, or %NULL
+ * to ignore.
+ *
+ * Finishes the asynchronous operation started with
+ * media_art_process_file_async().
+ *
+ * Returns: %TRUE on success, otherwise %FALSE when @error will be set.
+ *
+ * Since: 0.7.0
+ **/
+gboolean
+media_art_process_uri_finish (MediaArtProcess *process,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, process), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+
+}
diff --git a/libmediaart/extract.h b/libmediaart/extract.h
index 2356790..c01d2cb 100644
--- a/libmediaart/extract.h
+++ b/libmediaart/extract.h
@@ -129,32 +129,78 @@ struct _MediaArtProcessClass {
};
-GType media_art_process_get_type (void) G_GNUC_CONST;
-MediaArtProcess *media_art_process_new (GError **error);
-gboolean media_art_process_uri (MediaArtProcess *process,
- MediaArtType type,
- MediaArtProcessFlags flags,
- const gchar *uri,
- const gchar *artist,
- const gchar *title,
- GError **error);
-gboolean media_art_process_file (MediaArtProcess *process,
- MediaArtType type,
- MediaArtProcessFlags flags,
- GFile *file,
- const gchar *artist,
- const gchar *title,
- GError **error);
-gboolean media_art_process_buffer (MediaArtProcess *process,
- MediaArtType type,
- MediaArtProcessFlags flags,
- GFile *related_file,
- const guchar *buffer,
- gsize len,
- const gchar *mime,
- const gchar *artist,
- const gchar *title,
- GError **error);
+GType media_art_process_get_type (void) G_GNUC_CONST;
+
+MediaArtProcess *media_art_process_new (GError **error);
+gboolean media_art_process_uri (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ const gchar *uri,
+ const gchar *artist,
+ const gchar *title,
+ GCancellable *cancellable,
+ GError **error);
+void media_art_process_uri_async (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ const gchar *uri,
+ const gchar *artist,
+ const gchar *title,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean media_art_process_uri_finish (MediaArtProcess *process,
+ GAsyncResult *result,
+ GError **error);
+gboolean media_art_process_file (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *file,
+ const gchar *artist,
+ const gchar *title,
+ GCancellable *cancellable,
+ GError **error);
+void media_art_process_file_async (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *file,
+ const gchar *artist,
+ const gchar *title,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean media_art_process_file_finish (MediaArtProcess *process,
+ GAsyncResult *result,
+ GError **error);
+gboolean media_art_process_buffer (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *related_file,
+ const guchar *buffer,
+ gsize len,
+ const gchar *mime,
+ const gchar *artist,
+ const gchar *title,
+ GCancellable *cancellable,
+ GError **error);
+void media_art_process_buffer_async (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *related_file,
+ const guchar *buffer,
+ gsize len,
+ const gchar *mime,
+ const gchar *artist,
+ const gchar *title,
+ gint io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean media_art_process_buffer_finish (MediaArtProcess *process,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS