summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartyn Russell <martyn@lanedo.com>2014-07-28 09:25:22 +0100
committerMartyn Russell <martyn@lanedo.com>2014-07-28 09:25:22 +0100
commitf868869ff93c56b4d5df0bcd00393adcb03af7a0 (patch)
tree8b503c859accd2e85f08374be51b7676041198f2
parentf7317f8fdc21e357393e355e937d98a1b1a769c1 (diff)
parent23f3c73c3c3153b670c36b4f74c2e57665f7f075 (diff)
downloadlibmediaart-f868869ff93c56b4d5df0bcd00393adcb03af7a0.tar.gz
Merge branch 'api-cleanup'
-rw-r--r--configure.ac5
-rw-r--r--docs/reference/libmediaart/Makefile.am9
-rw-r--r--docs/reference/libmediaart/libmediaart-docs.sgml1
-rw-r--r--docs/reference/libmediaart/libmediaart-sections.txt33
-rw-r--r--libmediaart/cache.c43
-rw-r--r--libmediaart/extract.c1200
-rw-r--r--libmediaart/extract.h124
-rw-r--r--libmediaart/extractdummy.c80
-rw-r--r--libmediaart/extractgeneric.h17
-rw-r--r--libmediaart/extractpixbuf.c75
-rw-r--r--libmediaart/extractqt.cpp23
-rw-r--r--libmediaart/storage.c22
-rw-r--r--m4/.gitignore1
-rw-r--r--m4/attributes.m4288
-rw-r--r--m4/local.m4258
-rw-r--r--tests/LanedoIconHKS43-64².pngbin1560 -> 0 bytes
-rw-r--r--tests/mediaarttest.c157
17 files changed, 1734 insertions, 602 deletions
diff --git a/configure.ac b/configure.ac
index 95a3b73..a0f7fb3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -96,6 +96,8 @@ AC_SUBST(LT_REVISION)
AC_SUBST(LT_AGE)
AC_SUBST(LT_CURRENT_MINUS_AGE)
+IDT_COMPILE_WARNINGS
+
# Checks for programs.
AC_PROG_CXX
AC_PROG_AWK
@@ -151,6 +153,9 @@ PKG_CHECK_MODULES(LIBMEDIAART, [$LIBMEDIAART_REQUIRED])
GLIB_GENMARSHAL=`$PKG_CONFIG glib-2.0 --variable=glib_genmarshal`
AC_SUBST(GLIB_GENMARSHAL)
+GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`"
+AC_SUBST(GLIB_PREFIX)
+
####################################################################
# General CFLAGS/LIBS
####################################################################
diff --git a/docs/reference/libmediaart/Makefile.am b/docs/reference/libmediaart/Makefile.am
index 60ab37f..6424e10 100644
--- a/docs/reference/libmediaart/Makefile.am
+++ b/docs/reference/libmediaart/Makefile.am
@@ -15,14 +15,14 @@ SCAN_OPTIONS=
# SCANGOBJ_OPTIONS=--type-init-func="gtk_type_init(0)"
# The directory containing the source code. Relative to $(srcdir)
-DOC_SOURCE_DIR=../../../libmediaart
+DOC_SOURCE_DIR=$(top_srcdir)/libmediaart
# Used for dependencies
HFILE_GLOB=$(top_srcdir)/libmediaart/*.h
CFILE_GLOB=$(top_srcdir)/libmediaart/*.c
# Header files to ignore when scanning
-IGNORE_HFILES=
+IGNORE_HFILES=$(top_srcdir)/libmediaart/storage.h
# CFLAGS and LDFLAGS for compiling scan program. Only needed
# if $(DOC_MODULE).types is non-empty.
@@ -49,7 +49,10 @@ expand_content_files =
HTML_IMAGES =
# Extra options to supply to gtkdoc-fixref
-FIXXREF_OPTIONS=
+FIXXREF_OPTIONS=\
+ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gobject \
+ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \
+ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gio
include $(top_srcdir)/gtk-doc.make
diff --git a/docs/reference/libmediaart/libmediaart-docs.sgml b/docs/reference/libmediaart/libmediaart-docs.sgml
index 47e7abe..38a5021 100644
--- a/docs/reference/libmediaart/libmediaart-docs.sgml
+++ b/docs/reference/libmediaart/libmediaart-docs.sgml
@@ -32,6 +32,7 @@
<title>Reference</title>
<xi:include href="xml/extract.xml"/>
<xi:include href="xml/cache.xml"/>
+ <xi:include href="xml/plugins.xml"/>
</chapter>
</part>
diff --git a/docs/reference/libmediaart/libmediaart-sections.txt b/docs/reference/libmediaart/libmediaart-sections.txt
index cca4ecf..77bd1f7 100644
--- a/docs/reference/libmediaart/libmediaart-sections.txt
+++ b/docs/reference/libmediaart/libmediaart-sections.txt
@@ -1,30 +1,45 @@
<SECTION>
<FILE>cache</FILE>
-media_art_get_file
media_art_get_path
+media_art_get_file
media_art_remove
media_art_strip_invalid_entities
</SECTION>
<SECTION>
<FILE>extract</FILE>
+<TITLE>MediaArtProcess</TITLE>
MediaArtType
-media_art_init
-media_art_shutdown
+MediaArtError
+MediaArtProcessFlags
+MediaArtProcess
+MediaArtProcessClass
+media_art_error_quark
+media_art_process_get_type
+media_art_process_new
+media_art_process_uri
media_art_process_file
-media_art_process
+media_art_process_buffer
+<SUBSECTION Standard>
+MEDIA_ART_IS_PROCESS
+MEDIA_ART_IS_PROCESS_CLASS
+MEDIA_ART_PROCESS
+MEDIA_ART_PROCESS_CLASS
+MEDIA_ART_PROCESS_GET_CLASS
+MEDIA_ART_TYPE_PROCESS
</SECTION>
<SECTION>
-<FILE>extractgeneric</FILE>
-media_art_buffer_to_jpeg
-media_art_file_to_jpeg
+<FILE>plugins</FILE>
media_art_plugin_init
media_art_plugin_shutdown
+media_art_file_to_jpeg
+media_art_buffer_to_jpeg
</SECTION>
<SECTION>
-<FILE>mediaart</FILE>
-
+<FILE>marshal</FILE>
+media_art_marshal_VOID__STRING_STRING
+media_art_marshal_VOID__STRING_STRING_STRING_BOOLEAN_BOOLEAN
</SECTION>
diff --git a/libmediaart/cache.c b/libmediaart/cache.c
index 7249b14..82286a4 100644
--- a/libmediaart/cache.c
+++ b/libmediaart/cache.c
@@ -29,22 +29,25 @@
/**
* SECTION:cache
- * @title: Caching and Management
- * @short_description: Caching and management of stored media art.
+ * @title: Cache
+ * @short_description: Caching and lookup of stored media art.
* @include: libmediaart/mediaart.h
*
- * These functions give you access to the media art that has been extracted
- * and saved in the user's XDG_CACHE_HOME directory.
+ * These functions give you access to the media art that has been
+ * extracted and saved in the user's XDG_CACHE_HOME directory (usually
+ * ~/.cache/media-art/).
*
* To find the media art for a given media file, use the function
- * media_art_get_file() (you can also use media_art_get_path(), which does the
- * same thing but for path strings instead of #GFile objects).
+ * media_art_get_file() (you can also use media_art_get_path(), which
+ * does the same thing but for path strings instead of #GFile
+ * objects).
*
- * If media art for the file is not found in the cache, these functions will
- * return %NULL. You may find some embedded media art upon loading the file,
- * and you can use media_art_process() to convert it to the correct format and
- * save it in the cache for next time. The media_art_process() function also
- * supports searching for external media art images using a basic heuristic.
+ * If media art for the file is not found in the cache, these
+ * functions will return %NULL. You may find some embedded media art
+ * upon loading the file, and you can use media_art_process_buffer()
+ * to convert it to the correct format and save it in the cache for
+ * next time. The media_art_process_file() function also supports
+ * searching for external media art images using a basic heuristic.
**/
static gboolean
@@ -271,9 +274,7 @@ media_art_get_file (const gchar *artist,
*local_file = NULL;
}
- if (!artist && !title) {
- return;
- }
+ g_return_if_fail (artist != NULL || title != NULL);
if (artist) {
artist_stripped = media_art_strip_invalid_entities (artist);
@@ -359,8 +360,8 @@ media_art_get_file (const gchar *artist,
* @local_uri: (out) (transfer full) (allow-none): the location to store the
* local uri or %NULL
*
- * Get the path to media art for a given resource. Newly allocated data in
- * @path and @local_uri must be freed with g_free().
+ * Get the path to media art for a given resource. Newly allocated
+ * data returned in @path and @local_uri must be freed with g_free().
*
* Since: 0.2.0
*/
@@ -417,7 +418,7 @@ media_art_remove_foreach (gpointer data,
* @artist: artist the media art belongs to
* @album: (allow-none): album the media art belongs or %NULL
*
- * Removes media art for given album/artist/etc provided.
+ * Removes media art for given album/artist provided.
*
* Returns: #TRUE on success, otherwise #FALSE.
*
@@ -470,9 +471,11 @@ media_art_remove (const gchar *artist,
}
/* Add the album path also (to which the symlinks are made) */
- media_art_get_path (NULL, album, "album", NULL, &target, NULL);
- if (target) {
- g_hash_table_replace (table, target, target);
+ if (album) {
+ media_art_get_path (NULL, album, "album", NULL, &target, NULL);
+ if (target) {
+ g_hash_table_replace (table, target, target);
+ }
}
/* Perhaps we should have an internal list of media art files that we made,
diff --git a/libmediaart/extract.c b/libmediaart/extract.c
index e9ff970..7091aac 100644
--- a/libmediaart/extract.c
+++ b/libmediaart/extract.c
@@ -46,7 +46,7 @@
* from a media file and saving it into the media art cache, so that future
* applications can display the media art without having to extract the image
* again. This is done using the media_art_process_file() or
- * media_art_process() functions.
+ * media_art_process_buffer() functions.
*
* Extracting new media art from a file needs to be done by your application.
* Usually, when an application loads a media file any embedded images will be
@@ -56,21 +56,26 @@
*
* The media art cache requires that all images are saved as 'application/jpeg'
* files. Embedded images can be in several formats, and
- * media_art_process_file() and media_art_process() functions will
+ * media_art_process_file() and media_art_process_buffer() functions will
* convert the supplied image data into the correct format if
* necessary. There are multiple backends that can be used for this,
* and you can choose which is used at build time using the library's
* 'configure' script.
*
* If there is no embedded media art in a file,
- * media_art_process_file() and media_art_process() functions will
+ * media_art_process_file() and media_art_process_buffer() functions will
* look in the directory that contains the media file for likely media
* art using a simple heuristic.
- *
- * You must call media_art_init() before using the functions in libmediaart,
- * and call media_art_shutdown() to free the resources it uses.
**/
+typedef struct {
+ gboolean disable_requests;
+
+ GHashTable *media_art_cache;
+ GDBusConnection *connection;
+ Storage *storage;
+} MediaArtProcessPrivate;
+
static const gchar *media_art_type_name[MEDIA_ART_TYPE_COUNT] = {
"invalid",
"album",
@@ -78,6 +83,7 @@ static const gchar *media_art_type_name[MEDIA_ART_TYPE_COUNT] = {
};
typedef struct {
+ MediaArtProcess *process;
gchar *art_path;
gchar *local_uri;
} FileInfo;
@@ -96,16 +102,129 @@ typedef enum {
IMAGE_MATCH_TYPE_COUNT
} ImageMatchType;
-static gboolean initialized = FALSE;
-static gboolean disable_requests;
+static void media_art_queue_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+static void media_art_process_initable_iface_init (GInitableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MediaArtProcess, media_art_process, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
+ media_art_process_initable_iface_init)
+ G_ADD_PRIVATE (MediaArtProcess))
+
+static void
+media_art_process_finalize (GObject *object)
+{
+ MediaArtProcessPrivate *private;
+ MediaArtProcess *process;
+
+ process = MEDIA_ART_PROCESS (object);
+ private = media_art_process_get_instance_private (process);
+
+ if (private->storage) {
+ g_object_unref (private->storage);
+ }
+
+ if (private->connection) {
+ g_object_unref (private->connection);
+ }
+
+ if (private->media_art_cache) {
+ g_hash_table_unref (private->media_art_cache);
+ }
+
+ media_art_plugin_shutdown ();
+
+ G_OBJECT_CLASS (media_art_process_parent_class)->finalize (object);
+}
+
+static gboolean
+media_art_process_initable_init (GInitable *initable,
+ GCancellable *cancellable,
+ GError **error)
+{
+ MediaArtProcessPrivate *private;
+ MediaArtProcess *process;
+ GError *local_error = NULL;
+
+ process = MEDIA_ART_PROCESS (initable);
+ private = media_art_process_get_instance_private (process);
+
+ g_debug ("Initializing media art processing requirements...");
-static GHashTable *media_art_cache;
-static GDBusConnection *connection;
-static Storage *storage;
+ media_art_plugin_init (0);
-static void media_art_queue_cb (GObject *source_object,
- GAsyncResult *res,
- gpointer user_data);
+ /* Cache to know if we have already handled uris */
+ private->media_art_cache = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ NULL);
+
+ /* Signal handler for new album art from the extractor */
+ private->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &local_error);
+
+ if (!private->connection) {
+ g_critical ("Could not connect to the D-Bus session bus, %s",
+ local_error ? local_error->message : "no error given.");
+ g_propagate_error (error, local_error);
+
+ return FALSE;
+ }
+
+ private->storage = storage_new ();
+ if (!private->storage) {
+ g_critical ("Could not start storage module for removable media detection");
+
+ if (error) {
+ *error = g_error_new (media_art_error_quark (),
+ MEDIA_ART_ERROR_NO_STORAGE,
+ "Could not initialize storage module");
+ }
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+media_art_process_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = media_art_process_initable_init;
+}
+
+static void
+media_art_process_class_init (MediaArtProcessClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = media_art_process_finalize;
+}
+
+static void
+media_art_process_init (MediaArtProcess *thumbnailer)
+{
+}
+
+/**
+ * media_art_process_new:
+ * @error: Pointer to potential GLib / MediaArt error, or %NULL
+ *
+ * Initialize a GObject for processing and extracting media art.
+ *
+ * This function initializes cache hash tables, backend plugins,
+ * storage modules used for removable devices and a connection to D-Bus.
+ *
+ * Returns: A new #MediaArtProcess object on success or %NULL if
+ * @error is set. This object must be freed using g_object_unref().
+ *
+ * Since: 0.5.0
+ */
+MediaArtProcess *
+media_art_process_new (GError **error)
+{
+ return g_initable_new (MEDIA_ART_TYPE_PROCESS, NULL, error, NULL);
+}
static GDir *
get_parent_g_dir (const gchar *uri,
@@ -142,7 +261,6 @@ get_parent_g_dir (const gchar *uri,
return dir;
}
-
static gchar *
checksum_for_data (GChecksumType checksum_type,
const guchar *data,
@@ -255,10 +373,11 @@ end:
}
static gboolean
-convert_from_other_format (const gchar *found,
- const gchar *target,
- const gchar *album_path,
- const gchar *artist)
+convert_from_other_format (const gchar *found,
+ const gchar *target,
+ const gchar *album_path,
+ const gchar *artist,
+ GError **error)
{
gboolean retval;
gchar *sum1 = NULL;
@@ -266,18 +385,28 @@ convert_from_other_format (const gchar *found,
target_temp = g_strdup_printf ("%s-tmp", target);
- if (!media_art_file_to_jpeg (found, target_temp)) {
+ if (!media_art_file_to_jpeg (found, target_temp, error)) {
g_free (target_temp);
return FALSE;
}
if (artist == NULL || g_strcmp0 (artist, " ") == 0) {
- if (g_rename (target_temp, album_path) == -1) {
- g_debug ("rename(%s, %s) error: %s",
- target_temp,
- album_path,
- g_strerror (errno));
+ 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));
}
+
+ g_debug ("rename(%s, %s) error: %s",
+ target_temp,
+ album_path,
+ g_strerror (errno));
} else if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
target_temp,
&sum1,
@@ -294,45 +423,77 @@ convert_from_other_format (const gchar *found,
/* If album-space-md5.jpg is the same as found,
* make a symlink */
-
- if (symlink (album_path, target) != 0) {
- g_debug ("symlink(%s, %s) error: %s",
- album_path,
- target,
- g_strerror (errno));
- retval = FALSE;
- } else {
- retval = TRUE;
+ 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_debug ("symlink(%s, %s) error: %s",
+ album_path,
+ target,
+ g_strerror (errno));
+
g_unlink (target_temp);
} else {
/* If album-space-md5.jpg isn't the same as found,
* make a new album-md5-md5.jpg (found -> target) */
-
- if (g_rename (target_temp, album_path) == -1) {
- g_debug ("rename(%s, %s) error: %s",
- target_temp,
- album_path,
- g_strerror (errno));
+ 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));
}
+
+ g_debug ("rename(%s, %s) error: %s",
+ target_temp,
+ album_path,
+ g_strerror (errno));
}
g_free (sum2);
} else {
/* If there's not yet a album-space-md5.jpg, make one,
* and symlink album-md5-md5.jpg to it */
- g_rename (target_temp, album_path);
+ 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));
+ } 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));
+ }
- if (symlink (album_path, target) != 0) {
g_debug ("symlink(%s,%s) error: %s",
- album_path,
- target,
- g_strerror (errno));
- retval = FALSE;
- } else {
- retval = TRUE;
+ album_path,
+ target,
+ g_strerror (errno));
}
}
@@ -530,11 +691,12 @@ media_art_find_by_artist_and_title (const gchar *uri,
}
static gboolean
-media_art_heuristic (const gchar *artist,
- const gchar *title,
- MediaArtType type,
- const gchar *filename_uri,
- const gchar *local_uri)
+get_heuristic (MediaArtType type,
+ const gchar *filename_uri,
+ const gchar *local_uri,
+ const gchar *artist,
+ const gchar *title,
+ GError **error)
{
gchar *art_file_path = NULL;
gchar *album_art_file_path = NULL;
@@ -544,7 +706,10 @@ media_art_heuristic (const gchar *artist,
gboolean retval = FALSE;
if (title == NULL || title[0] == '\0') {
- g_debug ("Unable to fetch media art, no title specified");
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_NO_TITLE,
+ "Title is required, but was not provided, or was empty");
return FALSE;
}
@@ -600,171 +765,186 @@ media_art_heuristic (const gchar *artist,
artist,
title);
- if (art_file_path != NULL) {
- if (g_str_has_suffix (art_file_path, "jpeg") ||
- g_str_has_suffix (art_file_path, "jpg")) {
+ if (!art_file_path) {
+ // FIXME: Do we GError here?
- gboolean is_jpeg = FALSE;
- gchar *sum1 = NULL;
-
- if (type != MEDIA_ART_ALBUM ||
- (artist == NULL || g_strcmp0 (artist, " ") == 0)) {
- GFile *art_file;
- GFile *target_file;
- GError *err = NULL;
-
- g_debug ("Album art (JPEG) found in same directory being used:'%s'",
- art_file_path);
-
- target_file = g_file_new_for_path (target);
- art_file = g_file_new_for_path (art_file_path);
+ g_free (art_file_path);
+ g_free (album_art_file_path);
- g_file_copy (art_file,
- target_file,
- 0,
- NULL,
- NULL,
- NULL,
- &err);
+ g_free (target);
+ g_free (artist_stripped);
+ g_free (title_stripped);
- if (err) {
- g_debug ("%s", err->message);
- g_clear_error (&err);
- }
+ return FALSE;
+ }
- g_object_unref (art_file);
- g_object_unref (target_file);
- } else if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
- art_file_path,
- &sum1,
- TRUE,
- &is_jpeg)) {
- /* Avoid duplicate artwork for each track in an album */
- media_art_get_path (NULL,
- title_stripped,
- media_art_type_name [type],
- NULL,
- &album_art_file_path,
- NULL);
+ if (g_str_has_suffix (art_file_path, "jpeg") ||
+ g_str_has_suffix (art_file_path, "jpg")) {
+ gboolean is_jpeg = FALSE;
+ gchar *sum1 = NULL;
+
+ if (type != MEDIA_ART_ALBUM ||
+ (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);
+
+ target_file = g_file_new_for_path (target);
+ art_file = g_file_new_for_path (art_file_path);
+
+ g_file_copy (art_file,
+ target_file,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ &local_error);
+
+ if (local_error) {
+ g_debug ("%s", local_error->message);
+ g_propagate_error (error, local_error);
+ }
- if (is_jpeg) {
- gchar *sum2 = NULL;
-
- g_debug ("Album art (JPEG) found in same directory being used:'%s'", art_file_path);
-
- if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
- album_art_file_path,
- &sum2,
- FALSE,
- NULL)) {
- if (g_strcmp0 (sum1, sum2) == 0) {
- /* If album-space-md5.jpg is the same as found,
- * make a symlink */
-
- if (symlink (album_art_file_path, target) != 0) {
- g_debug ("symlink(%s, %s) error: %s",
- album_art_file_path,
- target,
- g_strerror (errno));
- retval = FALSE;
- } else {
- retval = TRUE;
- }
- } else {
- GFile *art_file;
- GFile *target_file;
- GError *err = NULL;
-
- /* If album-space-md5.jpg isn't the same as found,
- * make a new album-md5-md5.jpg (found -> target) */
-
- target_file = g_file_new_for_path (target);
- art_file = g_file_new_for_path (art_file_path);
- retval = g_file_copy (art_file,
- target_file,
- 0,
- NULL,
- NULL,
- NULL,
- &err);
- if (err) {
- g_debug ("%s", err->message);
- g_clear_error (&err);
- }
- g_object_unref (art_file);
- g_object_unref (target_file);
+ g_object_unref (art_file);
+ g_object_unref (target_file);
+ } else if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
+ art_file_path,
+ &sum1,
+ TRUE,
+ &is_jpeg)) {
+ /* Avoid duplicate artwork for each track in an album */
+ media_art_get_path (NULL,
+ title_stripped,
+ media_art_type_name [type],
+ NULL,
+ &album_art_file_path,
+ NULL);
+
+ if (is_jpeg) {
+ gchar *sum2 = NULL;
+
+ g_debug ("Album art (JPEG) found in same directory being used:'%s'", art_file_path);
+
+ if (file_get_checksum_if_exists (G_CHECKSUM_MD5,
+ album_art_file_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_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",
+ album_art_file_path,
+ target,
+ g_strerror (errno));
}
- g_free (sum2);
+
+ g_debug ("symlink(%s, %s) error: %s",
+ album_art_file_path,
+ target,
+ g_strerror (errno));
} else {
GFile *art_file;
- GFile *album_art_file;
- GError *err = NULL;
-
- /* If there's not yet a album-space-md5.jpg, make one,
- * and symlink album-md5-md5.jpg to it */
+ GFile *target_file;
- album_art_file = g_file_new_for_path (album_art_file_path);
+ /* If album-space-md5.jpg isn't the same as found,
+ * make a new album-md5-md5.jpg (found -> target) */
+ target_file = g_file_new_for_path (target);
art_file = g_file_new_for_path (art_file_path);
retval = g_file_copy (art_file,
- album_art_file,
+ target_file,
0,
NULL,
NULL,
NULL,
- &err);
-
- if (err == NULL) {
- if (symlink (album_art_file_path, target) != 0) {
- g_debug ("symlink(%s, %s) error: %s",
- album_art_file_path, target,
- g_strerror (errno));
- retval = FALSE;
- } else {
- retval = TRUE;
- }
- } else {
- g_debug ("%s", err->message);
- g_clear_error (&err);
- retval = FALSE;
- }
+ error);
- g_object_unref (album_art_file);
g_object_unref (art_file);
+ g_object_unref (target_file);
}
+
+ g_free (sum2);
} else {
- g_debug ("Album art found in same directory but not a real JPEG file (trying to convert): '%s'", art_file_path);
- retval = convert_from_other_format (art_file_path,
- target,
- album_art_file_path,
- artist);
- }
+ GFile *art_file;
+ GFile *album_art_file;
+
+ /* 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);
+ art_file = g_file_new_for_path (art_file_path);
+ retval = g_file_copy (art_file,
+ album_art_file,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ error);
+
+ if (retval) {
+ 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",
+ album_art_file_path,
+ target,
+ g_strerror (errno));
+ }
- g_free (sum1);
+ g_debug ("symlink(%s, %s) error: %s",
+ album_art_file_path, target,
+ g_strerror (errno));
+ }
+
+ g_object_unref (album_art_file);
+ g_object_unref (art_file);
+ }
} else {
- /* Can't read contents of the cover.jpg file ... */
- retval = FALSE;
- }
- } else if (g_str_has_suffix (art_file_path, "png")) {
- if (!album_art_file_path) {
- media_art_get_path (NULL,
- title_stripped,
- media_art_type_name[type],
- NULL,
- &album_art_file_path,
- NULL);
+ g_debug ("Album art found in same directory but not a real JPEG file (trying to convert): '%s'", art_file_path);
+ retval = convert_from_other_format (art_file_path,
+ target,
+ album_art_file_path,
+ artist,
+ error);
}
- g_debug ("Album art (PNG) found in same directory being used:'%s'", art_file_path);
- retval = convert_from_other_format (art_file_path,
- target,
- album_art_file_path,
- artist);
+ g_free (sum1);
+ } else {
+ /* Can't read contents of the cover.jpg file ... */
+ retval = FALSE;
+ }
+ } else if (g_str_has_suffix (art_file_path, "png")) {
+ if (!album_art_file_path) {
+ media_art_get_path (NULL,
+ title_stripped,
+ media_art_type_name[type],
+ NULL,
+ &album_art_file_path,
+ NULL);
}
- g_free (art_file_path);
- g_free (album_art_file_path);
+ g_debug ("Album art (PNG) found in same directory being used:'%s'", art_file_path);
+ retval = convert_from_other_format (art_file_path,
+ target,
+ album_art_file_path,
+ artist,
+ error);
}
+ g_free (art_file_path);
+ g_free (album_art_file_path);
+
g_free (target);
g_free (artist_stripped);
g_free (title_stripped);
@@ -777,8 +957,6 @@ is_buffer_jpeg (const gchar *mime,
const unsigned char *buffer,
size_t buffer_len)
{
- gboolean is_jpeg;
-
if (buffer == NULL || buffer_len < 3) {
return FALSE;
}
@@ -798,21 +976,19 @@ is_buffer_jpeg (const gchar *mime,
}
static gboolean
-media_art_set (const unsigned char *buffer,
- size_t len,
- const gchar *mime,
- MediaArtType type,
- const gchar *artist,
- const gchar *title)
+media_art_set (const unsigned char *buffer,
+ size_t len,
+ const gchar *mime,
+ MediaArtType type,
+ const gchar *artist,
+ const gchar *title,
+ GError **error)
{
gchar *local_path;
gchar *album_path;
gchar *md5_album = NULL;
gchar *md5_tmp = NULL;
gchar *temp;
- const gchar *save_path = NULL;
- gboolean save_buffer = FALSE;
- gboolean need_symlink = FALSE;
gboolean retval = FALSE;
g_return_val_if_fail (type > MEDIA_ART_NONE && type < MEDIA_ART_TYPE_COUNT, FALSE);
@@ -854,7 +1030,7 @@ 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);
+ retval = media_art_buffer_to_jpeg (buffer, len, mime, local_path, error);
g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s'", len, local_path);
g_free (local_path);
@@ -875,21 +1051,29 @@ media_art_set (const unsigned char *buffer,
if (!g_file_test (album_path, G_FILE_TEST_EXISTS)) {
retval = TRUE;
- if (media_art_buffer_to_jpeg (buffer, len, mime, album_path)) {
+ if (media_art_buffer_to_jpeg (buffer, len, mime, album_path, error)) {
g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s'", len, album_path);
/* If album-space-md5.jpg doesn't
* exist, make one and make a symlink
* to album-md5-md5.jpg
*/
- if (symlink (album_path, local_path) != 0) {
- g_debug ("Creating symlink '%s' --> '%s', %s",
- album_path,
- local_path,
- retval ? g_strerror (errno) : "no error given");
+ retval = symlink (album_path, local_path) == 0;
- retval = FALSE;
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_SYMLINK_FAILED,
+ "Could not link '%s' to '%s': %s",
+ album_path,
+ local_path,
+ g_strerror (errno));
}
+
+ g_debug ("Creating symlink '%s' --> '%s', %s",
+ album_path,
+ local_path,
+ retval ? g_strerror (errno) : "no error given");
}
g_free (album_path);
@@ -926,6 +1110,17 @@ media_art_set (const unsigned char *buffer,
*/
if (g_strcmp0 (md5_data, md5_album) == 0) {
retval = symlink (album_path, local_path) == 0;
+
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_SYMLINK_FAILED,
+ "Could not link '%s' to '%s': %s",
+ album_path,
+ local_path,
+ g_strerror (errno));
+ }
+
g_debug ("Creating symlink '%s' --> '%s', %s",
album_path,
local_path,
@@ -934,7 +1129,7 @@ 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);
+ retval = media_art_buffer_to_jpeg (buffer, len, mime, local_path, error);
g_debug ("Saving buffer to jpeg (%ld bytes) --> '%s'", len, local_path);
}
@@ -955,7 +1150,7 @@ media_art_set (const unsigned char *buffer,
temp = g_strdup_printf ("%s-tmp", album_path);
/* If buffer isn't a JPEG */
- if (!media_art_buffer_to_jpeg (buffer, len, mime, temp)) {
+ if (!media_art_buffer_to_jpeg (buffer, len, mime, temp, error)) {
/* Can't read temp file ... */
g_unlink (temp);
@@ -977,6 +1172,17 @@ media_art_set (const unsigned char *buffer,
* buffer, make a symlink to album-md5-md5.jpg
*/
retval = symlink (album_path, local_path) == 0;
+
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_SYMLINK_FAILED,
+ "Could not link '%s' to '%s': %s",
+ album_path,
+ local_path,
+ g_strerror (errno));
+ }
+
g_debug ("Creating symlink '%s' --> '%s', %s",
album_path,
local_path,
@@ -986,6 +1192,17 @@ media_art_set (const unsigned char *buffer,
* buffer, make a new album-md5-md5.jpg
*/
retval = g_rename (temp, local_path) == 0;
+
+ if (!retval) {
+ g_set_error (error,
+ media_art_error_quark (),
+ MEDIA_ART_ERROR_RENAME_FAILED,
+ "Could not rename '%s' to '%s': %s",
+ temp,
+ local_path,
+ g_strerror (errno));
+ }
+
g_debug ("Renaming temp file '%s' --> '%s', %s",
temp,
local_path,
@@ -1007,13 +1224,15 @@ media_art_set (const unsigned char *buffer,
}
static FileInfo *
-file_info_new (const gchar *local_uri,
- const gchar *art_path)
+file_info_new (MediaArtProcess *process,
+ const gchar *local_uri,
+ const gchar *art_path)
{
FileInfo *fi;
fi = g_slice_new (FileInfo);
+ fi->process = g_object_ref (process);
fi->local_uri = g_strdup (local_uri);
fi->art_path = g_strdup (art_path);
@@ -1023,23 +1242,33 @@ file_info_new (const gchar *local_uri,
static void
file_info_free (FileInfo *fi)
{
+ if (!fi) {
+ return;
+ }
+
g_free (fi->local_uri);
g_free (fi->art_path);
+ g_object_unref (fi->process);
g_slice_free (FileInfo, fi);
}
static void
-media_art_request_download (MediaArtType type,
- const gchar *album,
- const gchar *artist,
- const gchar *local_uri,
- const gchar *art_path)
+media_art_request_download (MediaArtProcess *process,
+ MediaArtType type,
+ const gchar *album,
+ const gchar *artist,
+ const gchar *local_uri,
+ const gchar *art_path)
{
- if (connection) {
+ MediaArtProcessPrivate *private;
+
+ private = media_art_process_get_instance_private (process);
+
+ if (private->connection) {
FileInfo *info;
- if (disable_requests) {
+ if (private->disable_requests) {
return;
}
@@ -1047,9 +1276,9 @@ media_art_request_download (MediaArtType type,
return;
}
- info = file_info_new (local_uri, art_path);
+ info = file_info_new (process, local_uri, art_path);
- g_dbus_connection_call (connection,
+ g_dbus_connection_call (private->connection,
ALBUMARTER_SERVICE,
ALBUMARTER_PATH,
ALBUMARTER_INTERFACE,
@@ -1069,14 +1298,18 @@ media_art_request_download (MediaArtType type,
}
static void
-media_art_copy_to_local (const gchar *filename,
- const gchar *local_uri)
+media_art_copy_to_local (MediaArtProcess *process,
+ const gchar *filename,
+ const gchar *local_uri)
{
+ MediaArtProcessPrivate *private;
GSList *roots, *l;
gboolean on_removable_device = FALSE;
guint flen;
- roots = storage_get_device_roots (storage, STORAGE_REMOVABLE, FALSE);
+ private = media_art_process_get_instance_private (process);
+
+ roots = storage_get_device_roots (private->storage, STORAGE_REMOVABLE, FALSE);
flen = strlen (filename);
for (l = roots; l; l = l->next) {
@@ -1133,17 +1366,20 @@ media_art_queue_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
+ MediaArtProcessPrivate *private;
GError *error = NULL;
FileInfo *fi;
GVariant *v;
fi = user_data;
+ private = media_art_process_get_instance_private (fi->process);
+
v = g_dbus_connection_call_finish ((GDBusConnection *) source_object, res, &error);
if (error) {
if (error->code == G_DBUS_ERROR_SERVICE_UNKNOWN) {
- disable_requests = TRUE;
+ private->disable_requests = TRUE;
} else {
g_warning ("%s", error->message);
}
@@ -1154,10 +1390,11 @@ media_art_queue_cb (GObject *source_object,
g_variant_unref (v);
}
- if (storage &&
+ if (private->storage &&
fi->art_path &&
g_file_test (fi->art_path, G_FILE_TEST_EXISTS)) {
- media_art_copy_to_local (fi->art_path,
+ media_art_copy_to_local (fi->process,
+ fi->art_path,
fi->local_uri);
}
@@ -1165,80 +1402,23 @@ media_art_queue_cb (GObject *source_object,
}
/**
- * media_art_init:
- *
- * Initialize libmediaart.
+ * media_art_error_quark:
*
- * This function initializes cache hash tables, backend plugins,
- * storage modules used for removable devices and connections to D-Bus.
- *
- * Returns: %TRUE if initialisation was successful, %FALSE otherwise.
+ * Returns: the #GQuark used to identify media art errors in
+ * GError structures.
*
* Since: 0.2.0
- */
-gboolean
-media_art_init (void)
-{
- GError *error = NULL;
-
- g_return_val_if_fail (initialized == FALSE, FALSE);
-
- media_art_plugin_init (0);
-
- /* Cache to know if we have already handled uris */
- media_art_cache = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify) g_free,
- NULL);
-
- /* Signal handler for new album art from the extractor */
- connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
-
- if (!connection) {
- g_critical ("Could not connect to the D-Bus session bus, %s",
- error ? error->message : "no error given.");
- g_clear_error (&error);
- return FALSE;
- }
-
- storage = storage_new ();
- if (!storage) {
- g_critical ("Could not start storage module for removable media detection");
- return FALSE;
- }
-
- initialized = TRUE;
-
- return TRUE;
-}
-
-/**
- * media_art_shutdown:
- *
- * Clean up and free the resources created and mentioned in media_art_init().
- *
- * Since: 0.2.0
- */
-void
-media_art_shutdown (void)
+ **/
+GQuark
+media_art_error_quark (void)
{
- g_return_if_fail (initialized == TRUE);
-
- if (storage) {
- g_object_unref (storage);
- }
+ static GQuark error_quark = 0;
- if (connection) {
- g_object_unref (connection);
+ if (G_UNLIKELY (error_quark == 0)) {
+ error_quark = g_quark_from_static_string ("media-art-error-quark");
}
- if (media_art_cache) {
- g_hash_table_unref (media_art_cache);
- }
-
- media_art_plugin_shutdown ();
-
- initialized = FALSE;
+ return error_quark;
}
static void
@@ -1253,27 +1433,21 @@ set_mtime (const gchar *filename,
static
guint64
-get_mtime (GFile *file)
+get_mtime (GFile *file,
+ GError **error)
{
GFileInfo *info;
- GError *error = NULL;
- guint64 mtime;
+ GError *local_error = NULL;
+ guint64 mtime;
info = g_file_query_info (file,
G_FILE_ATTRIBUTE_TIME_MODIFIED,
G_FILE_QUERY_INFO_NONE,
NULL,
- &error);
+ &local_error);
- if (G_UNLIKELY (error)) {
- gchar *uri;
-
- uri = g_file_get_uri (file);
- g_message ("Could not get mtime for '%s': %s",
- uri,
- error->message);
- g_free (uri);
- g_error_free (error);
+ if (G_UNLIKELY (local_error != NULL)) {
+ g_propagate_error (error, local_error);
mtime = 0;
} else {
mtime = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
@@ -1283,191 +1457,327 @@ get_mtime (GFile *file)
return mtime;
}
-guint64
-get_mtime_by_path (const gchar *path)
-{
- GFile *file;
- guint64 mtime;
-
- g_return_val_if_fail (path != NULL, 0);
-
- file = g_file_new_for_path (path);
-
- mtime = get_mtime (file);
-
- g_object_unref (file);
-
- return mtime;
-}
-
-
-guint64
-get_mtime_by_uri (const gchar *uri)
+static gchar *
+get_heuristic_for_parent_path (GFile *file,
+ MediaArtType type,
+ const gchar *artist,
+ const gchar *title)
{
- GFile *file;
- guint64 mtime;
+ gchar *key;
+ gchar *parent_path = NULL;
+ GFile *parent;
- g_return_val_if_fail (uri != NULL, 0);
+ if (!file) {
+ return NULL;
+ }
- file = g_file_new_for_uri (uri);
+ parent = g_file_get_parent (file);
+ if (parent) {
+ parent_path = g_file_get_path (parent);
+ g_object_unref (parent);
+ }
- mtime = get_mtime (file);
+ /* Just used for caching in our hash table */
+ key = g_strdup_printf ("%s:%s:%s:%s",
+ parent_path ? parent_path : "",
+ media_art_type_name[type],
+ artist ? artist : "",
+ title ? title : "");
- g_object_unref (file);
+ g_free (parent_path);
- return mtime;
+ return key;
}
-
/**
- * media_art_process_file:
+ * media_art_process_buffer:
+ * @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
- * @type: The type of media
- * @artist: The media file artist name, or %NULL
- * @title: The media file title, or %NULL
- * @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
*
- * Processes a media file. If you have extracted any embedded media art and
- * passed this in as @buffer, the image data will be converted to the correct
- * format and saved in the media art cache.
- *
- * If @buffer is %NULL, libmediaart will search the parent directory of @file
- * for image files that are likely to be media art for @file, and if one is
- * found it will be saved in the media art cache.
+ * Processes a memory buffer represented by @buffer and @len. If you
+ * have extracted any embedded media art and passed this in as
+ * @buffer, the image data will be converted to the correct format and
+ * saved in the media art cache.
*
* If @file is on a removable filesystem, the media art file will be saved in a
* cache on the removable file system rather than on the host machine.
*
- * Returns: #TRUE if the file could be processed.
+ * Returns: %TRUE if @file could be processed or %FALSE if @error is set.
*
- * Since: 0.2.0
+ * Since: 0.5.0
*/
gboolean
-media_art_process_file (const guchar *buffer,
- gsize len,
- const gchar *mime,
- MediaArtType type,
- const gchar *artist,
- const gchar *title,
- GFile *file)
+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)
{
GFile *cache_art_file, *local_art_file;
- gchar *art_path, *uri;
- gchar *local_art_uri = NULL;
- gboolean processed = TRUE, a_exists, created = FALSE;
- guint64 mtime, a_mtime = 0;
+ GError *local_error = NULL;
+ gchar *cache_art_path, *uri;
+ gboolean processed, created;
+ guint64 mtime, cache_mtime = 0;
+ g_return_val_if_fail (MEDIA_ART_IS_PROCESS (process), FALSE);
g_return_val_if_fail (type > MEDIA_ART_NONE && type < MEDIA_ART_TYPE_COUNT, FALSE);
- g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (G_IS_FILE (related_file), FALSE);
+ g_return_val_if_fail (buffer != NULL, FALSE);
+ g_return_val_if_fail (len < 0, FALSE);
- uri = g_file_get_uri (file);
- g_debug ("Processing media art: artist:'%s', title:'%s', type:'%s', uri:'%s'. Buffer is %ld bytes, mime:'%s'",
+ processed = created = FALSE;
+
+ uri = g_file_get_uri (related_file);
+ g_debug ("Processing media art: artist:'%s', title:'%s', type:'%s', uri:'%s', flags:0x%.8x. Buffer is %ld bytes, mime:'%s'",
artist ? artist : "",
title ? title : "",
media_art_type_name[type],
uri,
+ flags,
(long int) len,
mime);
- mtime = get_mtime (file);
+ mtime = get_mtime (related_file, &local_error);
+ if (local_error != NULL) {
+ g_debug ("Could not get mtime for related file '%s': %s",
+ uri,
+ local_error->message);
+ g_propagate_error (error, local_error);
+ g_free (uri);
+
+ return FALSE;
+ }
media_art_get_file (artist,
title,
media_art_type_name[type],
- file,
+ related_file,
&cache_art_file,
&local_art_file);
- if (!cache_art_file) {
- g_debug ("Album art path could not be obtained, not processing any further");
+ cache_mtime = get_mtime (cache_art_file, &local_error);
+
+ if (local_error &&
+ local_error->domain == g_io_error_quark () &&
+ local_error->code == G_IO_ERROR_NOT_FOUND) {
+ /* cache_art_file not existing is the only error we
+ * accept here, anything else and we return.
+ */
+ gchar *path;
+
+ path = g_file_get_uri (cache_art_file);
+ g_debug ("Cache for media art did not exist (%s)",
+ path);
+ g_free (path);
+ g_clear_error (&local_error);
+ } else if (local_error) {
+ g_free (uri);
+
+ uri = g_file_get_uri (cache_art_file);
+ g_debug ("Could not get mtime for cache '%s': %s",
+ uri,
+ local_error->message);
+ g_free (uri);
if (local_art_file) {
g_object_unref (local_art_file);
}
- g_free (uri);
+ g_propagate_error (error, local_error);
return FALSE;
}
- a_exists = g_file_query_exists (cache_art_file, NULL);
- if (a_exists) {
- a_mtime = get_mtime (cache_art_file);
+ cache_art_path = g_file_get_path (cache_art_file);
+
+ if (flags & MEDIA_ART_PROCESS_FLAGS_FORCE ||
+ cache_mtime == 0 || mtime > cache_mtime) {
+ processed = media_art_set (buffer, len, mime, type, artist, title, error);
+ set_mtime (cache_art_path, mtime);
+ } else {
+ g_debug ("Album art already exists for uri:'%s' as '%s'",
+ uri,
+ cache_art_path);
+ processed = TRUE;
}
- art_path = g_file_get_path (cache_art_file);
- local_art_uri = g_file_get_uri (local_art_file);
+ 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);
+ }
+ }
+
+ if (cache_art_file) {
+ g_object_unref (cache_art_file);
+ }
+
+ if (local_art_file) {
+ g_object_unref (local_art_file);
+ }
+
+ g_free (cache_art_path);
+ g_free (uri);
+
+ return processed;
+}
+
+/**
+ * media_art_process_file:
+ * @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
+ * @error: Pointer to potential GLib / MediaArt error, or %NULL
+ *
+ * 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
+ * %NULL, but they can not both be %NULL.
+ *
+ * NOTE: This function MAY retrieve media art for
+ * @artist and @title combinations. It is not guaranteed and depends
+ * on download services available over DBus at the time.
+ *
+ * In cases where download is unavailable, media_art_process_file()
+ * will only try to procure a cache for possible media art found in
+ * directories surrounding the location of @file. If a buffer or
+ * memory chunk needs to be saved to disk which has been retrieved
+ * from an MP3 (for example), you should use
+ * media_art_process_buffer().
+ *
+ * The modification time (mtime) of @file is checked against the
+ * cached stored for @artist and @title. If the cache is old or
+ * doesn't exist, it will be updated. What this actually does is
+ * update the mtime of the cache (a symlink) on the disk.
+ *
+ * If there is no actual media art stored locally (for example, it's
+ * stored in a directory on a removable device), it is copied locally
+ * (usually to an XDG cache directory).
+ *
+ * If @file is on a removable filesystem, the media art file will be
+ * saved in a cache on the removable file system rather than on the
+ * host machine.
+ *
+ * Returns: %TRUE if @file could be processed or %FALSE if @error is set.
+ *
+ * Since: 0.3.0
+ */
+gboolean
+media_art_process_file (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ GFile *file,
+ const gchar *artist,
+ const gchar *title,
+ GError **error)
+{
+ MediaArtProcessPrivate *private;
+ GFile *cache_art_file, *local_art_file;
+ GError *local_error = NULL;
+ gchar *cache_art_path, *uri;
+ gboolean no_cache_or_old;
+ guint64 mtime, cache_mtime;
+
+ g_return_val_if_fail (MEDIA_ART_IS_PROCESS (process), FALSE);
+ g_return_val_if_fail (type > MEDIA_ART_NONE && type < MEDIA_ART_TYPE_COUNT, FALSE);
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (artist != NULL || title != NULL, FALSE);
+
+ private = media_art_process_get_instance_private (process);
+
+ uri = g_file_get_uri (file);
+ g_debug ("Processing media art: artist:'%s', title:'%s', type:'%s', uri:'%s', flags:0x%.8x",
+ artist ? artist : "",
+ title ? title : "",
+ media_art_type_name[type],
+ uri,
+ flags);
+
+ mtime = get_mtime (file, &local_error);
+ if (local_error != NULL) {
+ g_debug ("Could not get mtime for file '%s': %s",
+ uri,
+ local_error->message);
+ g_propagate_error (error, local_error);
+ g_free (uri);
- if ((buffer && len > 0) && ((!a_exists) || (a_exists && mtime > a_mtime))) {
- processed = media_art_set (buffer, len, mime, type, artist, title);
- set_mtime (art_path, mtime);
- created = TRUE;
+ return FALSE;
}
- if ((!created) && ((!a_exists) || (a_exists && mtime > a_mtime))) {
+ media_art_get_file (artist,
+ title,
+ media_art_type_name[type],
+ file,
+ &cache_art_file,
+ &local_art_file);
+
+ cache_art_path = g_file_get_path (cache_art_file);
+
+ cache_mtime = get_mtime (cache_art_file, &local_error);
+ no_cache_or_old = cache_mtime == -1 || cache_mtime < mtime;
+
+ if (no_cache_or_old) {
/* If not, we perform a heuristic on the dir */
gchar *key;
- gchar *dirname = NULL;
- GFile *dirf;
- dirf = g_file_get_parent (file);
- if (dirf) {
- dirname = g_file_get_path (dirf);
- g_object_unref (dirf);
- }
+ key = get_heuristic_for_parent_path (file, type, artist, title);
- key = g_strdup_printf ("%i-%s-%s-%s",
- type,
- artist ? artist : "",
- title ? title : "",
- dirname ? dirname : "");
+ if (!g_hash_table_lookup (private->media_art_cache, key)) {
+ gchar *local_art_uri;
- g_free (dirname);
+ local_art_uri = g_file_get_uri (local_art_file);
- if (!g_hash_table_lookup (media_art_cache, key)) {
- if (!media_art_heuristic (artist,
- title,
- type,
- uri,
- local_art_uri)) {
+ 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 (type,
+ media_art_request_download (process,
+ type,
artist,
title,
local_art_uri,
- art_path);
+ cache_art_path);
+
+ /* FIXME: Should return TRUE or FALSE? */
}
- set_mtime (art_path, mtime);
+ set_mtime (cache_art_path, mtime);
- g_hash_table_insert (media_art_cache,
+ g_hash_table_insert (private->media_art_cache,
key,
GINT_TO_POINTER(TRUE));
+ g_free (local_art_uri);
} else {
g_free (key);
}
} else {
- if (!created) {
- g_debug ("Album art already exists for uri:'%s' as '%s'",
- uri,
- art_path);
- }
- }
-
- 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)) {
- media_art_copy_to_local (art_path, local_art_uri);
- }
+ g_debug ("Album art already exists for uri:'%s' as '%s'",
+ uri,
+ cache_art_path);
}
if (cache_art_file) {
@@ -1478,54 +1788,56 @@ media_art_process_file (const guchar *buffer,
g_object_unref (local_art_file);
}
- g_free (art_path);
- g_free (local_art_uri);
+ g_free (cache_art_path);
g_free (uri);
- return processed;
+ return TRUE;
}
-
/**
- * media_art_process:
- * @buffer: (array length=len): A buffer of binary image data
- * @len: The length of @buffer, in bytes
- * @mime: The MIME type of the data stored in @buffer
+ * media_art_process_uri:
+ * @process: Media art process object
* @type: The type of media that contained the image data
- * @artist: (allow-none): Artist name of the media
- * @title: (allow-none): Title of the media
- * @uri: URI of the media file that contained the image data
+ * @flags: How the media art is processed
+ * @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
+ * @error: Pointer to potential GLib / MediaArt error, or %NULL
*
- * This function is the same as media_art_process_file(), but takes the URI as
- * a string rather than a #GFile object.
+ * This function calls media_art_process_file(), but takes the @uri as
+ * a string rather than a #GFile object. Either @artist OR @title can be
+ * %NULL, but they can not both be %NULL.
*
- * Returns: %TRUE in case of success, %FALSE otherwise.
+ * Returns: %TRUE if @uri could be processed or %FALSE if @error is set.
*
- * Since: 0.2.0
+ * Since: 0.5.0
*/
gboolean
-media_art_process (const unsigned char *buffer,
- size_t len,
- const gchar *mime,
- MediaArtType type,
- const gchar *artist,
- const gchar *title,
- const gchar *uri)
+media_art_process_uri (MediaArtProcess *process,
+ MediaArtType type,
+ MediaArtProcessFlags flags,
+ const gchar *uri,
+ const gchar *artist,
+ const gchar *title,
+ GError **error)
{
GFile *file;
gboolean result;
+ g_return_val_if_fail (MEDIA_ART_IS_PROCESS (process), FALSE);
+ g_return_val_if_fail (type > MEDIA_ART_NONE && type < MEDIA_ART_TYPE_COUNT, FALSE);
g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (artist != NULL || title != NULL, FALSE);
file = g_file_new_for_uri (uri);
- result = media_art_process_file (buffer,
- len,
- mime,
+ result = media_art_process_file (process,
type,
+ flags,
+ file,
artist,
title,
- file);
+ error);
g_object_unref (file);
diff --git a/libmediaart/extract.h b/libmediaart/extract.h
index 3744923..e5ab8fa 100644
--- a/libmediaart/extract.h
+++ b/libmediaart/extract.h
@@ -46,25 +46,111 @@ typedef enum {
MEDIA_ART_TYPE_COUNT
} MediaArtType;
-gboolean media_art_init (void);
-void media_art_shutdown (void);
-
-gboolean media_art_process (const unsigned char *buffer,
- size_t len,
- const gchar *mime,
- MediaArtType type,
- const gchar *artist,
- const gchar *title,
- const gchar *uri);
-
-gboolean media_art_process_file (const guchar *buffer,
- gsize len,
- const gchar *mime,
- MediaArtType type,
- const gchar *artist,
- const gchar *title,
- GFile *file);
+/**
+ * MediaArtProcessFlags:
+ * @MEDIA_ART_PROCESS_FLAGS_NONE: Normal operation.
+ * @MEDIA_ART_PROCESS_FLAGS_FORCE: Force media art to be re-saved to disk even if it already exists and the related file or URI has the same modified time (mtime).
+ *
+ * This type categorized the flags used when processing media art.
+ *
+ * Since: 0.3.0
+ */
+typedef enum {
+ MEDIA_ART_PROCESS_FLAGS_NONE = 0,
+ MEDIA_ART_PROCESS_FLAGS_FORCE = 1 << 0,
+} MediaArtProcessFlags;
+
+/**
+ * MediaArtError:
+ * @MEDIA_ART_ERROR_NO_STORAGE: Storage information is unknown, we
+ * have no knowledge about removable media.
+ * @MEDIA_ART_ERROR_NO_TITLE: Title is required, but was not provided,
+ * or was empty.
+ * @MEDIA_ART_ERROR_SYMLINK_FAILED: A call to symlink() failed
+ * resulting in the incorrect storage of media art.
+ * @MEDIA_ART_ERROR_RENAME_FAILED: File could not be renamed.
+ *
+ * Enumeration values used in errors returned by the
+ * #MediaArtError API.
+ *
+ * Since: 0.2.0
+ **/
+typedef enum {
+ MEDIA_ART_ERROR_NO_STORAGE,
+ MEDIA_ART_ERROR_NO_TITLE,
+ MEDIA_ART_ERROR_SYMLINK_FAILED,
+ MEDIA_ART_ERROR_RENAME_FAILED
+} MediaArtError;
+
+
+/**
+ * media_art_error_quark:
+ *
+ * A #GQuark representing the type of #GError for #MediaArtProcess failures.
+ *
+ * Since: 0.2.0
+ **/
+GQuark media_art_error_quark (void) G_GNUC_CONST;
+
+
+#define MEDIA_ART_TYPE_PROCESS (media_art_process_get_type())
+#define MEDIA_ART_PROCESS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), MEDIA_ART_TYPE_PROCESS, MediaArtProcess))
+#define MEDIA_ART_PROCESS_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), MEDIA_ART_TYPE_PROCESS, MediaArtProcessClass))
+#define MEDIA_ART_IS_PROCESS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), MEDIA_ART_TYPE_PROCESS))
+#define MEDIA_ART_IS_PROCESS_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), MEDIA_ART_TYPE_PROCESS))
+#define MEDIA_ART_PROCESS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), MEDIA_ART_TYPE_PROCESS, MediaArtProcessClass))
+
+typedef struct _MediaArtProcess MediaArtProcess;
+typedef struct _MediaArtProcessClass MediaArtProcessClass;
+
+/**
+ * MediaArtProcess:
+ * @parent: parent object
+ *
+ * A class implementation for processing and extracting media art.
+ **/
+struct _MediaArtProcess {
+ GObject parent;
+};
+
+/**
+ * MediaArtProcessClass:
+ * @parent: parent object class
+ *
+ * Prototype for the class.
+ **/
+struct _MediaArtProcessClass {
+ GObjectClass parent;
+};
+
+
+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);
G_END_DECLS
-#endif /* __LIBMEDIAART_UTILS_H__ */
+#endif /* __LIBMEDIAART_EXTRACT_H__ */
diff --git a/libmediaart/extractdummy.c b/libmediaart/extractdummy.c
index 195de31..f80ccd2 100644
--- a/libmediaart/extractdummy.c
+++ b/libmediaart/extractdummy.c
@@ -22,30 +22,98 @@
#include "extractgeneric.h"
+/**
+ * SECTION:plugins
+ * @title: Plugins
+ * @short_description: Plugins for cache conversion.
+ * @include: libmediaart/mediaart.h
+ *
+ * Plugins are provided to allow different systems to make use of
+ * existing file format conversion APIs. By default, a GdkPixbuf and
+ * Qt implementation are provided. This API allows new implementations
+ * to be provided.
+ *
+ **/
+
+/**
+ * media_art_plugin_init:
+ * @max_width: The maximum width that an image is allowed to be
+ *
+ * This function facilitates a plugin&apos;s need to create any
+ * internal caches before anything else is done. This function must
+ * exist in each plugin and is called immediately after the plugin is
+ * loaded. Conversely, media_art_plugin_shutdown() is called before
+ * tear down of the plugin system or plugin itself.
+ *
+ * Since: 0.1.0
+ */
void
media_art_plugin_init (gint max_width)
{
/* Initialize something */
}
+/**
+ * media_art_plugin_shutdown:
+ *
+ * This function facilitates a plugin&apos;s need to clean up any
+ * internal caches. This function must exist in each plugin and is
+ * called immediately after the plugin is loaded. Conversely,
+ * media_art_plugin_init() is called after the plugin is loaded.
+ *
+ * Since: 0.1.0
+ */
void
media_art_plugin_shutdown (void)
{
/* Shutdown something */
}
+/**
+ * media_art_file_to_jpeg:
+ * @filename: Original file name (not URI) to convert
+ * @target: Output file name (not URI) to save converted content to
+ * @error: A #GError to use upon failure, or %NULL
+ *
+ * Save @filename to @target as JPEG format. The @filename may not be
+ * a JPEG in the first place.
+ *
+ * Returns: %TRUE if conversion was successful, otherwise %FALSE is
+ * returned if @error is set.
+ *
+ * Since: 0.1.0
+ */
gboolean
-media_art_file_to_jpeg (const gchar *filename,
- const gchar *target)
+media_art_file_to_jpeg (const gchar *filename,
+ const gchar *target,
+ GError **error)
{
return FALSE;
}
+/**
+ * media_art_buffer_to_jpeg:
+ * @buffer: Raw buffer representing content to save
+ * @len: Length of @buffer to use
+ * @buffer_mime: MIME type for @buffer
+ * @target: Output file name (not URI) to save converted content to
+ * @error: A #GError to use upon failure, or %NULL
+ *
+ * This function performs the same operation as
+ * media_art_file_to_jpeg() with the exception that a raw @buffer can
+ * be used instead providing @len and the @buffer_mime too.
+ *
+ * Returns: %TRUE if conversion was successful, otherwise %FALSE is
+ * returned if @error is set.
+ *
+ * Since: 0.1.0
+ */
gboolean
-media_art_buffer_to_jpeg (const unsigned char *buffer,
- size_t len,
- const gchar *buffer_mime,
- const gchar *target)
+media_art_buffer_to_jpeg (const unsigned char *buffer,
+ size_t len,
+ const gchar *buffer_mime,
+ const gchar *target,
+ GError **error)
{
return FALSE;
}
diff --git a/libmediaart/extractgeneric.h b/libmediaart/extractgeneric.h
index b48d2be..8fa114b 100644
--- a/libmediaart/extractgeneric.h
+++ b/libmediaart/extractgeneric.h
@@ -20,7 +20,6 @@
* Philip Van Hoof <philip@codeminded.be>
*/
-
#ifndef __LIBMEDIAART_EXTRACTGENERIC_H__
#define __LIBMEDIAART_EXTRACTGENERIC_H__
@@ -32,15 +31,17 @@
G_BEGIN_DECLS
-void media_art_plugin_init (gint max_width);
+void media_art_plugin_init (gint max_width);
void media_art_plugin_shutdown (void);
-gboolean media_art_file_to_jpeg (const gchar *filename,
- const gchar *target);
-gboolean media_art_buffer_to_jpeg (const unsigned char *buffer,
- size_t len,
- const gchar *buffer_mime,
- const gchar *target);
+gboolean media_art_file_to_jpeg (const gchar *filename,
+ const gchar *target,
+ GError **error);
+gboolean media_art_buffer_to_jpeg (const unsigned char *buffer,
+ size_t len,
+ const gchar *buffer_mime,
+ const gchar *target,
+ GError **error);
G_END_DECLS
diff --git a/libmediaart/extractpixbuf.c b/libmediaart/extractpixbuf.c
index 2f823fc..3b2854b 100644
--- a/libmediaart/extractpixbuf.c
+++ b/libmediaart/extractpixbuf.c
@@ -40,28 +40,28 @@ media_art_plugin_shutdown (void)
}
gboolean
-media_art_file_to_jpeg (const gchar *filename,
- const gchar *target)
+media_art_file_to_jpeg (const gchar *filename,
+ const gchar *target,
+ GError **error)
{
GdkPixbuf *pixbuf;
- GError *error = NULL;
+ GError *local_error = NULL;
/* TODO: Add resizing support */
- pixbuf = gdk_pixbuf_new_from_file (filename, &error);
-
- if (error) {
- g_clear_error (&error);
+ pixbuf = gdk_pixbuf_new_from_file (filename, &local_error);
+ if (local_error) {
+ g_propagate_error (error, local_error);
return FALSE;
- } else {
- gdk_pixbuf_save (pixbuf, target, "jpeg", &error, NULL);
- g_object_unref (pixbuf);
+ }
- if (error) {
- g_clear_error (&error);
- return FALSE;
- }
+ gdk_pixbuf_save (pixbuf, target, "jpeg", &local_error, NULL);
+ g_object_unref (pixbuf);
+
+ if (local_error) {
+ g_propagate_error (error, local_error);
+ return FALSE;
}
return TRUE;
@@ -87,11 +87,14 @@ size_prepared_cb (GdkPixbufLoader *loader,
}
gboolean
-media_art_buffer_to_jpeg (const unsigned char *buffer,
- size_t len,
- const gchar *buffer_mime,
- const gchar *target)
+media_art_buffer_to_jpeg (const unsigned char *buffer,
+ size_t len,
+ const gchar *buffer_mime,
+ const gchar *target,
+ GError **error)
{
+ GError *local_error = NULL;
+
if (max_width_in_bytes < 0) {
g_debug ("Not saving album art from buffer, disabled in config");
return TRUE;
@@ -103,11 +106,12 @@ media_art_buffer_to_jpeg (const unsigned char *buffer,
g_strcmp0 (buffer_mime, "JPG") == 0) &&
(buffer && len > 2 && buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff)) {
g_debug ("Saving album art using raw data as uri:'%s'", target);
- g_file_set_contents (target, (const gchar *) buffer, (gssize) len, NULL);
+ if (!g_file_set_contents (target, (const gchar *) buffer, (gssize) len, error)) {
+ return FALSE;
+ }
} else {
GdkPixbuf *pixbuf;
GdkPixbufLoader *loader;
- GError *error = NULL;
g_debug ("Saving album art using GdkPixbufLoader for uri:'%s' (max width:%d)",
target,
@@ -121,11 +125,11 @@ media_art_buffer_to_jpeg (const unsigned char *buffer,
NULL);
}
- if (!gdk_pixbuf_loader_write (loader, buffer, len, &error)) {
- g_warning ("Could not write with GdkPixbufLoader when setting album art, %s",
- error ? error->message : "no error given");
+ if (!gdk_pixbuf_loader_write (loader, buffer, len, &local_error)) {
+ g_warning ("Could not write with GdkPixbufLoader when setting media art, %s",
+ local_error ? local_error->message : "no error given");
- g_clear_error (&error);
+ g_propagate_error (error, local_error);
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
@@ -135,7 +139,9 @@ media_art_buffer_to_jpeg (const unsigned char *buffer,
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (pixbuf == NULL) {
- g_warning ("Could not get pixbuf from GdkPixbufLoader when setting album art");
+ g_warning ("Could not get pixbuf from GdkPixbufLoader when setting media art");
+
+ /* FIXME: Set error here */
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
@@ -143,21 +149,24 @@ media_art_buffer_to_jpeg (const unsigned char *buffer,
return FALSE;
}
- if (!gdk_pixbuf_save (pixbuf, target, "jpeg", &error, NULL)) {
- g_warning ("Could not save GdkPixbuf when setting album art, %s",
- error ? error->message : "no error given");
+ if (!gdk_pixbuf_save (pixbuf, target, "jpeg", &local_error, NULL)) {
+ g_warning ("Could not save GdkPixbuf when setting media art, %s",
+ local_error ? local_error->message : "no error given");
- g_clear_error (&error);
+ g_propagate_error (error, local_error);
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
return FALSE;
}
- if (!gdk_pixbuf_loader_close (loader, &error)) {
- g_warning ("Could not close GdkPixbufLoader when setting album art, %s",
- error ? error->message : "no error given");
- g_clear_error (&error);
+ if (!gdk_pixbuf_loader_close (loader, &local_error)) {
+ g_warning ("Could not close GdkPixbufLoader when setting media art, %s",
+ local_error ? local_error->message : "no error given");
+
+ g_propagate_error (error, local_error);
+
+ return FALSE;
}
g_object_unref (loader);
diff --git a/libmediaart/extractqt.cpp b/libmediaart/extractqt.cpp
index d39ddd7..dda324f 100644
--- a/libmediaart/extractqt.cpp
+++ b/libmediaart/extractqt.cpp
@@ -82,8 +82,9 @@ media_art_plugin_shutdown (void)
}
gboolean
-media_art_file_to_jpeg (const gchar *filename,
- const gchar *target)
+media_art_file_to_jpeg (const gchar *filename,
+ const gchar *target,
+ GError **error)
{
if (max_width_in_bytes < 0) {
g_debug ("Not saving album art from file, disabled in config");
@@ -91,6 +92,7 @@ media_art_file_to_jpeg (const gchar *filename,
}
/* TODO: Add resizing support */
+ /* TODO: Add error reporting */
QFile file (filename);
@@ -129,10 +131,11 @@ media_art_file_to_jpeg (const gchar *filename,
}
gboolean
-media_art_buffer_to_jpeg (const unsigned char *buffer,
- size_t len,
- const gchar *buffer_mime,
- const gchar *target)
+media_art_buffer_to_jpeg (const unsigned char *buffer,
+ size_t len,
+ const gchar *buffer_mime,
+ const gchar *target,
+ GError **error)
{
if (max_width_in_bytes < 0) {
g_debug ("Not saving album art from buffer, disabled in config");
@@ -144,14 +147,16 @@ media_art_buffer_to_jpeg (const unsigned char *buffer,
(g_strcmp0 (buffer_mime, "image/jpeg") == 0 ||
g_strcmp0 (buffer_mime, "JPG") == 0) &&
(buffer && len > 2 && buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff)) {
- g_debug ("Saving album art using raw data as uri:'%s'",
- target);
- g_file_set_contents (target, (const gchar*) buffer, (gssize) len, NULL);
+ g_debug ("Saving album art using raw data as uri:'%s'", target);
+ if (!g_file_set_contents (target, (const gchar*) buffer, (gssize) len, error)) {
+ return FALSE;
+ }
} else {
QImageReader *reader = NULL;
QByteArray array;
/* TODO: Add resizing support */
+ /* TODO: Add error reporting */
array = QByteArray ((const char *) buffer, (int) len);
diff --git a/libmediaart/storage.c b/libmediaart/storage.c
index feb22f6..36213d7 100644
--- a/libmediaart/storage.c
+++ b/libmediaart/storage.c
@@ -28,7 +28,7 @@
#include "marshal.h"
/**
- * SECTION:-storage
+ * SECTION:storage
* @short_description: Removable storage and mount point convenience API
* @include: libmediaart/mediaart.h
*
@@ -140,8 +140,6 @@ storage_init (Storage *storage)
{
StoragePrivate *priv;
- g_message ("Initializing Storage...");
-
priv = STORAGE_GET_PRIVATE (storage);
priv->mounts = g_node_new (NULL);
@@ -163,8 +161,6 @@ storage_init (Storage *storage)
g_signal_connect_object (priv->volume_monitor, "mount-added",
G_CALLBACK (mount_added_cb), storage, 0);
- g_message ("Mount monitors set up for to watch for added, removed and pre-unmounts...");
-
/* Get all mounts and set them up */
if (!mounts_setup (storage)) {
return;
@@ -702,7 +698,7 @@ mounts_setup (Storage *storage)
mounts = g_volume_monitor_get_mounts (priv->volume_monitor);
if (!mounts) {
- g_message ("No mounts found to iterate");
+ g_debug ("No mounts found to iterate");
return TRUE;
}
@@ -752,19 +748,19 @@ mount_remove (Storage *storage,
if (node) {
info = node->data;
- g_message ("Mount:'%s' with UUID:'%s' now unmounted from:'%s'",
- name,
- info->uuid,
- mount_point);
+ g_debug ("Mount:'%s' with UUID:'%s' now unmounted from:'%s'",
+ name,
+ info->uuid,
+ mount_point);
g_signal_emit (storage, signals[MOUNT_POINT_REMOVED], 0, info->uuid, mount_point, NULL);
g_hash_table_remove (priv->mounts_by_uuid, info->uuid);
mount_node_free (node);
} else {
- g_message ("Mount:'%s' now unmounted from:'%s' (was not tracked)",
- name,
- mount_point);
+ g_debug ("Mount:'%s' now unmounted from:'%s' (was not tracked)",
+ name,
+ mount_point);
}
g_free (name);
diff --git a/m4/.gitignore b/m4/.gitignore
new file mode 100644
index 0000000..0f4126c
--- /dev/null
+++ b/m4/.gitignore
@@ -0,0 +1 @@
+*.m4
diff --git a/m4/attributes.m4 b/m4/attributes.m4
new file mode 100644
index 0000000..aa53ef2
--- /dev/null
+++ b/m4/attributes.m4
@@ -0,0 +1,288 @@
+dnl Macros to check the presence of generic (non-typed) symbols.
+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
+dnl Copyright (c) 2006-2008 xine project
+dnl Copyright (c) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+dnl 02110-1301, USA.
+dnl
+dnl As a special exception, the copyright owners of the
+dnl macro gives unlimited permission to copy, distribute and modify the
+dnl configure scripts that are the output of Autoconf when processing the
+dnl Macro. You need not follow the terms of the GNU General Public
+dnl License when using or distributing such scripts, even though portions
+dnl of the text of the Macro appear in them. The GNU General Public
+dnl License (GPL) does govern all other use of the material that
+dnl constitutes the Autoconf Macro.
+dnl
+dnl This special exception to the GPL applies to versions of the
+dnl Autoconf Macro released by this project. When you make and
+dnl distribute a modified version of the Autoconf Macro, you may extend
+dnl this special exception to the GPL to apply to your modified version as
+dnl well.
+
+dnl Check if FLAG in ENV-VAR is supported by compiler and append it
+dnl to WHERE-TO-APPEND variable
+dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG])
+
+AC_DEFUN([CC_CHECK_FLAG_APPEND], [
+ AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2],
+ AS_TR_SH([cc_cv_$2_$3]),
+ [eval "AS_TR_SH([cc_save_$2])='${$2}'"
+ eval "AS_TR_SH([$2])='-Werror $3'"
+ AC_LINK_IFELSE([AC_LANG_SOURCE([int a = 0; int main(void) { return a; } ])],
+ [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"],
+ [eval "AS_TR_SH([cc_cv_$2_$3])='no'"])
+ eval "AS_TR_SH([$2])='$cc_save_$2'"])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes],
+ [eval "$1='${$1} $3'"])
+])
+
+dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2])
+AC_DEFUN([CC_CHECK_FLAGS_APPEND], [
+ for flag in $3; do
+ CC_CHECK_FLAG_APPEND($1, $2, $flag)
+ done
+])
+
+dnl Check if the flag is supported by linker (cacheable)
+dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
+
+AC_DEFUN([CC_CHECK_LDFLAGS], [
+ AC_CACHE_CHECK([if $CC supports $1 flag],
+ AS_TR_SH([cc_cv_ldflags_$1]),
+ [ac_save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $1"
+ AC_LINK_IFELSE([int main() { return 1; }],
+ [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
+ LDFLAGS="$ac_save_LDFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
+ [$2], [$3])
+])
+
+dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
+dnl the current linker to avoid undefined references in a shared object.
+AC_DEFUN([CC_NOUNDEFINED], [
+ dnl We check $host for which systems to enable this for.
+ AC_REQUIRE([AC_CANONICAL_HOST])
+
+ case $host in
+ dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
+ dnl are requested, as different implementations are present; to avoid problems
+ dnl use -Wl,-z,defs only for those platform not behaving this way.
+ *-freebsd* | *-openbsd*) ;;
+ *)
+ dnl First of all check for the --no-undefined variant of GNU ld. This allows
+ dnl for a much more readable commandline, so that people can understand what
+ dnl it does without going to look for what the heck -z defs does.
+ for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
+ CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
+ break
+ done
+ ;;
+ esac
+
+ AC_SUBST([LDFLAGS_NOUNDEFINED])
+])
+
+dnl Check for a -Werror flag or equivalent. -Werror is the GCC
+dnl and ICC flag that tells the compiler to treat all the warnings
+dnl as fatal. We usually need this option to make sure that some
+dnl constructs (like attributes) are not simply ignored.
+dnl
+dnl Other compilers don't support -Werror per se, but they support
+dnl an equivalent flag:
+dnl - Sun Studio compiler supports -errwarn=%all
+AC_DEFUN([CC_CHECK_WERROR], [
+ AC_CACHE_CHECK(
+ [for $CC way to treat warnings as errors],
+ [cc_cv_werror],
+ [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
+ [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
+ ])
+])
+
+AC_DEFUN([CC_CHECK_ATTRIBUTE], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
+ AS_TR_SH([cc_cv_attribute_$1]),
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
+ [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
+ [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
+ [AC_DEFINE(
+ AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
+ [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
+ )
+ $4],
+ [$5])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
+ CC_CHECK_ATTRIBUTE(
+ [constructor],,
+ [void __attribute__((constructor)) ctor() { int a; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
+ CC_CHECK_ATTRIBUTE(
+ [format], [format(printf, n, n)],
+ [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
+ CC_CHECK_ATTRIBUTE(
+ [format_arg], [format_arg(printf)],
+ [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
+ CC_CHECK_ATTRIBUTE(
+ [visibility_$1], [visibility("$1")],
+ [void __attribute__((visibility("$1"))) $1_function() { }],
+ [$2], [$3])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
+ CC_CHECK_ATTRIBUTE(
+ [nonnull], [nonnull()],
+ [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
+ CC_CHECK_ATTRIBUTE(
+ [unused], ,
+ [void some_function(void *foo, __attribute__((unused)) void *bar);],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
+ CC_CHECK_ATTRIBUTE(
+ [sentinel], ,
+ [void some_function(void *foo, ...) __attribute__((sentinel));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
+ CC_CHECK_ATTRIBUTE(
+ [deprecated], ,
+ [void some_function(void *foo, ...) __attribute__((deprecated));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
+ CC_CHECK_ATTRIBUTE(
+ [alias], [weak, alias],
+ [void other_function(void *foo) { }
+ void some_function(void *foo) __attribute__((weak, alias("other_function")));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
+ CC_CHECK_ATTRIBUTE(
+ [malloc], ,
+ [void * __attribute__((malloc)) my_alloc(int n);],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_PACKED], [
+ CC_CHECK_ATTRIBUTE(
+ [packed], ,
+ [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_CONST], [
+ CC_CHECK_ATTRIBUTE(
+ [const], ,
+ [int __attribute__((const)) twopow(int n) { return 1 << n; } ],
+ [$1], [$2])
+])
+
+AC_DEFUN([CC_FLAG_VISIBILITY], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
+ [cc_cv_flag_visibility],
+ [cc_flag_visibility_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
+ cc_cv_flag_visibility='yes',
+ cc_cv_flag_visibility='no')
+ CFLAGS="$cc_flag_visibility_save_CFLAGS"])
+
+ AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
+ [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
+ [Define this if the compiler supports the -fvisibility flag])
+ $1],
+ [$2])
+])
+
+AC_DEFUN([CC_FUNC_EXPECT], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([if compiler has __builtin_expect function],
+ [cc_cv_func_expect],
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+ [int some_function() {
+ int a = 3;
+ return (int)__builtin_expect(a, 3);
+ }])],
+ [cc_cv_func_expect=yes],
+ [cc_cv_func_expect=no])
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ AS_IF([test "x$cc_cv_func_expect" = "xyes"],
+ [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
+ [Define this if the compiler supports __builtin_expect() function])
+ $1],
+ [$2])
+])
+
+AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
+ AC_REQUIRE([CC_CHECK_WERROR])
+ AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
+ [cc_cv_attribute_aligned],
+ [ac_save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $cc_cv_werror"
+ for cc_attribute_align_try in 64 32 16 8 4 2; do
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ int main() {
+ static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
+ return c;
+ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
+ done
+ CFLAGS="$ac_save_CFLAGS"
+ ])
+
+ if test "x$cc_cv_attribute_aligned" != "x"; then
+ AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
+ [Define the highest alignment supported])
+ fi
+])
diff --git a/m4/local.m4 b/m4/local.m4
new file mode 100644
index 0000000..bca646d
--- /dev/null
+++ b/m4/local.m4
@@ -0,0 +1,258 @@
+dnl #########################################################################
+AC_DEFUN([AX_DOTS_TO_UNDERSCORES], [
+ $1[]_UNDERSCORES=`echo "$$1" | sed -e 's/\./_/g'`
+ AC_SUBST($1[]_UNDERSCORES)
+]) dnl AX_DOTS_TO_UNDERSCORES
+
+dnl #########################################################################
+AC_DEFUN([AX_COMPARE_VERSION], [
+ # Used to indicate true or false condition
+ ax_compare_version=false
+
+ # Convert the two version strings to be compared into a format that
+ # allows a simple string comparison. The end result is that a version
+ # string of the form 1.12.5-r617 will be converted to the form
+ # 0001001200050617. In other words, each number is zero padded to four
+ # digits, and non digits are removed.
+ AS_VAR_PUSHDEF([A],[ax_compare_version_A])
+ A=`echo "$1" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
+ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/[[^0-9]]//g'`
+
+ AS_VAR_PUSHDEF([B],[ax_compare_version_B])
+ B=`echo "$3" | sed -e 's/\([[0-9]]*\)/Z\1Z/g' \
+ -e 's/Z\([[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/Z\([[0-9]][[0-9]][[0-9]]\)Z/Z0\1Z/g' \
+ -e 's/[[^0-9]]//g'`
+
+ dnl # In the case of le, ge, lt, and gt, the strings are sorted as necessary
+ dnl # then the first line is used to determine if the condition is true.
+ dnl # The sed right after the echo is to remove any indented white space.
+ m4_case(m4_tolower($2),
+ [lt],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/false/;s/x${B}/true/;1q"`
+ ],
+ [gt],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort | sed "s/x${A}/false/;s/x${B}/true/;1q"`
+ ],
+ [le],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort | sed "s/x${A}/true/;s/x${B}/false/;1q"`
+ ],
+ [ge],[
+ ax_compare_version=`echo "x$A
+x$B" | sed 's/^ *//' | sort -r | sed "s/x${A}/true/;s/x${B}/false/;1q"`
+ ],[
+ dnl Split the operator from the subversion count if present.
+ m4_bmatch(m4_substr($2,2),
+ [0],[
+ # A count of zero means use the length of the shorter version.
+ # Determine the number of characters in A and B.
+ ax_compare_version_len_A=`echo "$A" | awk '{print(length)}'`
+ ax_compare_version_len_B=`echo "$B" | awk '{print(length)}'`
+
+ # Set A to no more than B's length and B to no more than A's length.
+ A=`echo "$A" | sed "s/\(.\{$ax_compare_version_len_B\}\).*/\1/"`
+ B=`echo "$B" | sed "s/\(.\{$ax_compare_version_len_A\}\).*/\1/"`
+ ],
+ [[0-9]+],[
+ # A count greater than zero means use only that many subversions
+ A=`echo "$A" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
+ B=`echo "$B" | sed "s/\(\([[0-9]]\{4\}\)\{m4_substr($2,2)\}\).*/\1/"`
+ ],
+ [.+],[
+ AC_WARNING(
+ [illegal OP numeric parameter: $2])
+ ],[])
+
+ # Pad zeros at end of numbers to make same length.
+ ax_compare_version_tmp_A="$A`echo $B | sed 's/./0/g'`"
+ B="$B`echo $A | sed 's/./0/g'`"
+ A="$ax_compare_version_tmp_A"
+
+ # Check for equality or inequality as necessary.
+ m4_case(m4_tolower(m4_substr($2,0,2)),
+ [eq],[
+ test "x$A" = "x$B" && ax_compare_version=true
+ ],
+ [ne],[
+ test "x$A" != "x$B" && ax_compare_version=true
+ ],[
+ AC_WARNING([illegal OP parameter: $2])
+ ])
+ ])
+
+ AS_VAR_POPDEF([A])dnl
+ AS_VAR_POPDEF([B])dnl
+
+ dnl # Execute ACTION-IF-TRUE / ACTION-IF-FALSE.
+ if test "$ax_compare_version" = "true" ; then
+ m4_ifvaln([$4],[$4],[:])dnl
+ m4_ifvaln([$5],[else $5])dnl
+ fi
+]) dnl AX_COMPARE_VERSION
+
+dnl #########################################################################
+dnl Turn on the additional warnings last, so -Werror doesn't affect other tests.
+AC_DEFUN([IDT_COMPILE_WARNINGS],[
+ if test -f $srcdir/autogen.sh; then
+ default_compile_warnings="maximum"
+ else
+ default_compile_warnings="no"
+ fi
+
+ AC_ARG_WITH(compile-warnings,
+ AS_HELP_STRING([--with-compile-warnings=@<:@no/yes/maximum/error@:>@],
+ [Compiler warnings]),
+ [enable_compile_warnings="$withval"],
+ [enable_compile_warnings="$default_compile_warnings"])
+
+ warnCFLAGS=
+ if test "x$GCC" != xyes; then
+ enable_compile_warnings=no
+ fi
+
+ warning_cflags=
+ warning_valaflags=
+ realsave_CFLAGS="$CFLAGS"
+
+ # Everything from -Wall except:
+ # 1. the -Wunused-* stuff
+ # 2. the non C warnings: -Wreorder -Wc++11-compat
+ # 3. unfixable issues: -Wmissing-braces
+ #
+ # We don't want to see warnings about generated code.
+ CC_CHECK_FLAGS_APPEND([common_cflags], [CFLAGS], [\
+ -Waddress \
+ -Warray-bounds \
+ -Wchar-subscripts \
+ -Wenum-compare \
+ -Wimplicit-int \
+ -Wimplicit-function-declaration \
+ -Wcomment \
+ -Wformat \
+ -Wmain \
+ -Wmaybe-uninitialized \
+ -Wnonnull \
+ -Wparentheses \
+ -Wpointer-sign \
+ -Wreturn-type \
+ -Wsequence-point \
+ -Wsign-compare \
+ -Wstrict-aliasing \
+ -Wstrict-overflow=1 \
+ -Wswitch \
+ -Wtrigraphs \
+ -Wuninitialized \
+ -Wunknown-pragmas \
+ -Wvolatile-register-var \
+ ])
+
+ case "$enable_compile_warnings" in
+ no)
+ warning_cflags=
+ warning_valaflags=
+ ;;
+ yes)
+ CC_CHECK_FLAGS_APPEND([additional_cflags], [CFLAGS], [\
+ -Wall \
+ -Wunused \
+ -Wmissing-prototypes \
+ -Wmissing-declarations \
+ ])
+
+ CC_CHECK_FLAGS_APPEND([additional_valaflags], [CFLAGS], [\
+ -Wmissing-prototypes \
+ -Wmissing-declarations \
+ ])
+
+ dnl -Wall includes the $common_cflags already.
+ warning_cflags="$additional_cflags"
+ warning_valaflags="$common_cflags $additional_valaflags"
+ ;;
+ maximum|error)
+ CC_CHECK_FLAGS_APPEND([additional_cflags], [CFLAGS], [\
+ -Wall \
+ -Wunused \
+ -Wchar-subscripts \
+ -Wmissing-prototypes \
+ -Wmissing-declarations \
+ -Wnested-externs \
+ -Wpointer-arit \
+ -Wno-sign-compare \
+ -Wno-pointer-sign \
+ ])
+
+ CC_CHECK_FLAGS_APPEND([additional_valaflags], [CFLAGS], [\
+ -Wmissing-prototypes \
+ -Wmissing-declarations \
+ -Wnested-externs \
+ -Wpointer-arith \
+ -Wno-sign-compare \
+ -Wno-pointer-sign \
+ ])
+
+ dnl -Wall includes the $common_cflags already.
+ warning_cflags="$additional_cflags"
+ warning_valaflags="$common_cflags $additional_valaflags"
+
+ if test "$enable_compile_warnings" = "error" ; then
+ warning_cflags="$warning_cflags -Werror"
+ warning_valaflags="$warning_valaflags -Werror"
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --with-compile-warnings)
+ ;;
+ esac
+ CFLAGS="$realsave_CFLAGS"
+ AC_MSG_CHECKING(what warning flags to pass to the C compiler)
+ AC_MSG_RESULT($warning_cflags)
+
+ AC_MSG_CHECKING(what warning flags to pass to the C compiler for Vala built sources)
+ AC_MSG_RESULT($warning_valaflags)
+
+ WARN_CFLAGS="$warning_cflags"
+ AC_SUBST(WARN_CFLAGS)
+
+ WARN_VALACFLAGS="$warning_valaflags"
+ AC_SUBST(WARN_VALACFLAGS)
+]) dnl IDT_COMPILE_WARNINGS
+
+
+
+dnl Stolen from https://git.gnome.org/browse/glib/tree/m4macros/glibtests.m4
+
+dnl GLIB_TESTS
+dnl
+
+AC_DEFUN([GLIB_TESTS],
+[
+ AC_ARG_ENABLE(installed-tests,
+ AS_HELP_STRING([--enable-installed-tests],
+ [Enable installation of some test cases]),
+ [case ${enableval} in
+ yes) ENABLE_INSTALLED_TESTS="1" ;;
+ no) ENABLE_INSTALLED_TESTS="" ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-installed-tests]) ;;
+ esac])
+ AM_CONDITIONAL([ENABLE_INSTALLED_TESTS], test "$ENABLE_INSTALLED_TESTS" = "1")
+ AC_ARG_ENABLE(always-build-tests,
+ AS_HELP_STRING([--enable-always-build-tests],
+ [Enable always building tests during 'make all']),
+ [case ${enableval} in
+ yes) ENABLE_ALWAYS_BUILD_TESTS="1" ;;
+ no) ENABLE_ALWAYS_BUILD_TESTS="" ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for --enable-always-build-tests]) ;;
+ esac])
+ AM_CONDITIONAL([ENABLE_ALWAYS_BUILD_TESTS], test "$ENABLE_ALWAYS_BUILD_TESTS" = "1")
+ if test "$ENABLE_INSTALLED_TESTS" = "1"; then
+ AC_SUBST(installed_test_metadir, [${datadir}/installed-tests/]AC_PACKAGE_NAME)
+ AC_SUBST(installed_testdir, [${libexecdir}/installed-tests/]AC_PACKAGE_NAME)
+ fi
+])
diff --git a/tests/LanedoIconHKS43-64².png b/tests/LanedoIconHKS43-64².png
deleted file mode 100644
index b5261a7..0000000
--- a/tests/LanedoIconHKS43-64².png
+++ /dev/null
Binary files differ
diff --git a/tests/mediaarttest.c b/tests/mediaarttest.c
index 3690335..09cc1ae 100644
--- a/tests/mediaarttest.c
+++ b/tests/mediaarttest.c
@@ -76,9 +76,17 @@ struct {
};
static void
-test_mediaart_init (void)
+test_mediaart_new (void)
{
- g_assert_true (media_art_init ());
+ 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
@@ -97,11 +105,6 @@ test_mediaart_stripping (void)
}
static void
-test_mediaart_stripping_null (void)
-{
-}
-
-static void
test_mediaart_stripping_failures_subprocess (void)
{
g_assert (!media_art_strip_invalid_entities (NULL));
@@ -150,8 +153,6 @@ test_mediaart_location (void)
g_free (local_uri);
}
g_print ("(%d test cases) ", i);
-
-
}
static void
@@ -160,8 +161,13 @@ test_mediaart_location_null (void)
gchar *path = NULL, *local_uri = NULL;
/* NULL parameters */
- media_art_get_path (NULL, NULL, "album", "file:///a/b/c.mp3", &path, &local_uri);
- g_assert (!path && !local_uri);
+ 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);
}
static void
@@ -192,35 +198,41 @@ test_mediaart_location_path (void)
static void
test_mediaart_embedded_mp3 (void)
{
+ MediaArtProcess *process;
GError *error = NULL;
GFile *file = NULL;
gchar *dir, *path;
gboolean retval;
- /* FIXME: Handle 'buffer' AND 'file/path', is broken currently */
-
dir = g_get_current_dir ();
path = g_build_filename (G_DIR_SEPARATOR_S, dir, "543249_King-Kilo---Radium.mp3", NULL);
file = g_file_new_for_path (path);
g_free (path);
- retval = media_art_process_file (NULL,
- 0,
- "audio/mp3", /* mime */
+ 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 */
- "Lanedo", /* title */
- file);
+ "Radium", /* title */
+ &error);
+ g_assert_no_error (error);
g_assert_true (retval);
g_object_unref (file);
g_free (dir);
+
+ g_object_unref (process);
}
static void
-test_mediaart_png (void)
+test_mediaart_process_buffer (void)
{
+ MediaArtProcess *process;
GError *error = NULL;
GFile *file = NULL;
gchar *dir, *path;
@@ -230,14 +242,17 @@ test_mediaart_png (void)
gboolean retval;
dir = g_get_current_dir ();
- path = g_build_filename (G_DIR_SEPARATOR_S, dir, "LanedoIconHKS43-64².png", NULL);
+ path = g_build_filename (G_DIR_SEPARATOR_S, dir, "cover.png", NULL);
file = g_file_new_for_path (path);
g_free (dir);
+ process = media_art_process_new (&error);
+ g_assert_no_error (error);
+
/* Check data is not cached currently */
media_art_get_path ("Lanedo", /* artist / title */
- NULL, /* album */
- NULL, /* prefix */
+ NULL, /* album */
+ NULL, /* prefix */
path,
&out_path,
&out_uri);
@@ -246,20 +261,20 @@ test_mediaart_png (void)
g_free (out_uri);
/* Process data */
- retval = media_art_process_file (NULL,
- 0,
- "image/png", /* mime */
+ retval = media_art_process_file (process,
MEDIA_ART_ALBUM,
- NULL, /* album */
- "Lanedo", /* title */
- file);
-
+ MEDIA_ART_PROCESS_FLAGS_NONE,
+ file,
+ NULL, /* album */
+ "Lanedo", /* title */
+ &error);
+ g_assert_no_error (error);
g_assert_true (retval);
/* Check cache exists */
media_art_get_path ("Lanedo", /* artist / title */
- NULL, /* album */
- NULL, /* prefix */
+ NULL, /* album */
+ NULL, /* prefix */
path,
&out_path,
&out_uri);
@@ -274,7 +289,7 @@ test_mediaart_png (void)
/* 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_assert (g_file_test (out_path, G_FILE_TEST_EXISTS) == TRUE);
g_free (out_path);
g_free (out_uri);
@@ -288,6 +303,70 @@ test_mediaart_png (void)
g_object_unref (file);
g_free (path);
+
+ g_object_unref (process);
+}
+
+static void
+test_mediaart_process_failures (void)
+{
+ MediaArtProcess *process;
+ GError *error = NULL;
+
+ 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*");
+
+ process = media_art_process_new (&error);
+ 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);
+
+ /* Test: Invalid mime type */
+ /* g_assert (!media_art_process_uri (process, */
+ /* "file:///invalid/path.png", */
+ /* NULL, */
+ /* 0, */
+ /* "image/png", /\* mime *\/ */
+ /* MEDIA_ART_ALBUM, */
+ /* "Foo", /\* album *\/ */
+ /* "Bar", /\* title *\/ */
+ /* &error)); */
+
+ /* g_message ("code:%d, domain:%d, error:'%s'\n", error->code, error->domain, error->message); */
+
+ g_object_unref (process);
+}
+
+static void
+test_mediaart_process_failures_subprocess (void)
+{
+ MediaArtProcess *process;
+ GError *error = NULL;
+
+ process = media_art_process_new (&error);
+ g_assert_no_error (error);
+
+ g_assert (!media_art_process_uri (process,
+ MEDIA_ART_ALBUM,
+ MEDIA_ART_PROCESS_FLAGS_NONE,
+ NULL,
+ "Foo", /* album */
+ "Bar", /* title */
+ &error));
+ g_assert_no_error (error);
+
+ g_object_unref (process);
}
int
@@ -297,8 +376,8 @@ main (int argc, char **argv)
g_test_init (&argc, &argv, NULL);
- g_test_add_func ("/mediaart/init",
- test_mediaart_init);
+ g_test_add_func ("/mediaart/new",
+ test_mediaart_new);
g_test_add_func ("/mediaart/stripping",
test_mediaart_stripping);
g_test_add_func ("/mediaart/stripping_failures",
@@ -313,12 +392,14 @@ main (int argc, char **argv)
test_mediaart_location_path);
g_test_add_func ("/mediaart/embedded_mp3",
test_mediaart_embedded_mp3);
- g_test_add_func ("/mediaart/png",
- test_mediaart_png);
+ 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 ();
- media_art_shutdown ();
-
return success;
}