summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libmediaart/extract.c895
-rw-r--r--libmediaart/extract.h98
-rw-r--r--tests/mediaarttest.c493
3 files changed, 1062 insertions, 424 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
diff --git a/tests/mediaarttest.c b/tests/mediaarttest.c
index 22694b6..f93845c 100644
--- a/tests/mediaarttest.c
+++ b/tests/mediaarttest.c
@@ -36,23 +36,23 @@ typedef struct {
static TestInfo strip_test_cases [] = {
{ "nothing-to-strip", "nothing to strip here", NULL, "nothing to strip here" },
- { "case-strip", "Upper Case gOEs dOwN", NULL, "upper case goes down" },
+ { "case-strip", "Upper Case gOEs dOwN", NULL, "upper case goes down" },
{ "single-char", "o", NULL, "o" },
- { "single-char-case", "A", NULL, "a" },
- { "remove-parenthesis-round", "cool album (CD1)", NULL, "cool album" },
+ { "single-char-case", "A", NULL, "a" },
+ { "remove-parenthesis-round", "cool album (CD1)", NULL, "cool album" },
{ "remove-parenthesis-square", "cool album [CD1]", NULL, "cool album" },
- { "remove-parenthesis-squirly", "cool album {CD1}", NULL, "cool album" },
- { "remove-parenthesis-gt-lt", "cool album <CD1>", NULL, "cool album" },
- { "whitespace", " ", NULL, "" },
- { "whitespace-with-content", " a ", NULL, "a" },
- { "messy-title", "messy #title & stuff?", NULL, "messy title stuff" },
+ { "remove-parenthesis-squirly", "cool album {CD1}", NULL, "cool album" },
+ { "remove-parenthesis-gt-lt", "cool album <CD1>", NULL, "cool album" },
+ { "whitespace", " ", NULL, "" },
+ { "whitespace-with-content", " a ", NULL, "a" },
+ { "messy-title", "messy #title & stuff?", NULL, "messy title stuff" },
{ "unbalanced-brackets-square-start", "Unbalanced [brackets", NULL, "unbalanced brackets" },
- { "unbalanced-brackets-round-start", "Unbalanced (brackets", NULL, "unbalanced brackets" },
- { "unbalanced-brackets-gt-lt-start", "Unbalanced <brackets", NULL, "unbalanced brackets" },
- { "unbalanced-brackets-round-end", "Unbalanced brackets)", NULL, "unbalanced brackets" },
- { "unbalanced-brackets-square-end", "Unbalanced brackets]", NULL, "unbalanced brackets" },
- { "unbalanced-brackets-gt-lt-end", "Unbalanced brackets>", NULL, "unbalanced brackets" },
- { "messy-title-punctuation", "Live at *WEMBLEY* dude!", NULL, "live at wembley dude" },
+ { "unbalanced-brackets-round-start", "Unbalanced (brackets", NULL, "unbalanced brackets" },
+ { "unbalanced-brackets-gt-lt-start", "Unbalanced <brackets", NULL, "unbalanced brackets" },
+ { "unbalanced-brackets-round-end", "Unbalanced brackets)", NULL, "unbalanced brackets" },
+ { "unbalanced-brackets-square-end", "Unbalanced brackets]", NULL, "unbalanced brackets" },
+ { "unbalanced-brackets-gt-lt-end", "Unbalanced brackets>", NULL, "unbalanced brackets" },
+ { "messy-title-punctuation", "Live at *WEMBLEY* dude!", NULL, "live at wembley dude" },
{ "crap-brackets-everywhere", "met[xX[x]alli]ca", NULL, "metallica" },
{ NULL, NULL, NULL, NULL }
};
@@ -60,20 +60,20 @@ static TestInfo strip_test_cases [] = {
static TestInfo location_test_cases [] = {
{ "normal-case",
"Beatles", "Sgt. Pepper",
- "album-2a9ea35253dbec60e76166ec8420fbda-cfba4326a32b44b8760b3a2fc827a634.jpeg" },
+ "album-2a9ea35253dbec60e76166ec8420fbda-cfba4326a32b44b8760b3a2fc827a634.jpeg" },
{ "empty-artist",
"", "sgt. pepper",
- "album-d41d8cd98f00b204e9800998ecf8427e-cfba4326a32b44b8760b3a2fc827a634.jpeg" },
+ "album-d41d8cd98f00b204e9800998ecf8427e-cfba4326a32b44b8760b3a2fc827a634.jpeg" },
{ "whitespace-artist",
" ", "sgt. pepper",
- "album-d41d8cd98f00b204e9800998ecf8427e-cfba4326a32b44b8760b3a2fc827a634.jpeg" },
+ "album-d41d8cd98f00b204e9800998ecf8427e-cfba4326a32b44b8760b3a2fc827a634.jpeg" },
{ "null-artist",
NULL, "sgt. pepper",
- "album-cfba4326a32b44b8760b3a2fc827a634-7215ee9c7d9dc229d2921a40e899ec5f.jpeg" },
+ "album-cfba4326a32b44b8760b3a2fc827a634-7215ee9c7d9dc229d2921a40e899ec5f.jpeg" },
{ "null-title",
"Beatles", NULL,
- "album-2a9ea35253dbec60e76166ec8420fbda-7215ee9c7d9dc229d2921a40e899ec5f.jpeg" },
- { NULL, NULL, NULL, NULL }
+ "album-2a9ea35253dbec60e76166ec8420fbda-7215ee9c7d9dc229d2921a40e899ec5f.jpeg" },
+ { NULL, NULL, NULL, NULL }
};
static void
@@ -93,29 +93,14 @@ teardown (TestInfo *info,
}
static void
-test_mediaart_new (TestInfo *test_info,
- gconstpointer context)
-{
- MediaArtProcess *process;
- GError *error = NULL;
-
- /* Test: creation of object */
- process = media_art_process_new (&error);
- g_assert_no_error (error);
- g_assert (process != NULL);
-
- g_object_unref (process);
-}
-
-static void
test_mediaart_stripping (TestInfo *test_info,
gconstpointer context)
{
- gchar *result;
+ gchar *result;
- result = media_art_strip_invalid_entities (test_info->input1);
- g_assert_cmpstr (result, ==, test_info->expected);
- g_free (result);
+ result = media_art_strip_invalid_entities (test_info->input1);
+ g_assert_cmpstr (result, ==, test_info->expected);
+ g_free (result);
}
static void
@@ -132,9 +117,9 @@ test_mediaart_stripping_failures (void)
/* a. Return NULL for NULL (subprocess)
* b. Return NULL for ""
*/
- stripped = media_art_strip_invalid_entities ("");
- g_assert (stripped);
- g_assert_cmpstr (stripped, ==, "");
+ stripped = media_art_strip_invalid_entities ("");
+ g_assert (stripped);
+ g_assert_cmpstr (stripped, ==, "");
g_test_trap_subprocess ("/mediaart/stripping_failures/subprocess", 0, 0);
g_test_trap_assert_failed ();
@@ -146,75 +131,151 @@ static void
test_mediaart_location (TestInfo *test_info,
gconstpointer context)
{
- gchar *path = NULL, *local_uri = NULL;
- gchar *expected;
-
- media_art_get_path (test_info->input1,
- test_info->input2,
- "album",
- "file:///home/test/a.mp3",
- &path,
- &local_uri);
- expected = g_build_path (G_DIR_SEPARATOR_S,
- g_get_user_cache_dir (),
- "media-art",
- test_info->expected,
- NULL);
- g_assert_cmpstr (path, ==, expected);
-
- g_free (expected);
- g_free (path);
- g_free (local_uri);
+ gchar *path = NULL, *local_uri = NULL;
+ gchar *expected;
+
+ media_art_get_path (test_info->input1,
+ test_info->input2,
+ "album",
+ "file:///home/test/a.mp3",
+ &path,
+ &local_uri);
+ expected = g_build_path (G_DIR_SEPARATOR_S,
+ g_get_user_cache_dir (),
+ "media-art",
+ test_info->expected,
+ NULL);
+ g_assert_cmpstr (path, ==, expected);
+
+ g_free (expected);
+ g_free (path);
+ g_free (local_uri);
}
static void
test_mediaart_location_null (void)
{
- gchar *path = NULL, *local_uri = NULL;
+ gchar *path = NULL, *local_uri = NULL;
- /* NULL parameters */
- media_art_get_path (NULL, "some-title", "album", "file:///a/b/c.mp3", &path, &local_uri);
- g_assert (path != NULL);
- g_assert (local_uri != NULL);
+ /* NULL parameters */
+ media_art_get_path (NULL, "some-title", "album", "file:///a/b/c.mp3", &path, &local_uri);
+ g_assert (path != NULL);
+ g_assert (local_uri != NULL);
- media_art_get_path ("some-artist", NULL, "album", "file:///a/b/c.mp3", &path, &local_uri);
- g_assert (path != NULL);
- g_assert (local_uri != NULL);
+ media_art_get_path ("some-artist", NULL, "album", "file:///a/b/c.mp3", &path, &local_uri);
+ g_assert (path != NULL);
+ g_assert (local_uri != NULL);
}
static void
test_mediaart_location_path (void)
{
- gchar *path = NULL, *local_uri = NULL;
- gchar *expected;
-
- /* Use path instead of URI */
- media_art_get_path (location_test_cases[0].input1,
- location_test_cases[0].input2,
- "album",
- "/home/test/a.mp3",
- &path,
- &local_uri);
- expected = g_build_path (G_DIR_SEPARATOR_S,
- g_get_user_cache_dir (),
- "media-art",
- location_test_cases[0].expected,
- NULL);
- g_assert_cmpstr (path, ==, expected);
-
- g_free (expected);
- g_free (path);
- g_free (local_uri);
+ gchar *path = NULL, *local_uri = NULL;
+ gchar *expected;
+
+ /* Use path instead of URI */
+ media_art_get_path (location_test_cases[0].input1,
+ location_test_cases[0].input2,
+ "album",
+ "/home/test/a.mp3",
+ &path,
+ &local_uri);
+ expected = g_build_path (G_DIR_SEPARATOR_S,
+ g_get_user_cache_dir (),
+ "media-art",
+ location_test_cases[0].expected,
+ NULL);
+ g_assert_cmpstr (path, ==, expected);
+
+ g_free (expected);
+ g_free (path);
+ g_free (local_uri);
+}
+
+static void
+test_mediaart_process_new (void)
+{
+ MediaArtProcess *process;
+ GError *error = NULL;
+ gchar *dir;
+
+ dir = g_build_filename (g_get_user_cache_dir (), "media-art", NULL);
+ g_assert_false (g_file_test (dir, G_FILE_TEST_EXISTS));
+
+ /* Creates media-art cache dir if it doesn't exist ... */
+ process = media_art_process_new (&error);
+ g_assert_no_error (error);
+
+ g_assert_true (g_file_test (dir, G_FILE_TEST_EXISTS));
+
+ g_free (dir);
+
+ g_object_unref (process);
+}
+
+static void
+test_mediaart_remove_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ GMainLoop *ml = user_data;
+ gboolean success;
+
+ success = media_art_remove_finish (source_object, result, &error);
+ g_assert_no_error (error);
+ g_assert_true (success);
+
+ g_main_loop_quit (ml);
+}
+
+static void
+test_mediaart_remove (const gchar *artist,
+ const gchar *title,
+ gpointer user_data)
+{
+ GCancellable *cancellable;
+
+ cancellable = g_cancellable_new ();
+
+ /* Remove album art */
+ media_art_remove_async (artist,
+ title,
+ G_PRIORITY_DEFAULT,
+ NULL,
+ cancellable,
+ test_mediaart_remove_cb,
+ user_data);
+
+ g_object_unref (cancellable);
+}
+
+static void
+test_mediaart_process_file_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ MediaArtProcess *process = MEDIA_ART_PROCESS (source_object);
+ GError *error = NULL;
+ GMainLoop *ml = user_data;
+ gboolean success;
+
+ success = media_art_process_file_finish (process, result, &error);
+ g_assert_no_error (error);
+ g_assert_true (success);
+
+ test_mediaart_remove ("King Kilo", "Radium", ml);
}
static void
-test_mediaart_embedded_mp3 (void)
+test_mediaart_process_file (void)
{
MediaArtProcess *process;
+ GMainLoop *ml;
+ GCancellable *cancellable;
GError *error = NULL;
GFile *file = NULL;
gchar *path;
- gboolean retval;
path = g_build_filename (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "543249_King-Kilo---Radium.mp3", NULL);
file = g_file_new_for_path (path);
@@ -223,135 +284,166 @@ test_mediaart_embedded_mp3 (void)
process = media_art_process_new (&error);
g_assert_no_error (error);
- retval = media_art_process_file (process,
- MEDIA_ART_ALBUM,
- MEDIA_ART_PROCESS_FLAGS_FORCE,
- file,
- "King Kilo", /* artist */
- "Radium", /* title */
- &error);
+ ml = g_main_loop_new (NULL, FALSE);
+ cancellable = g_cancellable_new ();
- g_assert_no_error (error);
- g_assert_true (retval);
+ media_art_process_file_async (process,
+ MEDIA_ART_ALBUM,
+ MEDIA_ART_PROCESS_FLAGS_FORCE,
+ file,
+ "King Kilo", /* artist */
+ "Radium", /* title */
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ test_mediaart_process_file_cb,
+ ml);
- g_object_unref (file);
+ g_main_loop_run (ml);
+ g_main_loop_unref (ml);
+ g_object_unref (cancellable);
g_object_unref (process);
}
static void
-test_mediaart_remove_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer user_data)
+test_mediaart_process_buffer_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
GError *error = NULL;
- GFile *file = user_data;
+ GFile *file;
+ gchar *path;
+ gchar *expected;
+ gchar *out_path = NULL;
+ gchar *out_uri = NULL;
gboolean success;
- success = media_art_remove_finish (source_object, result, &error);
- g_assert_no_error (error);
- g_assert_true (success);
+ success = media_art_process_buffer_finish (MEDIA_ART_PROCESS (source_object), result, &error);
+ g_assert_no_error (error);
+ g_assert_true (success);
- success = media_art_remove ("Lanedo", NULL, NULL, &error);
- g_assert_no_error (error);
- g_assert_true (success);
+ /* Check cache exists */
+ path = g_build_filename (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "cover.png", NULL);
+ file = g_file_new_for_path (path);
- g_object_unref (file);
+ media_art_get_path ("Lanedo", /* artist / title */
+ NULL, /* album */
+ NULL, /* prefix */
+ path,
+ &out_path,
+ &out_uri);
+ g_free (path);
+ g_object_unref (file);
+
+ expected = g_build_path (G_DIR_SEPARATOR_S,
+ g_get_user_cache_dir (),
+ "media-art",
+ "album-be60c84852d9762b0a896ba9ba24245e-7215ee9c7d9dc229d2921a40e899ec5f.jpeg",
+ NULL);
+ g_assert_cmpstr (out_path, ==, expected);
+ /* FIXME: Why is out_uri NULL? */
+ /* FIXME: Why does this next test fail - i.e. file does not
+ * exist if we've processed it?
+ */
+ g_assert (g_file_test (out_path, G_FILE_TEST_EXISTS) == TRUE);
+
+ test_mediaart_remove ("Lanedo", NULL, user_data);
+
+ g_free (out_path);
+ g_free (out_uri);
+ g_free (expected);
}
static void
test_mediaart_process_buffer (void)
{
MediaArtProcess *process;
- GCancellable *cancellable;
+ GMainLoop *ml;
+ GCancellable *cancellable;
+ GFile *file;
GError *error = NULL;
- GFile *file = NULL;
- gchar *dir;
gchar *path;
gchar *out_path = NULL;
gchar *out_uri = NULL;
- gchar *expected;
- gboolean retval;
+ unsigned char *buffer = NULL;
+ size_t length = 0;
+ const gchar *mime;
+
+ cancellable = g_cancellable_new ();
path = g_build_filename (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "cover.png", NULL);
- file = g_file_new_for_path (path);
/* Check data is not cached currently */
media_art_get_path ("Lanedo", /* artist / title */
NULL, /* album */
NULL, /* prefix */
- path,
- &out_path,
- &out_uri);
+ path,
+ &out_path,
+ &out_uri);
g_assert_false (g_file_test (out_path, G_FILE_TEST_EXISTS));
g_free (out_path);
g_free (out_uri);
- /* Creates media-art cache dir if it doesn't exist ... */
process = media_art_process_new (&error);
g_assert_no_error (error);
+ g_assert_nonnull (process);
- dir = g_build_filename (g_get_user_cache_dir (), "media-art", NULL);
- g_assert_true (g_file_test (dir, G_FILE_TEST_EXISTS));
- g_free (dir);
+ ml = g_main_loop_new (NULL, FALSE);
/* Process data */
- retval = media_art_process_file (process,
- MEDIA_ART_ALBUM,
- MEDIA_ART_PROCESS_FLAGS_NONE,
- file,
- NULL, /* album */
- "Lanedo", /* title */
- &error);
+ mime = "image/png";
+ g_file_get_contents (path, (gchar**) &buffer, &length, &error);
g_assert_no_error (error);
- g_assert_true (retval);
- /* Check cache exists */
- media_art_get_path ("Lanedo", /* artist / title */
- NULL, /* album */
- NULL, /* prefix */
- path,
- &out_path,
- &out_uri);
-
- expected = g_build_path (G_DIR_SEPARATOR_S,
- g_get_user_cache_dir (),
- "media-art",
- "album-be60c84852d9762b0a896ba9ba24245e-7215ee9c7d9dc229d2921a40e899ec5f.jpeg",
- NULL);
- g_assert_cmpstr (out_path, ==, expected);
- /* FIXME: Why is out_uri NULL? */
- /* FIXME: Why does this next test fail - i.e. file does not
- * exist if we've processed it?
- */
- g_assert (g_file_test (out_path, G_FILE_TEST_EXISTS) == TRUE);
-
- g_free (out_path);
- g_free (out_uri);
- g_free (expected);
-
- /* Remove album art */
- cancellable = g_cancellable_new ();
- media_art_remove_async ("Lanedo",
- "",
- G_PRIORITY_DEFAULT,
- G_OBJECT (process),
- cancellable,
- test_mediaart_remove_cb,
- file);
-
- g_object_unref (cancellable);
- g_free (path);
+ file = g_file_new_for_path (path);
+ g_free (path);
+
+ media_art_process_buffer_async (process,
+ MEDIA_ART_ALBUM,
+ MEDIA_ART_PROCESS_FLAGS_NONE,
+ file,
+ buffer,
+ length,
+ mime,
+ NULL, /* album */
+ "Lanedo", /* title */
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ test_mediaart_process_buffer_cb,
+ ml);
+
+ g_main_loop_run (ml);
+ g_main_loop_unref (ml);
+
+ g_object_unref (file);
+ g_object_unref (cancellable);
g_object_unref (process);
}
static void
+test_mediaart_process_uri_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ gboolean success;
+
+ success = media_art_process_uri_finish (MEDIA_ART_PROCESS (source_object), result, &error);
+ g_assert_false (success);
+ g_assert_error (error, g_io_error_quark(), G_IO_ERROR_NOT_FOUND);
+ g_clear_error (&error);
+}
+
+static void
test_mediaart_process_failures (void)
{
MediaArtProcess *process;
GError *error = NULL;
+ GCancellable *cancellable;
+
+ cancellable = g_cancellable_new ();
- g_test_trap_subprocess ("/mediaart/process_failures/subprocess", 0, 0 /*G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR*/);
+ g_test_trap_subprocess ("/mediaart/process/failures/subprocess", 0, 0 /*G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR*/);
g_test_trap_assert_failed ();
g_test_trap_assert_stderr ("*assertion 'uri != NULL' failed*");
@@ -359,16 +451,16 @@ test_mediaart_process_failures (void)
g_assert_no_error (error);
/* Test: invalid file */
- g_assert (!media_art_process_uri (process,
- MEDIA_ART_ALBUM,
- MEDIA_ART_PROCESS_FLAGS_NONE,
- "file:///invalid/path.png",
- "Foo", /* album */
- "Bar", /* title */
- &error));
-
- g_assert_error (error, g_io_error_quark(), G_IO_ERROR_NOT_FOUND);
- g_clear_error (&error);
+ media_art_process_uri_async (process,
+ MEDIA_ART_ALBUM,
+ MEDIA_ART_PROCESS_FLAGS_NONE,
+ "file:///invalid/path.png",
+ "Foo", /* album */
+ "Bar", /* title */
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ test_mediaart_process_uri_cb,
+ NULL);
/* Test: Invalid mime type */
/* g_assert (!media_art_process_uri (process, */
@@ -379,6 +471,7 @@ test_mediaart_process_failures (void)
/* MEDIA_ART_ALBUM, */
/* "Foo", /\* album *\/ */
/* "Bar", /\* title *\/ */
+ /* NULL, */
/* &error)); */
/* g_message ("code:%d, domain:%d, error:'%s'\n", error->code, error->domain, error->message); */
@@ -401,6 +494,7 @@ test_mediaart_process_failures_subprocess (void)
NULL,
"Foo", /* album */
"Bar", /* title */
+ NULL,
&error));
g_assert_no_error (error);
@@ -412,18 +506,16 @@ main (int argc, char **argv)
{
const gchar *cache_home_originally;
const gchar *test_dir;
- gchar *dir;
+ gchar *dir;
gint success;
gint i;
- g_test_init (&argc, &argv, NULL);
+ g_test_init (&argc, &argv, NULL);
test_dir = g_test_get_dir (G_TEST_BUILT);
cache_home_originally = g_getenv ("XDG_CACHE_HOME");
g_setenv ("XDG_CACHE_HOME", test_dir, TRUE);
- g_test_add ("/mediaart/new", TestInfo, NULL, setup, test_mediaart_new, teardown);
-
for (i = 0; strip_test_cases[i].test_name; i++) {
gchar *testpath;
@@ -432,8 +524,8 @@ main (int argc, char **argv)
g_free (testpath);
}
- g_test_add_func ("/mediaart/stripping_failures", test_mediaart_stripping_failures);
- g_test_add_func ("/mediaart/stripping_failures/subprocess", test_mediaart_stripping_failures_subprocess);
+ g_test_add_func ("/mediaart/stripping_failures", test_mediaart_stripping_failures);
+ g_test_add_func ("/mediaart/stripping_failures/subprocess", test_mediaart_stripping_failures_subprocess);
for (i = 0; location_test_cases[i].test_name; i++) {
gchar *testpath;
@@ -443,25 +535,26 @@ main (int argc, char **argv)
g_free (testpath);
}
- g_test_add_func ("/mediaart/location_null", test_mediaart_location_null);
- g_test_add_func ("/mediaart/location_path", test_mediaart_location_path);
- g_test_add_func ("/mediaart/embedded_mp3", test_mediaart_embedded_mp3);
- g_test_add_func ("/mediaart/process_buffer", test_mediaart_process_buffer);
- g_test_add_func ("/mediaart/process_failures", test_mediaart_process_failures);
- g_test_add_func ("/mediaart/process_failures/subprocess", test_mediaart_process_failures_subprocess);
+ g_test_add_func ("/mediaart/location_null", test_mediaart_location_null);
+ g_test_add_func ("/mediaart/location_path", test_mediaart_location_path);
+ g_test_add_func ("/mediaart/process/new", test_mediaart_process_new);
+ g_test_add_func ("/mediaart/process/file", test_mediaart_process_file);
+ g_test_add_func ("/mediaart/process/buffer", test_mediaart_process_buffer);
+ g_test_add_func ("/mediaart/process/failures", test_mediaart_process_failures);
+ g_test_add_func ("/mediaart/process/failures/subprocess", test_mediaart_process_failures_subprocess);
- success = g_test_run ();
+ success = g_test_run ();
- /* Clean up */
+ /* Clean up */
dir = g_build_filename (g_get_user_cache_dir (), "media-art", NULL);
g_rmdir (dir);
g_free (dir);
- if (cache_home_originally) {
- g_setenv ("XDG_CACHE_HOME", cache_home_originally, TRUE);
- } else {
- g_unsetenv ("XDG_CACHE_HOME");
- }
+ if (cache_home_originally) {
+ g_setenv ("XDG_CACHE_HOME", cache_home_originally, TRUE);
+ } else {
+ g_unsetenv ("XDG_CACHE_HOME");
+ }
- return success;
+ return success;
}