commit 176836bb6ff3209ebf22ef8531e67b5c19c6f02e
Author: Tom Callaway <spot(a)fedoraproject.org>
Date: Fri Aug 31 16:08:48 2012 -0400
missing patch in rawhide
0001-audiocd-Port-to-libmusicbrainz5.patch | 2389 ++++++++++++++++++++++++++++
1 files changed, 2389 insertions(+), 0 deletions(-)
---
diff --git a/0001-audiocd-Port-to-libmusicbrainz5.patch
b/0001-audiocd-Port-to-libmusicbrainz5.patch
new file mode 100644
index 0000000..97ba8b6
--- /dev/null
+++ b/0001-audiocd-Port-to-libmusicbrainz5.patch
@@ -0,0 +1,2389 @@
+From 7b446d83ae2e201884d48f7189bae9dfd9a21464 Mon Sep 17 00:00:00 2001
+From: Bastien Nocera <hadess(a)hadess.net>
+Date: Wed, 29 Aug 2012 19:37:24 +0100
+Subject: [PATCH] audiocd: Port to libmusicbrainz5
+
+And remove support for version 3 and 4 as the service will be
+broken with those versions.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=677286
+---
+ configure.ac | 34 +-
+ plugins/audiocd/Makefile.am | 20 +-
+ plugins/audiocd/sj-error.c | 6 +-
+ plugins/audiocd/sj-error.h | 2 +-
+ plugins/audiocd/sj-metadata-getter.c | 38 +-
+ plugins/audiocd/sj-metadata-gvfs.c | 2 +-
+ plugins/audiocd/sj-metadata-musicbrainz3.c | 460 ------------------
+ plugins/audiocd/sj-metadata-musicbrainz3.h | 56 ---
+ plugins/audiocd/sj-metadata-musicbrainz4.c | 615 -----------------------
+ plugins/audiocd/sj-metadata-musicbrainz4.h | 56 ---
+ plugins/audiocd/sj-metadata-musicbrainz5.c | 756 +++++++++++++++++++++++++++++
+ plugins/audiocd/sj-metadata-musicbrainz5.h | 56 +++
+ plugins/audiocd/sj-metadata.c | 2 +-
+ plugins/audiocd/sj-structures.c | 11 +-
+ plugins/audiocd/sj-structures.h | 6 +-
+ 15 files changed, 854 insertions(+), 1266 deletions(-)
+ delete mode 100644 plugins/audiocd/sj-metadata-musicbrainz3.c
+ delete mode 100644 plugins/audiocd/sj-metadata-musicbrainz3.h
+ delete mode 100644 plugins/audiocd/sj-metadata-musicbrainz4.c
+ delete mode 100644 plugins/audiocd/sj-metadata-musicbrainz4.h
+ create mode 100644 plugins/audiocd/sj-metadata-musicbrainz5.c
+ create mode 100644 plugins/audiocd/sj-metadata-musicbrainz5.h
+
+diff --git a/configure.ac b/configure.ac
+index 33efca8..0687796 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -351,39 +351,21 @@ have_sj_metadata_getter=no
+ AC_ARG_ENABLE(musicbrainz, AC_HELP_STRING([--disable-musicbrainz],
+ [build without MusicBrainz support]))
+ if test x"$enable_musicbrainz" != "xno"; then
+- PKG_CHECK_MODULES(MUSICBRAINZ3, libmusicbrainz3 >= $MUSICBRAINZ3_REQS gconf-2.0,
[have_musicbrainz3=yes], [have_musicbrainz3=no])
+- AC_SUBST(MUSICBRAINZ3_CFLAGS)
+- AC_SUBST(MUSICBRAINZ3_LIBS)
++ PKG_CHECK_MODULES(MUSICBRAINZ5, libmusicbrainz5 >= $MUSICBRAINZ5_REQS libdiscid
gconf-2.0, [have_musicbrainz5=yes], [have_musicbrainz5=no])
++ AC_SUBST(MUSICBRAINZ5_CFLAGS)
++ AC_SUBST(MUSICBRAINZ5_LIBS)
+
+- PKG_CHECK_MODULES(MUSICBRAINZ4, libmusicbrainz4 >= $MUSICBRAINZ4_REQS gconf-2.0,
[have_musicbrainz4=yes], [have_musicbrainz4=no])
+- AC_SUBST(MUSICBRAINZ4_CFLAGS)
+- AC_SUBST(MUSICBRAINZ4_LIBS)
+-
+- if test x"$have_musicbrainz3" = xyes; then
+- oldlibs=$LIBS
+- LIBS="$LIBS $MUSICBRAINZ3_LIBS"
+- AC_CHECK_FUNCS(mb_extract_uuid)
+- LIBS="$oldlibs"
+-
+- AC_DEFINE([HAVE_MUSICBRAINZ3], 1, [Whether libmusicbrainz3 is available])
++ if test x"$have_musicbrainz5" = xyes; then
+ have_sj_metadata_getter=yes
+- fi
+-
+- if test x"$have_musicbrainz4" = xyes; then
+- AC_DEFINE([HAVE_MUSICBRAINZ4], 1, [Whether libmusicbrainz4 is available])
+- have_sj_metadata_getter=yes
+- fi
+-
+- if test x"$have_sj_metadata_getter" = xyes; then
+ AC_DEFINE([HAVE_SJ_METADATA_GETTER], 1, [Whether to use the sound-juicer metadata
getter code])
++ AC_DEFINE([HAVE_MUSICBRAINZ5], 1, [Whether libmusicbrainz5 is available])
+ else
+ if test x"$enable_musicbrainz" = xyes; then
+- AC_MSG_ERROR([MusicBrainz requested, but neither libmusicbrainz3 nor libmusicbrainz4
are available])
++ AC_MSG_ERROR([MusicBrainz requested, but libmusicbrainz5 is not available])
+ fi
+ fi
+ fi
+-AM_CONDITIONAL([HAVE_MUSICBRAINZ3], [test "x$have_musicbrainz3" =
"xyes"])
+-AM_CONDITIONAL([HAVE_MUSICBRAINZ4], [test "x$have_musicbrainz4" =
"xyes"])
++AM_CONDITIONAL([HAVE_MUSICBRAINZ5], [test "x$have_musicbrainz5" =
"xyes"])
+ AM_CONDITIONAL([HAVE_SJ_METADATA_GETTER], [test "x$have_sj_metadata_getter" =
"xyes"])
+
+ AC_PATH_XTRA
+@@ -900,7 +882,7 @@ else
+ AC_MSG_NOTICE([** Multimedia keys support is enabled])
+ fi
+
+-if test x"$have_musicbrainz3" = "xyes"; then
++if test x"$have_musicbrainz5" = "xyes"; then
+ AC_MSG_NOTICE([** MusicBrainz support is enabled])
+ else
+ AC_MSG_NOTICE([ MusicBrainz support is disabled])
+diff --git a/plugins/audiocd/Makefile.am b/plugins/audiocd/Makefile.am
+index e757d2d..667bb99 100644
+--- a/plugins/audiocd/Makefile.am
++++ b/plugins/audiocd/Makefile.am
+@@ -42,13 +42,9 @@ INCLUDES = \
+ -DUSE_TOTEM_PL_PARSER \
+ -D_BSD_SOURCE
+
+-if HAVE_MUSICBRAINZ3
+-libaudiocd_la_LIBADD +=$(MUSICBRAINZ3_LIBS)
+-INCLUDES += $(MUSICBRAINZ3_CFLAGS)
+-endif
+-if HAVE_MUSICBRAINZ4
+-libaudiocd_la_LIBADD +=$(MUSICBRAINZ4_LIBS)
+-INCLUDES += $(MUSICBRAINZ4_CFLAGS)
++if HAVE_MUSICBRAINZ5
++libaudiocd_la_LIBADD +=$(MUSICBRAINZ5_LIBS)
++INCLUDES += $(MUSICBRAINZ5_CFLAGS)
+ endif
+
+ libaudiocd_la_LIBADD += $(NULL)
+@@ -75,8 +71,7 @@ SJ_FILES = \
+ sj-metadata.c sj-metadata.h \
+ sj-metadata-gvfs.c sj-metadata-gvfs.h \
+ sj-metadata-getter.c sj-metadata-getter.h \
+- sj-metadata-musicbrainz3.c sj-metadata-musicbrainz3.h \
+- sj-metadata-musicbrainz4.c sj-metadata-musicbrainz4.h \
++ sj-metadata-musicbrainz5.c sj-metadata-musicbrainz5.h \
+ sj-structures.c sj-structures.h \
+ sj-metadata-marshal.list
+
+@@ -95,11 +90,8 @@ libaudiocd_la_SOURCES += \
+ sj-error.h sj-error.c \
+ $(MARSHALFILES)
+
+-if HAVE_MUSICBRAINZ3
+-libaudiocd_la_SOURCES += sj-metadata-musicbrainz3.c sj-metadata-musicbrainz3.h
+-endif
+-if HAVE_MUSICBRAINZ4
+-libaudiocd_la_SOURCES += sj-metadata-musicbrainz4.c sj-metadata-musicbrainz4.h
++if HAVE_MUSICBRAINZ5
++libaudiocd_la_SOURCES += sj-metadata-musicbrainz5.c sj-metadata-musicbrainz5.h
+ endif
+
+ MARSHALFILES += sj-metadata-marshal.h sj-metadata-marshal.c
+diff --git a/plugins/audiocd/sj-error.c b/plugins/audiocd/sj-error.c
+index 76d691c..dc1f5de 100644
+--- a/plugins/audiocd/sj-error.c
++++ b/plugins/audiocd/sj-error.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * Copyright (C) 2003 Ross Burton <ross(a)burtonini.com>
+ *
+ * Sound Juicer - sj-error.c
+@@ -26,9 +26,9 @@
+ #include "sj-error.h"
+
+ GQuark
+-sj_error_quark (void)
++sj_error_quark (void)
+ {
+- static GQuark q = 0;
++ static GQuark q = 0;
+ if (q == 0) {
+ q = g_quark_from_static_string ("sj-error-quark");
+ }
+diff --git a/plugins/audiocd/sj-error.h b/plugins/audiocd/sj-error.h
+index 3d8e94e..f1961a1 100644
+--- a/plugins/audiocd/sj-error.h
++++ b/plugins/audiocd/sj-error.h
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * Copyright (C) 2003 Ross Burton <ross(a)burtonini.com>
+ *
+ * Sound Juicer - sj-error.h
+diff --git a/plugins/audiocd/sj-metadata-getter.c b/plugins/audiocd/sj-metadata-getter.c
+index cfc447d..2d27055 100644
+--- a/plugins/audiocd/sj-metadata-getter.c
++++ b/plugins/audiocd/sj-metadata-getter.c
+@@ -26,15 +26,9 @@
+ #include "sj-metadata-getter.h"
+ #include "sj-metadata-marshal.h"
+ #include "sj-metadata.h"
+-#ifdef HAVE_MUSICBRAINZ4
+-#include "sj-metadata-musicbrainz4.h"
+-#endif /* HAVE_MUSICBRAINZ4 */
+-#ifdef HAVE_MUSICBRAINZ3
+-#include "sj-metadata-musicbrainz3.h"
+-#endif /* HAVE_MUSICBRAINZ3 */
+-#ifdef HAVE_MUSICBRAINZ
+-#include "sj-metadata-musicbrainz.h"
+-#endif /* HAVE_MUSICBRAINZ */
++#ifdef HAVE_MUSICBRAINZ5
++#include "sj-metadata-musicbrainz5.h"
++#endif /* HAVE_MUSICBRAINZ5 */
+ #include "sj-metadata-gvfs.h"
+ #include "sj-error.h"
+
+@@ -94,7 +88,7 @@ static void
+ sj_metadata_getter_finalize (GObject *object)
+ {
+ SjMetadataGetterPrivate *priv = GETTER_PRIVATE (object);
+-
++
+ g_free (priv->url);
+ g_free (priv->cdrom);
+ g_free (priv->proxy_host);
+@@ -178,15 +172,9 @@ lookup_cd (SjMetadataGetter *mdg)
+ GError *error = NULL;
+ gboolean found = FALSE;
+ GType types[] = {
+-#ifdef HAVE_MUSICBRAINZ4
+- SJ_TYPE_METADATA_MUSICBRAINZ4,
+-#endif /* HAVE_MUSICBRAINZ4 */
+-#ifdef HAVE_MUSICBRAINZ3
+- SJ_TYPE_METADATA_MUSICBRAINZ3,
+-#endif /* HAVE_MUSICBRAINZ3 */
+-#ifdef HAVE_MUSICBRAINZ
+- SJ_TYPE_METADATA_MUSICBRAINZ,
+-#endif /* HAVE_MUSICBRAINZ */
++#ifdef HAVE_MUSICBRAINZ5
++ SJ_TYPE_METADATA_MUSICBRAINZ5,
++#endif /* HAVE_MUSICBRAINZ5 */
+ SJ_TYPE_METADATA_GVFS
+ };
+
+@@ -215,7 +203,7 @@ lookup_cd (SjMetadataGetter *mdg)
+ signal = g_new0 (SjMetadataGetterSignal, 1);
+ signal->albums = albums;
+ signal->mdg = g_object_ref (mdg);
+- signal->metadata = g_object_ref (metadata);
++ signal->metadata = metadata;
+ g_idle_add ((GSourceFunc)fire_signal_idle, signal);
+ break;
+ }
+@@ -246,15 +234,7 @@ sj_metadata_getter_list_albums (SjMetadataGetter *mdg, GError
**error)
+ GThread *thread;
+
+ g_object_ref (mdg);
+- thread = g_thread_create ((GThreadFunc)lookup_cd, mdg, TRUE, error);
+- if (thread == NULL) {
+- g_set_error (error,
+- SJ_ERROR, SJ_ERROR_INTERNAL_ERROR,
+- _("Could not create CD lookup thread"));
+- g_object_unref (mdg);
+- return FALSE;
+- }
+-
++ g_thread_new ("sj-list-albums", (GThreadFunc)lookup_cd, mdg);
+ return TRUE;
+ }
+
+diff --git a/plugins/audiocd/sj-metadata-gvfs.c b/plugins/audiocd/sj-metadata-gvfs.c
+index 0c05a80..961fe39 100644
+--- a/plugins/audiocd/sj-metadata-gvfs.c
++++ b/plugins/audiocd/sj-metadata-gvfs.c
+@@ -232,7 +232,7 @@ static void
+ metadata_iface_init (gpointer g_iface, gpointer iface_data)
+ {
+ SjMetadataClass *klass = (SjMetadataClass*)g_iface;
+-
++
+ klass->list_albums = gvfs_list_albums;
+ }
+
+diff --git a/plugins/audiocd/sj-metadata-musicbrainz3.c
b/plugins/audiocd/sj-metadata-musicbrainz3.c
+deleted file mode 100644
+index ee96946..0000000
+--- a/plugins/audiocd/sj-metadata-musicbrainz3.c
++++ /dev/null
+@@ -1,460 +0,0 @@
+-/*
+- * sj-metadata-musicbrainz3.c
+- * Copyright (C) 2008 Ross Burton <ross(a)burtonini.com>
+- * Copyright (C) 2008 Bastien Nocera <hadess(a)hadess.net>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+- * Boston, MA 02111-1307, USA.
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif /* HAVE_CONFIG_H */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <glib.h>
+-#include <glib-object.h>
+-#include <gconf/gconf-client.h>
+-#include <musicbrainz3/mb_c.h>
+-
+-#include "sj-metadata-musicbrainz3.h"
+-#include "sj-structures.h"
+-#include "sj-error.h"
+-
+-#define GET(field, function, obj) { \
+- function (obj, buffer, sizeof (buffer)); \
+- if (field) \
+- g_free (field); \
+- if (*buffer == '\0') \
+- field = NULL; \
+- else \
+- field = g_strdup (buffer); \
+-}
+-
+-#if HAVE_MB_EXTRACT_UUID
+-#define GET_ID(field, function, obj) { \
+- char uuid_buffer[37]; \
+- function (obj, buffer, sizeof (buffer)); \
+- mb_extract_uuid (buffer, uuid_buffer, sizeof (uuid_buffer)); \
+- if (field) \
+- g_free (field); \
+- if (*uuid_buffer == '\0') \
+- field = NULL; \
+- else \
+- field = g_strdup (uuid_buffer); \
+-}
+-#else
+-#define GET_ID(field, function, obj) { \
+- if (field) \
+- g_free (field); \
+- field = NULL; \
+-}
+-#endif /* HAVE_MB_EXTRACT_UUID */
+-
+-#define GCONF_MUSICBRAINZ_SERVER "/apps/sound-juicer/musicbrainz_server"
+-#define GCONF_PROXY_USE_PROXY "/system/http_proxy/use_http_proxy"
+-#define GCONF_PROXY_HOST "/system/http_proxy/host"
+-#define GCONF_PROXY_PORT "/system/http_proxy/port"
+-#define GCONF_PROXY_USE_AUTHENTICATION
"/system/http_proxy/use_authentication"
+-#define GCONF_PROXY_USERNAME "/system/http_proxy/authentication_user"
+-#define GCONF_PROXY_PASSWORD "/system/http_proxy/authentication_password"
+-
+-typedef struct {
+- MbWebService mb;
+- MbDisc disc;
+- char *cdrom;
+- /* Proxy */
+- char *http_proxy;
+- int http_proxy_port;
+-} SjMetadataMusicbrainz3Private;
+-
+-#define GET_PRIVATE(o) \
+- (G_TYPE_INSTANCE_GET_PRIVATE ((o), SJ_TYPE_METADATA_MUSICBRAINZ3,
SjMetadataMusicbrainz3Private))
+-
+-enum {
+- PROP_0,
+- PROP_DEVICE,
+- PROP_USE_PROXY,
+- PROP_PROXY_HOST,
+- PROP_PROXY_PORT,
+-};
+-
+-static void metadata_interface_init (gpointer g_iface, gpointer iface_data);
+-
+-G_DEFINE_TYPE_WITH_CODE (SjMetadataMusicbrainz3,
+- sj_metadata_musicbrainz3,
+- G_TYPE_OBJECT,
+- G_IMPLEMENT_INTERFACE (SJ_TYPE_METADATA,
+- metadata_interface_init));
+-
+-
+-/*
+- * Private methods
+- */
+-
+-static AlbumDetails *
+-make_album_from_release (MbRelease *release)
+-{
+- AlbumDetails *album;
+- char buffer[512];
+- MbArtist artist;
+- char *new_title;
+- int i;
+-
+- g_assert (release);
+-
+- album = g_new0 (AlbumDetails, 1);
+-
+- GET_ID (album->album_id, mb_release_get_id, release);
+- GET (album->title, mb_release_get_title, release);
+- new_title = sj_metadata_helper_scan_disc_number (album->title,
&album->disc_number);
+- if (new_title) {
+- g_free (album->title);
+- album->title = new_title;
+- }
+-
+- artist = mb_release_get_artist (release);
+- GET_ID (album->artist_id, mb_artist_get_id, artist);
+- GET (album->artist, mb_artist_get_name, artist);
+- GET (album->artist_sortname, mb_artist_get_sortname, artist);
+-
+- if (mb_release_get_num_release_events (release) >= 1) {
+- MbReleaseEvent event;
+- char *date = NULL;
+-
+- event = mb_release_get_release_event (release, 0);
+- GET (date, mb_release_event_get_date, event);
+- album->release_date = sj_metadata_helper_scan_date (date);
+- g_free (date);
+- }
+-
+- album->number = mb_release_get_num_tracks (release);
+- GET (album->asin, mb_release_get_asin, release);
+-
+- for (i = 0; i < mb_release_get_num_relations (release); i++) {
+- MbRelation relation;
+- char *type = NULL;
+-
+- relation = mb_release_get_relation (release, i);
+- GET(type, mb_relation_get_type, relation);
+- if (type && g_str_equal (type,
"http://musicbrainz.org/ns/rel-1.0#Wikipedia")) {
+- GET (album->wikipedia, mb_relation_get_target_id, relation);
+- } else if (type && g_str_equal (type,
"http://musicbrainz.org/ns/rel-1.0#Discogs")) {
+- GET (album->discogs, mb_relation_get_target_id, relation);
+- continue;
+- }
+- g_free (type);
+- }
+-
+- for (i = 0; i < mb_release_get_num_types (release); i++) {
+- mb_release_get_type (release, i, buffer, sizeof(buffer));
+-
+- if (g_str_has_suffix (buffer, "#Spokenword")
+- || g_str_has_suffix (buffer, "#Interview")
+- || g_str_has_suffix (buffer, "#Audiobook")) {
+- album->is_spoken_word = TRUE;
+- break;
+- }
+- }
+-
+- for (i = 0; i < album->number; i++) {
+- MbTrack mbt;
+- TrackDetails *track;
+-
+- mbt = mb_release_get_track (release, i);
+- track = g_new0 (TrackDetails, 1);
+-
+- track->album = album;
+-
+- track->number = i + 1;
+- GET_ID (track->track_id, mb_track_get_id, mbt);
+-
+- GET (track->title, mb_track_get_title, mbt);
+- track->duration = mb_track_get_duration (mbt) / 1000;
+-
+- artist = mb_track_get_artist (mbt);
+- if (artist == NULL)
+- artist = mb_release_get_artist (release);
+- GET_ID (track->artist_id, mb_artist_get_id, artist);
+- GET (track->artist, mb_artist_get_name, artist);
+- GET (track->artist_sortname, mb_artist_get_sortname, artist);
+-
+- album->tracks = g_list_append (album->tracks, track);
+- }
+-
+- return album;
+-}
+-
+-static void
+-fill_empty_durations (MbDisc *disc, AlbumDetails *album)
+-{
+- if (disc == NULL)
+- return;
+-}
+-
+-static MbReleaseIncludes
+-get_release_includes (void)
+-{
+- MbReleaseIncludes includes;
+-
+- includes = mb_release_includes_new ();
+- includes = mb_release_includes_artist (includes);
+- includes = mb_release_includes_tracks (includes);
+- includes = mb_artist_includes_release_events (includes);
+- includes = mb_track_includes_url_relations (includes);
+-
+- return includes;
+-}
+-
+-/*
+- * Virtual methods
+- */
+-
+-static GList *
+-mb_list_albums (SjMetadata *metadata, char **url, GError **error)
+-{
+- SjMetadataMusicbrainz3Private *priv;
+- GList *albums = NULL;
+- MbQuery query;
+- MbReleaseFilter filter;
+- MbResultList results;
+- MbRelease release;
+- char *id = NULL;
+- char buffer[1024];
+- int i;
+- g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ3 (metadata), NULL);
+-
+- priv = GET_PRIVATE (metadata);
+-
+- if (sj_metadata_helper_check_media (priv->cdrom, error) == FALSE) {
+- return NULL;
+- }
+-
+- priv->disc = mb_read_disc (priv->cdrom);
+- if (priv->disc == NULL)
+- return NULL;
+-
+- if (url != NULL) {
+- mb_get_submission_url (priv->disc, NULL, 0, buffer, sizeof (buffer));
+- *url = g_strdup (buffer);
+- }
+-
+- if (g_getenv("MUSICBRAINZ_FORCE_DISC_ID")) {
+- id = g_strdup (g_getenv("MUSICBRAINZ_FORCE_DISC_ID"));
+- } else {
+- GET(id, mb_disc_get_id, priv->disc);
+- }
+-
+- query = mb_query_new (priv->mb, "sound-juicer");
+- filter = mb_release_filter_new ();
+- filter = mb_release_filter_disc_id (filter, id);
+- results = mb_query_get_releases (query, filter);
+- mb_release_filter_free (filter);
+- g_free (id);
+-
+- if (results == NULL) {
+- mb_query_free (query);
+- return NULL;
+- }
+-
+- if (mb_result_list_get_size (results) == 0) {
+- mb_result_list_free (results);
+- mb_query_free (query);
+- return NULL;
+- }
+-
+- for (i = 0; i < mb_result_list_get_size (results); i++) {
+- AlbumDetails *album;
+- MbReleaseIncludes includes;
+- char buffer[512];
+-
+- release = mb_result_list_get_release (results, i);
+- if(release) {
+- mb_release_get_id (release, buffer, sizeof (buffer));
+- includes = get_release_includes ();
+- release = mb_query_get_release_by_id (query, buffer, includes);
+- if(release) {
+- mb_release_includes_free (includes);
+- album = make_album_from_release (release);
+- album->metadata_source = SOURCE_MUSICBRAINZ;
+- fill_empty_durations (priv->disc, album);
+- albums = g_list_append (albums, album);
+- mb_release_free (release);
+- }
+- }
+- }
+- mb_result_list_free (results);
+- mb_query_free (query);
+-
+- return albums;
+-}
+-
+-/*
+- * GObject methods
+- */
+-
+-static void
+-metadata_interface_init (gpointer g_iface, gpointer iface_data)
+-{
+- SjMetadataClass *klass = (SjMetadataClass*)g_iface;
+-
+- klass->list_albums = mb_list_albums;
+-}
+-
+-static void
+-sj_metadata_musicbrainz3_init (SjMetadataMusicbrainz3 *self)
+-{
+- GConfClient *gconf_client;
+- gchar *server_name;
+-
+- SjMetadataMusicbrainz3Private *priv;
+-
+- priv = GET_PRIVATE (self);
+-
+- priv->mb = mb_webservice_new ();
+-
+- gconf_client = gconf_client_get_default ();
+-
+- server_name = gconf_client_get_string (gconf_client, GCONF_MUSICBRAINZ_SERVER, NULL);
+-
+- if (server_name && strcmp (server_name, "") != 0) {
+- mb_webservice_set_host (priv->mb, server_name);
+- }
+-
+- g_free (server_name);
+-
+- /* Set the HTTP proxy */
+- if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_PROXY, NULL)) {
+- char *proxy_host;
+- int port;
+-
+- proxy_host = gconf_client_get_string (gconf_client, GCONF_PROXY_HOST, NULL);
+- mb_webservice_set_proxy_host (priv->mb, proxy_host);
+- g_free (proxy_host);
+-
+- port = gconf_client_get_int (gconf_client, GCONF_PROXY_PORT, NULL);
+- mb_webservice_set_proxy_port (priv->mb, port);
+-
+- if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_AUTHENTICATION, NULL)) {
+- char *username, *password;
+-
+- username = gconf_client_get_string (gconf_client, GCONF_PROXY_USERNAME, NULL);
+- mb_webservice_set_proxy_username (priv->mb, username);
+- g_free (username);
+-
+- password = gconf_client_get_string (gconf_client, GCONF_PROXY_PASSWORD, NULL);
+- mb_webservice_set_proxy_password (priv->mb, password);
+- g_free (password);
+- }
+- }
+-
+- g_object_unref (gconf_client);
+-}
+-
+-static void
+-sj_metadata_musicbrainz3_get_property (GObject *object, guint property_id,
+- GValue *value, GParamSpec *pspec)
+-{
+- SjMetadataMusicbrainz3Private *priv = GET_PRIVATE (object);
+- g_assert (priv);
+-
+- switch (property_id) {
+- case PROP_DEVICE:
+- g_value_set_string (value, priv->cdrom);
+- break;
+- case PROP_PROXY_HOST:
+- g_value_set_string (value, priv->http_proxy);
+- break;
+- case PROP_PROXY_PORT:
+- g_value_set_int (value, priv->http_proxy_port);
+- break;
+- default:
+- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+- }
+-}
+-
+-static void
+-sj_metadata_musicbrainz3_set_property (GObject *object, guint property_id,
+- const GValue *value, GParamSpec *pspec)
+-{
+- SjMetadataMusicbrainz3Private *priv = GET_PRIVATE (object);
+- g_assert (priv);
+-
+- switch (property_id) {
+- case PROP_DEVICE:
+- if (priv->cdrom)
+- g_free (priv->cdrom);
+- priv->cdrom = g_value_dup_string (value);
+- break;
+- case PROP_PROXY_HOST:
+- if (priv->http_proxy) {
+- g_free (priv->http_proxy);
+- }
+- priv->http_proxy = g_value_dup_string (value);
+- /* TODO: check this unsets the proxy if NULL, or should we pass "" ? */
+- mb_webservice_set_proxy_host (priv->mb, priv->http_proxy);
+- break;
+- case PROP_PROXY_PORT:
+- priv->http_proxy_port = g_value_get_int (value);
+- mb_webservice_set_proxy_port (priv->mb, priv->http_proxy_port);
+- break;
+- default:
+- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+- }
+-}
+-
+-static void
+-sj_metadata_musicbrainz3_finalize (GObject *object)
+-{
+- SjMetadataMusicbrainz3Private *priv;
+-
+- priv = GET_PRIVATE (object);
+-
+- if (priv->mb != NULL) {
+- mb_webservice_free (priv->mb);
+- priv->mb = NULL;
+- }
+- g_free (priv->cdrom);
+-
+- G_OBJECT_CLASS (sj_metadata_musicbrainz3_parent_class)->finalize (object);
+-}
+-
+-static void
+-sj_metadata_musicbrainz3_class_init (SjMetadataMusicbrainz3Class *class)
+-{
+- GObjectClass *object_class = (GObjectClass*)class;
+-
+- g_type_class_add_private (class, sizeof (SjMetadataMusicbrainz3Private));
+-
+- object_class->get_property = sj_metadata_musicbrainz3_get_property;
+- object_class->set_property = sj_metadata_musicbrainz3_set_property;
+- object_class->finalize = sj_metadata_musicbrainz3_finalize;
+-
+- g_object_class_override_property (object_class, PROP_DEVICE, "device");
+- g_object_class_override_property (object_class, PROP_PROXY_HOST,
"proxy-host");
+- g_object_class_override_property (object_class, PROP_PROXY_PORT,
"proxy-port");
+-}
+-
+-
+-/*
+- * Public methods.
+- */
+-
+-GObject *
+-sj_metadata_musicbrainz3_new (void)
+-{
+- return g_object_new (SJ_TYPE_METADATA_MUSICBRAINZ3, NULL);
+-}
+diff --git a/plugins/audiocd/sj-metadata-musicbrainz3.h
b/plugins/audiocd/sj-metadata-musicbrainz3.h
+deleted file mode 100644
+index bcc337d..0000000
+--- a/plugins/audiocd/sj-metadata-musicbrainz3.h
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+- * sj-metadata-musicbrainz3.h
+- * Copyright (C) 2008 Ross Burton <ross(a)burtonini.com>
+- * Copyright (C) 2008 Bastien Nocera <hadess(a)hadess.net>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+- * Boston, MA 02111-1307, USA.
+- */
+-
+-#ifndef SJ_METADATA_MUSICBRAINZ3_H
+-#define SJ_METADATA_MUSICBRAINZ3_H
+-
+-#include <glib-object.h>
+-#include "sj-metadata.h"
+-
+-G_BEGIN_DECLS
+-
+-#define SJ_TYPE_METADATA_MUSICBRAINZ3 (sj_metadata_musicbrainz3_get_type ())
+-#define SJ_METADATA_MUSICBRAINZ3(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ3, SjMetadataMusicbrainz3))
+-#define SJ_METADATA_MUSICBRAINZ3_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable),
SJ_TYPE_METADATA_MUSICBRAINZ3, SjMetadataMusicbrainz3Class))
+-#define SJ_IS_METADATA_MUSICBRAINZ3(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ3))
+-#define SJ_IS_METADATA_MUSICBRAINZ3_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable),
SJ_TYPE_METADATA_MUSICBRAINZ3))
+-#define SJ_METADATA_MUSICBRAINZ3_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ3, SjMetadataMusicbrainz3Class))
+-
+-typedef struct _SjMetadataMusicbrainz3 SjMetadataMusicbrainz3;
+-typedef struct _SjMetadataMusicbrainz3Class SjMetadataMusicbrainz3Class;
+-
+-struct _SjMetadataMusicbrainz3
+-{
+- GObject parent;
+-};
+-
+-struct _SjMetadataMusicbrainz3Class
+-{
+- GObjectClass parent;
+-};
+-
+-GType sj_metadata_musicbrainz3_get_type (void);
+-
+-GObject *sj_metadata_musicbrainz3_new (void);
+-
+-G_END_DECLS
+-
+-#endif /* SJ_METADATA_MUSICBRAINZ3_H */
+diff --git a/plugins/audiocd/sj-metadata-musicbrainz4.c
b/plugins/audiocd/sj-metadata-musicbrainz4.c
+deleted file mode 100644
+index 573ef64..0000000
+--- a/plugins/audiocd/sj-metadata-musicbrainz4.c
++++ /dev/null
+@@ -1,615 +0,0 @@
+-/*
+- * sj-metadata-musicbrainz4.c
+- * Copyright (C) 2008 Ross Burton <ross(a)burtonini.com>
+- * Copyright (C) 2008 Bastien Nocera <hadess(a)hadess.net>
+- * Copyright (C) 2011 Christophe Fergeau <cfergeau(a)redhat.com>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+- * Boston, MA 02111-1307, USA.
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif /* HAVE_CONFIG_H */
+-
+-#include <string.h>
+-#include <stdlib.h>
+-#include <glib.h>
+-#include <glib-object.h>
+-#include <gconf/gconf-client.h>
+-#include <discid/discid.h>
+-#include <musicbrainz4/mb4_c.h>
+-
+-#include "sj-metadata-musicbrainz4.h"
+-#include "sj-structures.h"
+-#include "sj-error.h"
+-
+-#define GET(field, function, obj) { \
+- function (obj, buffer, sizeof (buffer)); \
+- if (field) \
+- g_free (field); \
+- if (*buffer == '\0') \
+- field = NULL; \
+- else \
+- field = g_strdup (buffer); \
+-}
+-
+-#define GCONF_MUSICBRAINZ_SERVER "/apps/sound-juicer/musicbrainz_server"
+-#define GCONF_PROXY_USE_PROXY "/system/http_proxy/use_http_proxy"
+-#define GCONF_PROXY_HOST "/system/http_proxy/host"
+-#define GCONF_PROXY_PORT "/system/http_proxy/port"
+-#define GCONF_PROXY_USE_AUTHENTICATION
"/system/http_proxy/use_authentication"
+-#define GCONF_PROXY_USERNAME "/system/http_proxy/authentication_user"
+-#define GCONF_PROXY_PASSWORD "/system/http_proxy/authentication_password"
+-#define SJ_MUSICBRAINZ_USER_AGENT "libjuicer-"VERSION
+-
+-typedef struct {
+- Mb4Query mb;
+- DiscId *disc;
+- char *cdrom;
+- /* Proxy */
+- char *http_proxy;
+- int http_proxy_port;
+-} SjMetadataMusicbrainz4Private;
+-
+-#define GET_PRIVATE(o) \
+- (G_TYPE_INSTANCE_GET_PRIVATE ((o), SJ_TYPE_METADATA_MUSICBRAINZ4,
SjMetadataMusicbrainz4Private))
+-
+-enum {
+- PROP_0,
+- PROP_DEVICE,
+- PROP_USE_PROXY,
+- PROP_PROXY_HOST,
+- PROP_PROXY_PORT,
+-};
+-
+-static void metadata_interface_init (gpointer g_iface, gpointer iface_data);
+-
+-G_DEFINE_TYPE_WITH_CODE (SjMetadataMusicbrainz4,
+- sj_metadata_musicbrainz4,
+- G_TYPE_OBJECT,
+- G_IMPLEMENT_INTERFACE (SJ_TYPE_METADATA,
+- metadata_interface_init));
+-
+-
+-/*
+- * Private methods
+- */
+-#ifdef DUMP_DETAILS
+-static void
+-sj_mb4_album_details_dump (AlbumDetails *details)
+-{
+- if (details->country)
+- g_print ("Country: %s\n", details->country);
+- if (details->type)
+- g_print ("Type: %s\n", details->type);
+- if (details->lyrics_url)
+- g_print ("Lyrics URL: %s\n", details->lyrics_url);
+-}
+-#else
+-#define sj_mb4_album_details_dump(...)
+-#endif
+-
+-static GList *
+-get_artist_list (Mb4ArtistCredit credit)
+-{
+- Mb4NameCreditList name_list;
+- GList *artists;
+- unsigned int i;
+- char buffer[512]; /* for the GET macro */
+-
+- if (credit == NULL)
+- return NULL;
+-
+- name_list = mb4_artistcredit_get_namecreditlist (credit);
+- if (name_list == NULL) {
+- return NULL;
+- }
+-
+- artists = NULL;
+- for (i = 0; i < mb4_namecredit_list_size (name_list); i++) {
+- Mb4NameCredit name_credit;
+- Mb4Artist artist;
+- ArtistDetails *details;
+-
+- name_credit = mb4_namecredit_list_item (name_list, i);
+- details = g_new0 (ArtistDetails, 1);
+- GET (details->joinphrase, mb4_namecredit_get_joinphrase, name_credit);
+- artists = g_list_prepend (artists, details);
+- artist = mb4_namecredit_get_artist (name_credit);
+- if (!artist) {
+- g_warning ("no Mb4Artist associated with Mb4NameCredit, falling back to
Mb4NameCredit::name");
+- GET (details->name, mb4_namecredit_get_name, name_credit);
+- continue;
+- }
+-
+- GET (details->id, mb4_artist_get_id, artist);
+- GET (details->name, mb4_artist_get_name, artist);
+- GET (details->sortname, mb4_artist_get_sortname, artist);
+- GET (details->disambiguation, mb4_artist_get_disambiguation, artist);
+- GET (details->gender, mb4_artist_get_gender, artist);
+- GET (details->country, mb4_artist_get_country, artist);
+- }
+-
+- return g_list_reverse(artists);
+-}
+-
+-static void
+-get_artist_info (GList *artists, char **name, char **sortname, char **id)
+-{
+- GString *artist_name;
+- GList *it;
+- unsigned int artist_count;
+-
+- artist_name = g_string_new (NULL);
+- artist_count = 0;
+- for (it = artists; it != NULL; it = it->next) {
+- ArtistDetails *details = (ArtistDetails *)it->data;
+- artist_count++;
+- g_string_append (artist_name, details->name);
+- if (details->joinphrase != NULL)
+- g_string_append (artist_name, details->joinphrase);
+- }
+-
+- if (artist_count != 1) {
+- g_warning ("multiple artists");
+- if (sortname != NULL)
+- *sortname = NULL;
+- if (id != NULL)
+- *id = NULL;
+- } else {
+- ArtistDetails *details = (ArtistDetails *)artists->data;
+- if (sortname != NULL)
+- *sortname = g_strdup (details->sortname);
+- if (id != NULL)
+- *id = g_strdup (details->id);
+- }
+-
+- if (name != NULL)
+- *name = artist_name->str;
+-
+- g_string_free (artist_name, FALSE);
+-}
+-
+-
+-static void
+-fill_relations (Mb4RelationList relations, AlbumDetails *album)
+-{
+- unsigned int i;
+-
+- for (i = 0; i < mb4_relation_list_size (relations); i++) {
+- Mb4Relation relation;
+- char buffer[512]; /* for the GET() macro */
+- char *type = NULL;
+-
+- relation = mb4_relation_list_item (relations, i);
+- if (relation == NULL)
+- continue;
+-
+- GET (type, mb4_relation_get_type, relation);
+- if (type == NULL) {
+- continue;
+- }
+- if (g_str_equal (type, "wikipedia")) {
+- char *wikipedia = NULL;
+- GET (wikipedia, mb4_relation_get_target, relation);
+- if (wikipedia != NULL) {
+- g_free (album->wikipedia);
+- album->wikipedia = wikipedia;
+- }
+- } else if (g_str_equal (type, "discogs")) {
+- char *discogs = NULL;
+- GET (discogs, mb4_relation_get_target, relation);
+- if (discogs != NULL) {
+- g_free (album->discogs);
+- album->discogs = discogs;
+- }
+- } else if (g_str_equal (type, "lyrics")) {
+- char *lyrics = NULL;
+- GET (lyrics, mb4_relation_get_target, relation);
+- if (lyrics != NULL) {
+- g_free (album->lyrics_url);
+- album->lyrics_url = lyrics;
+- }
+- }
+- g_free (type);
+- }
+-}
+-
+-static void
+-fill_tracks_from_medium (Mb4Medium medium, AlbumDetails *album)
+-{
+- Mb4TrackList track_list;
+- GList *tracks;
+- unsigned int i;
+- char buffer[512]; /* for the GET() macro */
+-
+- track_list = mb4_medium_get_tracklist (medium);
+- if (!track_list)
+- return;
+-
+- album->number = mb4_track_list_size (track_list);
+-
+- tracks = NULL;
+-
+- for (i = 0; i < mb4_track_list_size (track_list); i++) {
+- Mb4Track mbt;
+- Mb4ArtistCredit credit;
+- Mb4Recording recording;
+- TrackDetails *track;
+-
+- mbt = mb4_track_list_item (track_list, i);
+- if (!mbt)
+- continue;
+-
+- track = g_new0 (TrackDetails, 1);
+-
+- track->album = album;
+-
+- track->number = mb4_track_get_position (mbt);
+- recording = mb4_track_get_recording (mbt);
+- if (recording != NULL) {
+- GET (track->title, mb4_recording_get_title, recording);
+- GET (track->track_id, mb4_recording_get_id, recording);
+- track->duration = mb4_recording_get_length (recording) / 1000;
+- credit = mb4_recording_get_artistcredit (recording);
+- } else {
+- GET (track->title, mb4_track_get_title, mbt);
+- track->duration = mb4_track_get_length (mbt) / 1000;
+- credit = mb4_track_get_artistcredit (mbt);
+- }
+-
+- if (credit) {
+- GList *artists;
+- artists = get_artist_list (credit);
+- if (artists) {
+- get_artist_info (artists, &track->artist,
+- &track->artist_sortname,
+- &track->artist_id);
+- }
+- track->artists = artists;
+- }
+- if (track->artist == NULL)
+- track->artist = g_strdup (album->artist);
+- if (track->artist_sortname == NULL)
+- track->artist_sortname = g_strdup (album->artist_sortname);
+- if (track->artist_id == NULL)
+- track->artist_id = g_strdup (album->artist_id);
+-
+- tracks = g_list_prepend (tracks, track);
+- }
+- album->tracks = g_list_reverse (tracks);
+-}
+-
+-static AlbumDetails *
+-make_album_from_release (Mb4ReleaseGroup group,
+- Mb4Release release,
+- Mb4Medium medium)
+-{
+- AlbumDetails *album;
+- Mb4ArtistCredit credit;
+- GList *artists;
+- char *date = NULL;
+- char buffer[512]; /* for the GET macro */
+-
+- g_assert (release);
+- g_return_val_if_fail (medium != NULL, NULL);
+-
+- album = g_new0 (AlbumDetails, 1);
+-
+- GET (album->album_id, mb4_release_get_id, release);
+- GET (album->title, mb4_medium_get_title, medium);
+- if (album->title == NULL)
+- GET (album->title, mb4_release_get_title, release);
+-
+- credit = mb4_release_get_artistcredit (release);
+-
+- artists = get_artist_list (credit);
+- if (artists) {
+- get_artist_info (artists, &album->artist,
+- &album->artist_sortname,
+- &album->artist_id);
+- }
+- album->artists = artists;
+-
+- GET (date, mb4_release_get_date, release);
+- album->release_date = sj_metadata_helper_scan_date (date);
+- g_free (date);
+-
+- GET (album->asin, mb4_release_get_asin, release);
+- GET (album->country, mb4_release_get_country, release);
+- if (group) {
+- GET (album->type, mb4_releasegroup_get_type, group);
+- if (g_str_has_suffix (album->type, "Spokenword")
+- || g_str_has_suffix (album->type, "Interview")
+- || g_str_has_suffix (album->type, "Audiobook")) {
+- album->is_spoken_word = TRUE;
+- }
+- fill_relations (mb4_releasegroup_get_relationlist(group), album);
+- }
+-
+- album->disc_number = mb4_medium_get_position (medium);
+- fill_tracks_from_medium (medium, album);
+- fill_relations (mb4_release_get_relationlist (release), album);
+-
+- sj_mb4_album_details_dump (album);
+- return album;
+-}
+-
+-/*
+- * Virtual methods
+- */
+-static GList *
+-mb4_list_albums (SjMetadata *metadata, char **url, GError **error)
+-{
+- SjMetadataMusicbrainz4Private *priv;
+- GList *albums = NULL;
+- Mb4ReleaseList releases;
+- Mb4Release release;
+- const char *discid = NULL;
+- char buffer[1024];
+- int i;
+- g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ4 (metadata), NULL);
+-
+- priv = GET_PRIVATE (metadata);
+-
+- if (sj_metadata_helper_check_media (priv->cdrom, error) == FALSE) {
+- return NULL;
+- }
+-
+- priv->disc = discid_new ();
+- if (priv->disc == NULL)
+- return NULL;
+- if (discid_read (priv->disc, priv->cdrom) == 0)
+- return NULL;
+-
+- if (url != NULL)
+- *url = g_strdup (discid_get_submission_url (priv->disc));
+-
+- if (g_getenv("MUSICBRAINZ_FORCE_DISC_ID")) {
+- discid = g_getenv("MUSICBRAINZ_FORCE_DISC_ID");
+- } else {
+- discid = discid_get_id (priv->disc);
+- }
+-
+- releases = mb4_query_lookup_discid(priv->mb, discid);
+-
+- if (releases == NULL) {
+- return NULL;
+- }
+-
+- if (mb4_release_list_size (releases) == 0) {
+- return NULL;
+- }
+-
+- for (i = 0; i < mb4_release_list_size (releases); i++) {
+- AlbumDetails *album;
+-
+- release = mb4_release_list_item (releases, i);
+- if (release) {
+- char *releaseid = NULL;
+- Mb4Release full_release;
+-
+- releaseid = NULL;
+- GET(releaseid, mb4_release_get_id, release);
+-
+- full_release = mb4_query_lookup_release (priv->mb, releaseid);
+- g_free (releaseid);
+- if (full_release) {
+- Mb4MediumList media;
+- Mb4Metadata metadata = NULL;
+- Mb4ReleaseGroup group;
+- unsigned int j;
+-
+- group = mb4_release_get_releasegroup (full_release);
+- if (group) {
+- /* The release-group information we can extract from the
+- * lookup_release query doesn't have the url relations for the
+- * release-group, so run a separate query to get these urls
+- */
+- char *releasegroupid = NULL;
+- char *params_names[] = { "inc" };
+- char *params_values[] = { "artists url-rels" };
+-
+- GET (releasegroupid, mb4_releasegroup_get_id, group);
+- metadata = mb4_query_query (priv->mb, "release-group",
releasegroupid, "",
+- 1, params_names, params_values);
+- g_free (releasegroupid);
+- }
+-
+- if (metadata && mb4_metadata_get_releasegroup (metadata))
+- group = mb4_metadata_get_releasegroup (metadata);
+-
+- media = mb4_release_media_matching_discid (full_release, discid);
+- for (j = 0; j < mb4_medium_list_size (media); j++) {
+- Mb4Medium medium;
+- medium = mb4_medium_list_item (media, j);
+- if (medium) {
+- album = make_album_from_release (group, full_release, medium);
+- album->metadata_source = SOURCE_MUSICBRAINZ;
+- albums = g_list_append (albums, album);
+- }
+- }
+- mb4_metadata_delete (metadata);
+- mb4_medium_list_delete (media);
+- mb4_release_delete (full_release);
+- }
+- }
+- }
+- mb4_release_list_delete (releases);
+- return albums;
+-}
+-
+-/*
+- * GObject methods
+- */
+-
+-static void
+-metadata_interface_init (gpointer g_iface, gpointer iface_data)
+-{
+- SjMetadataClass *klass = (SjMetadataClass*)g_iface;
+-
+- klass->list_albums = mb4_list_albums;
+-}
+-
+-static void
+-sj_metadata_musicbrainz4_init (SjMetadataMusicbrainz4 *self)
+-{
+- GConfClient *gconf_client;
+- gchar *server_name;
+-
+- SjMetadataMusicbrainz4Private *priv;
+-
+- priv = GET_PRIVATE (self);
+-
+- gconf_client = gconf_client_get_default ();
+-
+- server_name = gconf_client_get_string (gconf_client, GCONF_MUSICBRAINZ_SERVER, NULL);
+-
+- if (server_name && (*server_name == '\0')) {
+- g_free (server_name);
+- server_name = NULL;
+- }
+-
+- priv->mb = mb4_query_new (SJ_MUSICBRAINZ_USER_AGENT, server_name, 0);
+- g_free (server_name);
+-
+-
+- /* Set the HTTP proxy */
+- if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_PROXY, NULL)) {
+- char *proxy_host;
+- int port;
+-
+- proxy_host = gconf_client_get_string (gconf_client, GCONF_PROXY_HOST, NULL);
+- mb4_query_set_proxyhost (priv->mb, proxy_host);
+- g_free (proxy_host);
+-
+- port = gconf_client_get_int (gconf_client, GCONF_PROXY_PORT, NULL);
+- mb4_query_set_proxyport (priv->mb, port);
+-
+- if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_AUTHENTICATION, NULL)) {
+- char *username, *password;
+-
+- username = gconf_client_get_string (gconf_client, GCONF_PROXY_USERNAME, NULL);
+- mb4_query_set_proxyusername (priv->mb, username);
+- g_free (username);
+-
+- password = gconf_client_get_string (gconf_client, GCONF_PROXY_PASSWORD, NULL);
+- mb4_query_set_proxypassword (priv->mb, password);
+- g_free (password);
+- }
+- }
+-
+- g_object_unref (gconf_client);
+-}
+-
+-static void
+-sj_metadata_musicbrainz4_get_property (GObject *object, guint property_id,
+- GValue *value, GParamSpec *pspec)
+-{
+- SjMetadataMusicbrainz4Private *priv = GET_PRIVATE (object);
+- g_assert (priv);
+-
+- switch (property_id) {
+- case PROP_DEVICE:
+- g_value_set_string (value, priv->cdrom);
+- break;
+- case PROP_PROXY_HOST:
+- g_value_set_string (value, priv->http_proxy);
+- break;
+- case PROP_PROXY_PORT:
+- g_value_set_int (value, priv->http_proxy_port);
+- break;
+- default:
+- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+- }
+-}
+-
+-static void
+-sj_metadata_musicbrainz4_set_property (GObject *object, guint property_id,
+- const GValue *value, GParamSpec *pspec)
+-{
+- SjMetadataMusicbrainz4Private *priv = GET_PRIVATE (object);
+- g_assert (priv);
+-
+- switch (property_id) {
+- case PROP_DEVICE:
+- if (priv->cdrom)
+- g_free (priv->cdrom);
+- priv->cdrom = g_value_dup_string (value);
+- break;
+- case PROP_PROXY_HOST:
+- if (priv->http_proxy) {
+- g_free (priv->http_proxy);
+- }
+- priv->http_proxy = g_value_dup_string (value);
+- /* TODO: check this unsets the proxy if NULL, or should we pass "" ? */
+- mb4_query_set_proxyhost (priv->mb, priv->http_proxy);
+- break;
+- case PROP_PROXY_PORT:
+- priv->http_proxy_port = g_value_get_int (value);
+- mb4_query_set_proxyport (priv->mb, priv->http_proxy_port);
+- break;
+- default:
+- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+- }
+-}
+-
+-static void
+-sj_metadata_musicbrainz4_finalize (GObject *object)
+-{
+- SjMetadataMusicbrainz4Private *priv;
+-
+- priv = GET_PRIVATE (object);
+-
+- if (priv->mb != NULL) {
+- mb4_query_delete (priv->mb);
+- priv->mb = NULL;
+- }
+- if (priv->disc != NULL) {
+- discid_free (priv->disc);
+- priv->disc = NULL;
+- }
+- g_free (priv->cdrom);
+-
+- G_OBJECT_CLASS (sj_metadata_musicbrainz4_parent_class)->finalize (object);
+-}
+-
+-static void
+-sj_metadata_musicbrainz4_class_init (SjMetadataMusicbrainz4Class *class)
+-{
+- GObjectClass *object_class = (GObjectClass*)class;
+-
+- g_type_class_add_private (class, sizeof (SjMetadataMusicbrainz4Private));
+-
+- object_class->get_property = sj_metadata_musicbrainz4_get_property;
+- object_class->set_property = sj_metadata_musicbrainz4_set_property;
+- object_class->finalize = sj_metadata_musicbrainz4_finalize;
+-
+- g_object_class_override_property (object_class, PROP_DEVICE, "device");
+- g_object_class_override_property (object_class, PROP_PROXY_HOST,
"proxy-host");
+- g_object_class_override_property (object_class, PROP_PROXY_PORT,
"proxy-port");
+-}
+-
+-
+-/*
+- * Public methods.
+- */
+-
+-GObject *
+-sj_metadata_musicbrainz4_new (void)
+-{
+- return g_object_new (SJ_TYPE_METADATA_MUSICBRAINZ4, NULL);
+-}
+diff --git a/plugins/audiocd/sj-metadata-musicbrainz4.h
b/plugins/audiocd/sj-metadata-musicbrainz4.h
+deleted file mode 100644
+index 5a73e9b..0000000
+--- a/plugins/audiocd/sj-metadata-musicbrainz4.h
++++ /dev/null
+@@ -1,56 +0,0 @@
+-/*
+- * sj-metadata-musicbrainz4.h
+- * Copyright (C) 2008 Ross Burton <ross(a)burtonini.com>
+- * Copyright (C) 2008 Bastien Nocera <hadess(a)hadess.net>
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Library General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Library General Public License for more details.
+- *
+- * You should have received a copy of the GNU Library General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+- * Boston, MA 02111-1307, USA.
+- */
+-
+-#ifndef SJ_METADATA_MUSICBRAINZ4_H
+-#define SJ_METADATA_MUSICBRAINZ4_H
+-
+-#include <glib-object.h>
+-#include "sj-metadata.h"
+-
+-G_BEGIN_DECLS
+-
+-#define SJ_TYPE_METADATA_MUSICBRAINZ4 (sj_metadata_musicbrainz4_get_type ())
+-#define SJ_METADATA_MUSICBRAINZ4(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ4, SjMetadataMusicbrainz4))
+-#define SJ_METADATA_MUSICBRAINZ4_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable),
SJ_TYPE_METADATA_MUSICBRAINZ4, SjMetadataMusicbrainz4Class))
+-#define SJ_IS_METADATA_MUSICBRAINZ4(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ4))
+-#define SJ_IS_METADATA_MUSICBRAINZ4_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable),
SJ_TYPE_METADATA_MUSICBRAINZ4))
+-#define SJ_METADATA_MUSICBRAINZ4_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ4, SjMetadataMusicbrainz4Class))
+-
+-typedef struct _SjMetadataMusicbrainz4 SjMetadataMusicbrainz4;
+-typedef struct _SjMetadataMusicbrainz4Class SjMetadataMusicbrainz4Class;
+-
+-struct _SjMetadataMusicbrainz4
+-{
+- GObject parent;
+-};
+-
+-struct _SjMetadataMusicbrainz4Class
+-{
+- GObjectClass parent;
+-};
+-
+-GType sj_metadata_musicbrainz4_get_type (void);
+-
+-GObject *sj_metadata_musicbrainz4_new (void);
+-
+-G_END_DECLS
+-
+-#endif /* SJ_METADATA_MUSICBRAINZ4_H */
+diff --git a/plugins/audiocd/sj-metadata-musicbrainz5.c
b/plugins/audiocd/sj-metadata-musicbrainz5.c
+new file mode 100644
+index 0000000..cad2141
+--- /dev/null
++++ b/plugins/audiocd/sj-metadata-musicbrainz5.c
+@@ -0,0 +1,756 @@
++/*
++ * sj-metadata-musicbrainz5.c
++ * Copyright (C) 2008 Ross Burton <ross(a)burtonini.com>
++ * Copyright (C) 2008 Bastien Nocera <hadess(a)hadess.net>
++ * Copyright (C) 2011 Christophe Fergeau <cfergeau(a)redhat.com>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif /* HAVE_CONFIG_H */
++
++#include <string.h>
++#include <stdlib.h>
++#include <glib.h>
++#include <glib-object.h>
++#include <gconf/gconf-client.h>
++#include <discid/discid.h>
++#include <musicbrainz5/mb5_c.h>
++
++#include "sj-metadata-musicbrainz5.h"
++#include "sj-structures.h"
++#include "sj-error.h"
++
++#define GET(field, function, obj) { \
++ function (obj, buffer, sizeof (buffer)); \
++ if (field) \
++ g_free (field); \
++ if (*buffer == '\0') \
++ field = NULL; \
++ else \
++ field = g_strdup (buffer); \
++}
++
++#define GCONF_MUSICBRAINZ_SERVER "/apps/sound-juicer/musicbrainz_server"
++#define GCONF_PROXY_USE_PROXY "/system/http_proxy/use_http_proxy"
++#define GCONF_PROXY_HOST "/system/http_proxy/host"
++#define GCONF_PROXY_PORT "/system/http_proxy/port"
++#define GCONF_PROXY_USE_AUTHENTICATION
"/system/http_proxy/use_authentication"
++#define GCONF_PROXY_USERNAME "/system/http_proxy/authentication_user"
++#define GCONF_PROXY_PASSWORD "/system/http_proxy/authentication_password"
++#define SJ_MUSICBRAINZ_USER_AGENT "libjuicer-"VERSION
++
++typedef struct {
++ Mb5Query mb;
++ DiscId *disc;
++ char *cdrom;
++ /* Proxy */
++ char *http_proxy;
++ int http_proxy_port;
++} SjMetadataMusicbrainz5Private;
++
++#define GET_PRIVATE(o) \
++ (G_TYPE_INSTANCE_GET_PRIVATE ((o), SJ_TYPE_METADATA_MUSICBRAINZ5,
SjMetadataMusicbrainz5Private))
++
++enum {
++ PROP_0,
++ PROP_DEVICE,
++ PROP_USE_PROXY,
++ PROP_PROXY_HOST,
++ PROP_PROXY_PORT,
++};
++
++static void metadata_interface_init (gpointer g_iface, gpointer iface_data);
++
++G_DEFINE_TYPE_WITH_CODE (SjMetadataMusicbrainz5,
++ sj_metadata_musicbrainz5,
++ G_TYPE_OBJECT,
++ G_IMPLEMENT_INTERFACE (SJ_TYPE_METADATA,
++ metadata_interface_init));
++
++
++/*
++ * Private methods
++ */
++#ifdef DUMP_DETAILS
++static void
++sj_mb5_album_details_dump (AlbumDetails *details)
++{
++ if (details->country)
++ g_print ("Country: %s\n", details->country);
++ if (details->type)
++ g_print ("Type: %s\n", details->type);
++ if (details->lyrics_url)
++ g_print ("Lyrics URL: %s\n", details->lyrics_url);
++}
++#else
++#define sj_mb5_album_details_dump(...)
++#endif
++
++static GList *
++get_artist_list (Mb5ArtistCredit credit)
++{
++ Mb5NameCreditList name_list;
++ GList *artists;
++ unsigned int i;
++ char buffer[512]; /* for the GET macro */
++
++ if (credit == NULL)
++ return NULL;
++
++ name_list = mb5_artistcredit_get_namecreditlist (credit);
++ if (name_list == NULL) {
++ return NULL;
++ }
++
++ artists = NULL;
++ for (i = 0; i < mb5_namecredit_list_size (name_list); i++) {
++ Mb5NameCredit name_credit;
++ Mb5Artist artist;
++ ArtistDetails *details;
++
++ name_credit = mb5_namecredit_list_item (name_list, i);
++ details = g_new0 (ArtistDetails, 1);
++ GET (details->joinphrase, mb5_namecredit_get_joinphrase, name_credit);
++ artists = g_list_prepend (artists, details);
++ artist = mb5_namecredit_get_artist (name_credit);
++ if (!artist) {
++ g_warning ("no Mb5Artist associated with Mb5NameCredit, falling back to
Mb5NameCredit::name");
++ GET (details->name, mb5_namecredit_get_name, name_credit);
++ continue;
++ }
++
++ GET (details->id, mb5_artist_get_id, artist);
++ GET (details->name, mb5_artist_get_name, artist);
++ GET (details->sortname, mb5_artist_get_sortname, artist);
++ GET (details->disambiguation, mb5_artist_get_disambiguation, artist);
++ GET (details->gender, mb5_artist_get_gender, artist);
++ GET (details->country, mb5_artist_get_country, artist);
++ }
++
++ return g_list_reverse(artists);
++}
++
++static void
++get_artist_info (GList *artists, char **name, char **sortname, char **id)
++{
++ GString *artist_name;
++ GList *it;
++ unsigned int artist_count;
++
++ artist_name = g_string_new (NULL);
++ artist_count = 0;
++ for (it = artists; it != NULL; it = it->next) {
++ ArtistDetails *details = (ArtistDetails *)it->data;
++ artist_count++;
++ g_string_append (artist_name, details->name);
++ if (details->joinphrase != NULL)
++ g_string_append (artist_name, details->joinphrase);
++ }
++
++ if (artist_count != 1) {
++ g_warning ("multiple artists");
++ if (sortname != NULL)
++ *sortname = NULL;
++ if (id != NULL)
++ *id = NULL;
++ } else {
++ ArtistDetails *details = (ArtistDetails *)artists->data;
++ if (sortname != NULL)
++ *sortname = g_strdup (details->sortname);
++ if (id != NULL)
++ *id = g_strdup (details->id);
++ }
++
++ if (name != NULL)
++ *name = artist_name->str;
++
++ g_string_free (artist_name, FALSE);
++}
++
++static void
++fill_album_composer (AlbumDetails *album)
++{
++ char *old_composer;
++ GList *l;
++ TrackDetails *track_one; /* The first track on the album */
++ gboolean one_composer = TRUE; /* TRUE if all tracks have the same composer */
++
++ if (album->composer != NULL)
++ return;
++
++ if (album->tracks == NULL)
++ return;
++
++ l = album->tracks;
++ track_one = (TrackDetails*)l->data;
++ old_composer = track_one->composer;
++
++ for (l = l->next; l != NULL; l = l->next) {
++ char *new_composer;
++ TrackDetails *track = (TrackDetails*)l->data;
++ new_composer = track->composer;
++ if (g_strcmp0 (old_composer, new_composer) != 0) {
++ one_composer = FALSE;
++ break;
++ }
++ }
++
++ if (one_composer) {
++ album->composer = g_strdup (track_one->composer);
++ album->composer_sortname = g_strdup (track_one->composer_sortname);
++ } else {
++ album->composer = g_strdup ("Various Composers");
++ album->composer_sortname = g_strdup ("Various Composers");
++ }
++}
++
++typedef void (*RelationForeachFunc)(Mb5Relation relation, gpointer user_data);
++
++static void relationlist_list_foreach_relation(Mb5RelationListList relation_lists,
++ const char *targettype,
++ const char *relation_type,
++ RelationForeachFunc callback,
++ gpointer user_data)
++{
++ unsigned int j;
++
++ if (relation_lists == NULL)
++ return;
++
++ for (j = 0; j < mb5_relationlist_list_size (relation_lists); j++) {
++ Mb5RelationList relations;
++ char type[512]; /* To hold relationlist target-type and relation type */
++ unsigned int i;
++
++ relations = mb5_relationlist_list_item (relation_lists, j);
++ if (relations == NULL)
++ return;
++
++ mb5_relation_list_get_targettype (relations, type, sizeof (type));
++ if (!g_str_equal (type, targettype))
++ continue;
++
++ for (i = 0; i < mb5_relation_list_size (relations); i++) {
++ Mb5Relation relation;
++
++ relation = mb5_relation_list_item (relations, i);
++ if (relation == NULL)
++ continue;
++
++ mb5_relation_get_type (relation, type, sizeof (type));
++ if (!g_str_equal (type, relation_type))
++ continue;
++
++ callback(relation, user_data);
++ }
++ }
++}
++
++static void composer_cb (Mb5Relation relation, gpointer user_data)
++{
++ Mb5Artist composer;
++ TrackDetails *track = (TrackDetails *)user_data;
++ char buffer[512]; /* for the GET() macro */
++
++ composer = mb5_relation_get_artist (relation);
++ if (composer == NULL)
++ return;
++
++ GET (track->composer, mb5_artist_get_name, composer);
++ GET (track->composer_sortname, mb5_artist_get_sortname, composer);
++}
++
++static void work_cb (Mb5Relation relation, gpointer user_data)
++{
++ Mb5RelationListList relation_lists;
++ Mb5Work work;
++
++ work = mb5_relation_get_work (relation);
++ if (work == NULL)
++ return;
++ relation_lists = mb5_work_get_relationlistlist (work);
++ relationlist_list_foreach_relation (relation_lists, "artist",
"composer",
++ composer_cb, user_data);
++}
++
++static void
++fill_recording_relations (Mb5Recording recording, TrackDetails *track)
++{
++ Mb5RelationListList relation_lists;
++
++ relation_lists = mb5_recording_get_relationlistlist (recording);
++ relationlist_list_foreach_relation(relation_lists, "work",
"performance",
++ work_cb, track);
++}
++
++static void
++fill_tracks_from_medium (Mb5Medium medium, AlbumDetails *album)
++{
++ Mb5TrackList track_list;
++ GList *tracks;
++ unsigned int i;
++ char buffer[512]; /* for the GET() macro */
++
++ track_list = mb5_medium_get_tracklist (medium);
++ if (!track_list)
++ return;
++
++ album->number = mb5_track_list_size (track_list);
++
++ tracks = NULL;
++
++ for (i = 0; i < mb5_track_list_size (track_list); i++) {
++ Mb5Track mbt;
++ Mb5ArtistCredit credit;
++ Mb5Recording recording;
++ TrackDetails *track;
++
++ mbt = mb5_track_list_item (track_list, i);
++ if (!mbt)
++ continue;
++
++ track = g_new0 (TrackDetails, 1);
++
++ track->album = album;
++
++ track->number = mb5_track_get_position (mbt);
++
++ /* duration from track is more reliable than from recording */
++ track->duration = mb5_track_get_length (mbt) / 1000;
++
++ recording = mb5_track_get_recording (mbt);
++ if (recording != NULL) {
++ GET (track->title, mb5_recording_get_title, recording);
++ GET (track->track_id, mb5_recording_get_id, recording);
++ fill_recording_relations (recording, track);
++ if (track->duration == 0)
++ track->duration = mb5_recording_get_length (recording) / 1000;
++ credit = mb5_recording_get_artistcredit (recording);
++ } else {
++ GET (track->title, mb5_track_get_title, mbt);
++ credit = mb5_track_get_artistcredit (mbt);
++ }
++
++ if (credit) {
++ GList *artists;
++ artists = get_artist_list (credit);
++ if (artists) {
++ get_artist_info (artists, &track->artist,
++ &track->artist_sortname,
++ &track->artist_id);
++ }
++ track->artists = artists;
++ }
++ if (track->artist == NULL)
++ track->artist = g_strdup (album->artist);
++ if (track->artist_sortname == NULL)
++ track->artist_sortname = g_strdup (album->artist_sortname);
++ if (track->artist_id == NULL)
++ track->artist_id = g_strdup (album->artist_id);
++
++ tracks = g_list_prepend (tracks, track);
++ }
++ album->tracks = g_list_reverse (tracks);
++}
++
++static void wikipedia_cb (Mb5Relation relation, gpointer user_data)
++{
++ AlbumDetails *album = (AlbumDetails *)user_data;
++ char buffer[512]; /* for the GET() macro */
++ char *wikipedia = NULL;
++
++ GET (wikipedia, mb5_relation_get_target, relation);
++ if (wikipedia != NULL) {
++ g_free (album->wikipedia);
++ album->wikipedia = wikipedia;
++ }
++}
++
++static void discogs_cb (Mb5Relation relation, gpointer user_data)
++{
++ AlbumDetails *album = (AlbumDetails *)user_data;
++ char buffer[512]; /* for the GET() macro */
++ char *discogs = NULL;
++
++ GET (discogs, mb5_relation_get_target, relation);
++ if (discogs != NULL) {
++ g_free (album->discogs);
++ album->discogs = discogs;
++ }
++}
++
++static void lyrics_cb (Mb5Relation relation, gpointer user_data)
++{
++ AlbumDetails *album = (AlbumDetails *)user_data;
++ char buffer[512]; /* for the GET() macro */
++ char *lyrics = NULL;
++
++ GET (lyrics, mb5_relation_get_target, relation);
++ if (lyrics != NULL) {
++ g_free (album->lyrics_url);
++ album->lyrics_url = lyrics;
++ }
++}
++
++static void
++fill_relations (Mb5RelationListList relation_lists, AlbumDetails *album)
++{
++ relationlist_list_foreach_relation (relation_lists, "url",
"wikipedia",
++ wikipedia_cb, album);
++ relationlist_list_foreach_relation (relation_lists, "url",
"discogs",
++ discogs_cb, album);
++ relationlist_list_foreach_relation (relation_lists, "url",
"lyrics",
++ lyrics_cb, album);
++}
++
++static AlbumDetails *
++make_album_from_release (Mb5ReleaseGroup group,
++ Mb5Release release,
++ Mb5Medium medium)
++{
++ AlbumDetails *album;
++ Mb5ArtistCredit credit;
++ Mb5RelationListList relationlists;
++ GList *artists;
++ char *date = NULL;
++ char buffer[512]; /* for the GET macro */
++
++ g_assert (release);
++ g_return_val_if_fail (medium != NULL, NULL);
++
++ album = g_new0 (AlbumDetails, 1);
++
++ GET (album->album_id, mb5_release_get_id, release);
++ GET (album->title, mb5_medium_get_title, medium);
++ if (album->title == NULL)
++ GET (album->title, mb5_release_get_title, release);
++
++ credit = mb5_release_get_artistcredit (release);
++
++ artists = get_artist_list (credit);
++ if (artists) {
++ get_artist_info (artists, &album->artist,
++ &album->artist_sortname,
++ &album->artist_id);
++ }
++ album->artists = artists;
++
++ GET (date, mb5_release_get_date, release);
++ album->release_date = sj_metadata_helper_scan_date (date);
++ g_free (date);
++
++ GET (album->asin, mb5_release_get_asin, release);
++ GET (album->country, mb5_release_get_country, release);
++ if (group) {
++ GET (album->type, mb5_releasegroup_get_primarytype, group);
++ if (g_str_has_suffix (album->type, "Spokenword")
++ || g_str_has_suffix (album->type, "Interview")
++ || g_str_has_suffix (album->type, "Audiobook")) {
++ album->is_spoken_word = TRUE;
++ }
++ relationlists = mb5_releasegroup_get_relationlistlist (group);
++ fill_relations (relationlists, album);
++ }
++
++ album->disc_number = mb5_medium_get_position (medium);
++ fill_tracks_from_medium (medium, album);
++ fill_album_composer (album);
++ relationlists = mb5_release_get_relationlistlist (release);
++ fill_relations (relationlists, album);
++
++ sj_mb5_album_details_dump (album);
++ return album;
++}
++
++/*
++ * Virtual methods
++ */
++static GList *
++mb5_list_albums (SjMetadata *metadata, char **url, GError **error)
++{
++ SjMetadataMusicbrainz5Private *priv;
++ GList *albums = NULL;
++ Mb5ReleaseList releases;
++ Mb5Release release;
++ const char *discid = NULL;
++ char buffer[1024];
++ int i;
++ g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ5 (metadata), NULL);
++
++ priv = GET_PRIVATE (metadata);
++
++ if (sj_metadata_helper_check_media (priv->cdrom, error) == FALSE) {
++ return NULL;
++ }
++
++ priv->disc = discid_new ();
++ if (priv->disc == NULL)
++ return NULL;
++ if (discid_read (priv->disc, priv->cdrom) == 0)
++ return NULL;
++
++ if (url != NULL)
++ *url = g_strdup (discid_get_submission_url (priv->disc));
++
++ if (g_getenv("MUSICBRAINZ_FORCE_DISC_ID")) {
++ discid = g_getenv("MUSICBRAINZ_FORCE_DISC_ID");
++ } else {
++ discid = discid_get_id (priv->disc);
++ }
++
++ releases = mb5_query_lookup_discid(priv->mb, discid);
++
++ if (releases == NULL)
++ return NULL;
++
++ if (mb5_release_list_size (releases) == 0)
++ return NULL;
++
++ for (i = 0; i < mb5_release_list_size (releases); i++) {
++ AlbumDetails *album;
++
++ release = mb5_release_list_item (releases, i);
++ if (release) {
++ char *releaseid = NULL;
++ Mb5Release full_release = NULL;
++ Mb5Metadata release_md = NULL;
++ const char *query_entity = "release";
++ char *params_names[] = { "inc" };
++ char *params_values[] = { "artists artist-credits labels recordings \
++release-groups url-rels discids recording-level-rels work-level-rels work-rels \
++artist-rels" };
++
++ releaseid = NULL;
++ GET(releaseid, mb5_release_get_id, release);
++ /* Inorder to get metadata from work and composer relationships
++ * we need to perform a custom query
++ */
++ release_md = mb5_query_query (priv->mb, query_entity, releaseid, "",
1,
++ params_names, params_values);
++
++ if (release_md && mb5_metadata_get_release (release_md))
++ full_release = mb5_metadata_get_release (release_md);
++ g_free (releaseid);
++
++ if (full_release) {
++ Mb5MediumList media;
++ Mb5Metadata metadata = NULL;
++ Mb5ReleaseGroup group;
++ unsigned int j;
++
++ group = mb5_release_get_releasegroup (full_release);
++ if (group) {
++ /* The release-group information we can extract from the
++ * lookup_release query doesn't have the url relations for the
++ * release-group, so run a separate query to get these urls
++ */
++ char *releasegroupid = NULL;
++ char *params_names[] = { "inc" };
++ char *params_values[] = { "artists url-rels" };
++
++ GET (releasegroupid, mb5_releasegroup_get_id, group);
++ metadata = mb5_query_query (priv->mb, "release-group",
releasegroupid, "",
++ 1, params_names, params_values);
++ g_free (releasegroupid);
++ }
++
++ if (metadata && mb5_metadata_get_releasegroup (metadata))
++ group = mb5_metadata_get_releasegroup (metadata);
++
++ media = mb5_release_media_matching_discid (full_release, discid);
++ for (j = 0; j < mb5_medium_list_size (media); j++) {
++ Mb5Medium medium;
++ medium = mb5_medium_list_item (media, j);
++ if (medium) {
++ album = make_album_from_release (group, full_release, medium);
++ album->metadata_source = SOURCE_MUSICBRAINZ;
++ albums = g_list_append (albums, album);
++ }
++ }
++ mb5_metadata_delete (metadata);
++ mb5_medium_list_delete (media);
++ }
++ mb5_metadata_delete (release_md);
++ }
++ }
++ mb5_release_list_delete (releases);
++ return albums;
++}
++
++/*
++ * GObject methods
++ */
++
++static void
++metadata_interface_init (gpointer g_iface, gpointer iface_data)
++{
++ SjMetadataClass *klass = (SjMetadataClass*)g_iface;
++
++ klass->list_albums = mb5_list_albums;
++}
++
++static void
++sj_metadata_musicbrainz5_init (SjMetadataMusicbrainz5 *self)
++{
++ GConfClient *gconf_client;
++ gchar *server_name;
++
++ SjMetadataMusicbrainz5Private *priv;
++
++ priv = GET_PRIVATE (self);
++
++ gconf_client = gconf_client_get_default ();
++
++ server_name = gconf_client_get_string (gconf_client, GCONF_MUSICBRAINZ_SERVER, NULL);
++
++ if (server_name && (*server_name == '\0')) {
++ g_free (server_name);
++ server_name = NULL;
++ }
++
++ priv->mb = mb5_query_new (SJ_MUSICBRAINZ_USER_AGENT, server_name, 0);
++ g_free (server_name);
++
++
++ /* Set the HTTP proxy */
++ if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_PROXY, NULL)) {
++ char *proxy_host;
++ int port;
++
++ proxy_host = gconf_client_get_string (gconf_client, GCONF_PROXY_HOST, NULL);
++ mb5_query_set_proxyhost (priv->mb, proxy_host);
++ g_free (proxy_host);
++
++ port = gconf_client_get_int (gconf_client, GCONF_PROXY_PORT, NULL);
++ mb5_query_set_proxyport (priv->mb, port);
++
++ if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_AUTHENTICATION, NULL)) {
++ char *username, *password;
++
++ username = gconf_client_get_string (gconf_client, GCONF_PROXY_USERNAME, NULL);
++ mb5_query_set_proxyusername (priv->mb, username);
++ g_free (username);
++
++ password = gconf_client_get_string (gconf_client, GCONF_PROXY_PASSWORD, NULL);
++ mb5_query_set_proxypassword (priv->mb, password);
++ g_free (password);
++ }
++ }
++
++ g_object_unref (gconf_client);
++}
++
++static void
++sj_metadata_musicbrainz5_get_property (GObject *object, guint property_id,
++ GValue *value, GParamSpec *pspec)
++{
++ SjMetadataMusicbrainz5Private *priv = GET_PRIVATE (object);
++ g_assert (priv);
++
++ switch (property_id) {
++ case PROP_DEVICE:
++ g_value_set_string (value, priv->cdrom);
++ break;
++ case PROP_PROXY_HOST:
++ g_value_set_string (value, priv->http_proxy);
++ break;
++ case PROP_PROXY_PORT:
++ g_value_set_int (value, priv->http_proxy_port);
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
++ }
++}
++
++static void
++sj_metadata_musicbrainz5_set_property (GObject *object, guint property_id,
++ const GValue *value, GParamSpec *pspec)
++{
++ SjMetadataMusicbrainz5Private *priv = GET_PRIVATE (object);
++ g_assert (priv);
++
++ switch (property_id) {
++ case PROP_DEVICE:
++ if (priv->cdrom)
++ g_free (priv->cdrom);
++ priv->cdrom = g_value_dup_string (value);
++ break;
++ case PROP_PROXY_HOST:
++ if (priv->http_proxy) {
++ g_free (priv->http_proxy);
++ }
++ priv->http_proxy = g_value_dup_string (value);
++ /* TODO: check this unsets the proxy if NULL, or should we pass "" ? */
++ mb5_query_set_proxyhost (priv->mb, priv->http_proxy);
++ break;
++ case PROP_PROXY_PORT:
++ priv->http_proxy_port = g_value_get_int (value);
++ mb5_query_set_proxyport (priv->mb, priv->http_proxy_port);
++ break;
++ default:
++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
++ }
++}
++
++static void
++sj_metadata_musicbrainz5_finalize (GObject *object)
++{
++ SjMetadataMusicbrainz5Private *priv;
++
++ priv = GET_PRIVATE (object);
++
++ if (priv->mb != NULL) {
++ mb5_query_delete (priv->mb);
++ priv->mb = NULL;
++ }
++ if (priv->disc != NULL) {
++ discid_free (priv->disc);
++ priv->disc = NULL;
++ }
++ g_free (priv->cdrom);
++
++ G_OBJECT_CLASS (sj_metadata_musicbrainz5_parent_class)->finalize (object);
++}
++
++static void
++sj_metadata_musicbrainz5_class_init (SjMetadataMusicbrainz5Class *class)
++{
++ GObjectClass *object_class = (GObjectClass*)class;
++
++ g_type_class_add_private (class, sizeof (SjMetadataMusicbrainz5Private));
++
++ object_class->get_property = sj_metadata_musicbrainz5_get_property;
++ object_class->set_property = sj_metadata_musicbrainz5_set_property;
++ object_class->finalize = sj_metadata_musicbrainz5_finalize;
++
++ g_object_class_override_property (object_class, PROP_DEVICE, "device");
++ g_object_class_override_property (object_class, PROP_PROXY_HOST,
"proxy-host");
++ g_object_class_override_property (object_class, PROP_PROXY_PORT,
"proxy-port");
++}
++
++
++/*
++ * Public methods.
++ */
++
++GObject *
++sj_metadata_musicbrainz5_new (void)
++{
++ return g_object_new (SJ_TYPE_METADATA_MUSICBRAINZ5, NULL);
++}
+diff --git a/plugins/audiocd/sj-metadata-musicbrainz5.h
b/plugins/audiocd/sj-metadata-musicbrainz5.h
+new file mode 100644
+index 0000000..3cd4c42
+--- /dev/null
++++ b/plugins/audiocd/sj-metadata-musicbrainz5.h
+@@ -0,0 +1,56 @@
++/*
++ * sj-metadata-musicbrainz5.h
++ * Copyright (C) 2008 Ross Burton <ross(a)burtonini.com>
++ * Copyright (C) 2008 Bastien Nocera <hadess(a)hadess.net>
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Library General Public
++ * License as published by the Free Software Foundation; either
++ * version 2 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library General Public
++ * License along with this library; if not, write to the
++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
++ * Boston, MA 02111-1307, USA.
++ */
++
++#ifndef SJ_METADATA_MUSICBRAINZ5_H
++#define SJ_METADATA_MUSICBRAINZ5_H
++
++#include <glib-object.h>
++#include "sj-metadata.h"
++
++G_BEGIN_DECLS
++
++#define SJ_TYPE_METADATA_MUSICBRAINZ5 (sj_metadata_musicbrainz5_get_type ())
++#define SJ_METADATA_MUSICBRAINZ5(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ5, SjMetadataMusicbrainz5))
++#define SJ_METADATA_MUSICBRAINZ5_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable),
SJ_TYPE_METADATA_MUSICBRAINZ5, SjMetadataMusicbrainz5Class))
++#define SJ_IS_METADATA_MUSICBRAINZ5(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ5))
++#define SJ_IS_METADATA_MUSICBRAINZ5_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable),
SJ_TYPE_METADATA_MUSICBRAINZ5))
++#define SJ_METADATA_MUSICBRAINZ5_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
SJ_TYPE_METADATA_MUSICBRAINZ5, SjMetadataMusicbrainz5Class))
++
++typedef struct _SjMetadataMusicbrainz5 SjMetadataMusicbrainz5;
++typedef struct _SjMetadataMusicbrainz5Class SjMetadataMusicbrainz5Class;
++
++struct _SjMetadataMusicbrainz5
++{
++ GObject parent;
++};
++
++struct _SjMetadataMusicbrainz5Class
++{
++ GObjectClass parent;
++};
++
++GType sj_metadata_musicbrainz5_get_type (void);
++
++GObject *sj_metadata_musicbrainz5_new (void);
++
++G_END_DECLS
++
++#endif /* SJ_METADATA_MUSICBRAINZ5_H */
+diff --git a/plugins/audiocd/sj-metadata.c b/plugins/audiocd/sj-metadata.c
+index ce25cf6..0a6497d 100644
+--- a/plugins/audiocd/sj-metadata.c
++++ b/plugins/audiocd/sj-metadata.c
+@@ -84,7 +84,7 @@ sj_metadata_get_type (void)
+ NULL,
+ NULL
+ };
+-
++
+ type = g_type_register_static (G_TYPE_INTERFACE, "SjMetadata", &info,
0);
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+diff --git a/plugins/audiocd/sj-structures.c b/plugins/audiocd/sj-structures.c
+index b4577d4..3dc29c3 100644
+--- a/plugins/audiocd/sj-structures.c
++++ b/plugins/audiocd/sj-structures.c
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * Copyright (C) 2003 Ross Burton <ross(a)burtonini.com>
+ *
+ * Sound Juicer - sj-structures.c
+@@ -32,11 +32,13 @@ void track_details_free(TrackDetails *track)
+ g_return_if_fail (track != NULL);
+ g_free (track->title);
+ g_free (track->artist);
++ g_free (track->composer);
++ g_free (track->composer_sortname);
+ g_free (track->track_id);
+ g_free (track->artist_id);
+ g_free (track->artist_sortname);
+ g_list_foreach (track->artists, (GFunc)artist_details_free, NULL);
+-
++ g_list_free (track->artists);
+ g_free (track);
+ }
+
+@@ -48,12 +50,15 @@ void album_details_free(AlbumDetails *album)
+ g_return_if_fail (album != NULL);
+ g_free (album->title);
+ g_free (album->artist);
++ g_free (album->composer);
++ g_free (album->composer_sortname);
+ g_free (album->genre);
+ g_free (album->album_id);
+ if (album->release_date) g_date_free (album->release_date);
+ g_list_foreach (album->tracks, (GFunc)track_details_free, NULL);
+ g_list_free (album->tracks);
+ g_free (album->artist_sortname);
++ g_free (album->artist_id);
+ g_free (album->asin);
+ g_free (album->discogs);
+ g_free (album->wikipedia);
+@@ -61,7 +66,7 @@ void album_details_free(AlbumDetails *album)
+ g_free (album->country);
+ g_free (album->type);
+ g_list_foreach (album->artists, (GFunc)artist_details_free, NULL);
+-
++ g_list_free (album->artists);
+ g_free (album);
+ }
+
+diff --git a/plugins/audiocd/sj-structures.h b/plugins/audiocd/sj-structures.h
+index 46d67e9..a611521 100644
+--- a/plugins/audiocd/sj-structures.h
++++ b/plugins/audiocd/sj-structures.h
+@@ -1,4 +1,4 @@
+-/*
++/*
+ * Copyright (C) 2003 Ross Burton <ross(a)burtonini.com>
+ *
+ * Sound Juicer - sj-structures.h
+@@ -46,6 +46,8 @@ struct _TrackDetails {
+ char *title;
+ char *artist;
+ char* artist_sortname; /* Can be NULL, so fall back onto artist */
++ char* composer;
++ char* composer_sortname;
+ int duration; /* seconds */
+ char* track_id;
+ char* artist_id;
+@@ -56,6 +58,8 @@ struct _AlbumDetails {
+ char* title;
+ char* artist;
+ char* artist_sortname;
++ char* composer;
++ char* composer_sortname;
+ char *genre;
+ int number; /* number of tracks in the album */
+ int disc_number;
+--
+1.7.11.2
+