sound-juicer r2279 - in trunk: . libjuicer po src tests



Author: hadess
Date: Wed Sep  3 18:47:17 2008
New Revision: 2279
URL: http://svn.gnome.org/viewvc/sound-juicer?rev=2279&view=rev

Log:
2008-09-03  Bastien Nocera  <hadess hadess net>

	* configure.in: Check for libmusicbrainz3, and require libcdio
	* libjuicer/Makefile.am:

	* libjuicer/sj-metadata-getter.c:
	* libjuicer/sj-metadata-getter.h: Add a helper object to gather
	data from different metadata backends, with fallback support. The
	threading is now in the helper object, and not in the metadata
	backends themselves. The backends don't have signals anymore,
	and are synchronous.

	* libjuicer/sj-metadata-cdtext.c (cdtext_list_albums),
	(sj_metadata_cdtext_finalize):
	* libjuicer/sj-metadata-musicbrainz.c (mb_list_albums),
	(metadata_interface_init):
	* libjuicer/sj-metadata.c (sj_metadata_base_init),
	(sj_metadata_list_albums):
	* libjuicer/sj-metadata.h:
	* libjuicer/sj-structures.h:
	* src/sj-main.c (metadata_cb), (reread_cd), (set_device),
	(http_proxy_setup), (main):
	* tests/mb-test.c (source_to_str), (metadata_cb), (main):
	Change for the above

	* libjuicer/sj-metadata-musicbrainz3.c:
	* libjuicer/sj-metadata-musicbrainz3.h: Add libmusicbrainz3 support

	(Closes: #516447)

2008-09-03  Bastien Nocera  <hadess hadess net>

	* POTFILES.in: upd



Added:
   trunk/libjuicer/sj-metadata-getter.c
   trunk/libjuicer/sj-metadata-getter.h
   trunk/libjuicer/sj-metadata-musicbrainz3.c
   trunk/libjuicer/sj-metadata-musicbrainz3.h
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/libjuicer/Makefile.am
   trunk/libjuicer/sj-metadata-cdtext.c
   trunk/libjuicer/sj-metadata-musicbrainz.c
   trunk/libjuicer/sj-metadata.c
   trunk/libjuicer/sj-metadata.h
   trunk/libjuicer/sj-structures.h
   trunk/po/ChangeLog
   trunk/po/POTFILES.in
   trunk/src/sj-main.c
   trunk/tests/mb-test.c

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Wed Sep  3 18:47:17 2008
@@ -69,7 +69,20 @@
 AC_SUBST(MEDIA_PROFILES_CFLAGS)
 AC_SUBST(MEDIA_PROFILES_LIBS)
 
+# Find libcdio
+PKG_CHECK_MODULES([CDIO],[libcdio >= 0.70])
+AC_SUBST([CDIO_CFLAGS])
+AC_SUBST([CDIO_LIBS])
+
 # Find MusicBrainz
+PKG_CHECK_MODULES(MUSICBRAINZ3, libmusicbrainz3, [have_mb3=yes], [have_mb3=no])
+AC_SUBST(MUSICBRAINZ3_CFLAGS)
+AC_SUBST(MUSICBRAINZ3_LIBS)
+AM_CONDITIONAL([HAVE_MB3], [test "$have_mb3" = "yes"])
+if test "$have_mb3" = "yes" ; then
+	AC_DEFINE([HAVE_MB3], 1, [Whether libmusicbrainz3 is available])
+fi
+
 PKG_CHECK_MODULES(MUSICBRAINZ, libmusicbrainz >= 2.1.3)
 AC_SUBST(MUSICBRAINZ_CFLAGS)
 AC_SUBST(MUSICBRAINZ_LIBS)
@@ -79,17 +92,6 @@
 AC_CHECK_FUNCS(mb_SetProxyCreds)
 LIBS="$oldlibs"
 
-# Find the optional dependency libcdio
-PKG_CHECK_MODULES([CDIO],[libcdio >= 0.70],[have_cdio=yes],[have_cdio=no])
-AC_SUBST([CDIO_CFLAGS])
-AC_SUBST([CDIO_LIBS])
-
-if test "$have_cdio" != "yes"; then
-	AC_MSG_WARN([libcdio not found, cannot get track names from CD-TEXT])
-fi
-
-AM_CONDITIONAL([HAVE_CDIO],[test "$have_cdio" = "yes"])
-
 # Find TagLib for the internal copy of id3mux
 PKG_CHECK_MODULES([TAGLIB],[taglib],[have_taglib=yes],[have_taglib=no])
 AC_SUBST([TAGLIB_CFLAGS]) 

Modified: trunk/libjuicer/Makefile.am
==============================================================================
--- trunk/libjuicer/Makefile.am	(original)
+++ trunk/libjuicer/Makefile.am	Wed Sep  3 18:47:17 2008
@@ -12,6 +12,10 @@
 	sj-metadata.c \
 	sj-metadata-musicbrainz.h \
 	sj-metadata-musicbrainz.c \
+	sj-metadata-cdtext.h \
+	sj-metadata-cdtext.c \
+	sj-metadata-getter.c \
+	sj-metadata-getter.h \
 	sj-util.h sj-util.c
 
 libjuicer_la_CPPFLAGS = \
@@ -21,33 +25,31 @@
 libjuicer_la_CFLAGS = \
 	$(WARN_CFLAGS)	\
 	$(MUSICBRAINZ_CFLAGS) \
+	$(MUSICBRAINZ3_CFLAGS) \
 	$(GSTREAMER_CFLAGS) \
 	$(MEDIA_PROFILES_CFLAGS) \
 	$(BURN_CFLAGS) \
 	$(UI_CFLAGS) \
+	$(CDIO_CFLAGS) \
 	$(AM_CFLAGS)
 
 libjuicer_la_LIBADD = \
 	$(MUSICBRAINZ_LIBS) \
+	$(MUSICBRAINZ3_LIBS) \
 	$(MEDIA_PROFILES_LIBS) \
 	$(GSTREAMER_LIBS) \
 	$(BURN_LIBS) \
-	$(UI_LIBS)
+	$(UI_LIBS) \
+	$(CDIO_LIBS)
 
 libjuicer_la_LDFLAGS = \
 	-export-dynamic \
 	$(AM_LDFLAGS)
 
-if HAVE_CDIO
+if HAVE_MB3
 libjuicer_la_SOURCES += \
-	sj-metadata-cdtext.h \
-	sj-metadata-cdtext.c
-
-libjuicer_la_CFLAGS += \
-	$(CDIO_CFLAGS)
-
-libjuicer_la_LDFLAGS += \
-	$(CDIO_LIBS)
+	sj-metadata-musicbrainz3.h \
+	sj-metadata-musicbrainz3.c
 endif
 
 #

Modified: trunk/libjuicer/sj-metadata-cdtext.c
==============================================================================
--- trunk/libjuicer/sj-metadata-cdtext.c	(original)
+++ trunk/libjuicer/sj-metadata-cdtext.c	Wed Sep  3 18:47:17 2008
@@ -40,7 +40,6 @@
 struct SjMetadataCdtextPrivate {
   char *cdrom;
   GList *albums;
-  GError *error;
 };
 
 #define GET_PRIVATE(o)  \
@@ -64,35 +63,25 @@
  * Private methods
  */
 
-static gboolean
-fire_signal_idle (SjMetadataCdtext *m)
+static GList *
+cdtext_list_albums (SjMetadata *metadata, char **url, GError **error)
 {
-  g_return_val_if_fail (SJ_IS_METADATA_CDTEXT (m), FALSE);
-  g_signal_emit_by_name (G_OBJECT (m), "metadata", m->priv->albums, m->priv->error);
-  return FALSE;
-}
-
-static void
-cdtext_list_albums (SjMetadata *metadata, GError **error)
-{
-  /* TODO: put in a thread */
   SjMetadataCdtextPrivate *priv;
   AlbumDetails *album;
   CdIo *cdio;
   track_t cdtrack, last_cdtrack;
   const cdtext_t *cdtext;
 
-  g_return_if_fail (SJ_IS_METADATA_CDTEXT (metadata));
+  g_return_val_if_fail (SJ_IS_METADATA_CDTEXT (metadata), NULL);
 
   priv = SJ_METADATA_CDTEXT (metadata)->priv;
 
   cdio = cdio_open (priv->cdrom, DRIVER_UNKNOWN);
   if (!cdio) {
     g_warning ("Cannot open CD");
-    priv->error = g_error_new (SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Cannot read CD"));
+    g_set_error (error, SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, _("Cannot read CD"));
     priv->albums = NULL;
-    g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
-    return;
+    return NULL;
   }
 
 #if 0
@@ -120,7 +109,8 @@
       track->title = g_strdup (cdtext_get (CDTEXT_TITLE, cdtext));
       track->artist = g_strdup (cdtext_get (CDTEXT_PERFORMER, cdtext));
     } else {
-      g_print ("No CD-TEXT for track %u\n", cdtrack);
+      track->title = g_strdup_printf (_("Track %d"), cdtrack);
+      track->artist = g_strdup (_("Unknown Artist"));
     }
     track->duration = cdio_get_track_sec_count (cdio, cdtrack) / CDIO_CD_FRAMES_PER_SEC;
 
@@ -130,15 +120,24 @@
 
   /* TODO: why can't I do this first? */
   cdtext = cdio_get_cdtext(cdio, 0);
-  album->title = g_strdup (cdtext_get (CDTEXT_TITLE, cdtext));
-  album->artist = g_strdup (cdtext_get (CDTEXT_PERFORMER, cdtext));
-  album->genre = g_strdup (cdtext_get (CDTEXT_GENRE, cdtext));
+  if (cdtext) {
+    album->title = g_strdup (cdtext_get (CDTEXT_TITLE, cdtext));
+    album->artist = g_strdup (cdtext_get (CDTEXT_PERFORMER, cdtext));
+    album->genre = g_strdup (cdtext_get (CDTEXT_GENRE, cdtext));
+
+    album->metadata_source = SOURCE_CDTEXT;
+  } else {
+    album->artist = g_strdup (_("Unknown Artist"));
+    album->title = g_strdup (_("Unknown Title"));
+    album->genre = g_strdup ("");
+
+    album->metadata_source = SOURCE_FALLBACK;
+  }
 
-  album->metadata_source = SOURCE_CDTEXT;
 
-  priv->error = NULL;
   priv->albums = g_list_append (NULL, album);
-  g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
+
+  return priv->albums;
 }
 
 
@@ -198,8 +197,6 @@
   SjMetadataCdtextPrivate *priv = SJ_METADATA_CDTEXT (object)->priv;
   g_free (priv->cdrom);
   g_list_deep_free (priv->albums, (GFunc)album_details_free);
-  if (priv->error)
-    g_error_free (priv->error);
 }
 
 static void

Added: trunk/libjuicer/sj-metadata-getter.c
==============================================================================
--- (empty file)
+++ trunk/libjuicer/sj-metadata-getter.c	Wed Sep  3 18:47:17 2008
@@ -0,0 +1,251 @@
+/*
+ * sj-metadata.c
+ * Copyright (C) 2003 Ross Burton <ross burtonini 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.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include "sj-metadata-getter.h"
+#include "sj-metadata-marshal.h"
+#include "sj-metadata.h"
+#ifdef HAVE_MB3
+#include "sj-metadata-musicbrainz3.h"
+#endif /* HAVE_MB3 */
+#include "sj-metadata-musicbrainz.h"
+#include "sj-metadata-cdtext.h"
+#include "sj-error.h"
+
+enum {
+  METADATA,
+  LAST_SIGNAL
+};
+
+struct SjMetadataGetterPrivate {
+  char *url;
+  char *cdrom;
+  char *proxy_host;
+  int proxy_port;
+};
+
+struct SjMetadataGetterSignal {
+  SjMetadataGetter *mdg;
+  SjMetadata *metadata;
+  GList *albums;
+  GError *error;
+};
+
+typedef struct SjMetadataGetterPrivate SjMetadataGetterPrivate;
+typedef struct SjMetadataGetterSignal SjMetadataGetterSignal;
+
+static int signals[LAST_SIGNAL] = { 0 };
+
+static void sj_metadata_getter_finalize (GObject *object);
+static void sj_metadata_getter_init (SjMetadataGetter *mdg);
+
+G_DEFINE_TYPE(SjMetadataGetter, sj_metadata_getter, G_TYPE_OBJECT);
+
+#define GETTER_PRIVATE(o)                                            \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), SJ_TYPE_METADATA_GETTER, SjMetadataGetterPrivate))
+
+static void
+sj_metadata_getter_class_init (SjMetadataGetterClass *klass)
+{
+  GObjectClass *object_class;
+  object_class = (GObjectClass *)klass;
+
+  g_type_class_add_private (klass, sizeof (SjMetadataGetterPrivate));
+
+  object_class->finalize = sj_metadata_getter_finalize;
+
+  /* Properties */
+  signals[METADATA] = g_signal_new ("metadata",
+				    G_TYPE_FROM_CLASS (object_class),
+				    G_SIGNAL_RUN_LAST,
+				    G_STRUCT_OFFSET (SjMetadataGetterClass, metadata),
+				    NULL, NULL,
+				    metadata_marshal_VOID__POINTER_POINTER,
+				    G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
+}
+
+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);
+
+  G_OBJECT_CLASS (sj_metadata_getter_parent_class)->finalize (object);
+}
+
+static void
+sj_metadata_getter_init (SjMetadataGetter *mdg)
+{
+}
+
+SjMetadataGetter *
+sj_metadata_getter_new (void)
+{
+  return SJ_METADATA_GETTER (g_object_new (SJ_TYPE_METADATA_GETTER, NULL));
+}
+
+void
+sj_metadata_getter_set_cdrom (SjMetadataGetter *mdg, const char* device)
+{
+  SjMetadataGetterPrivate *priv;
+
+  priv = GETTER_PRIVATE (mdg);
+
+  if (priv->cdrom)
+    g_free (priv->cdrom);
+  priv->cdrom = g_strdup (device);
+}
+
+void
+sj_metadata_getter_set_proxy (SjMetadataGetter *mdg, const char* proxy)
+{
+  SjMetadataGetterPrivate *priv;
+
+  priv = GETTER_PRIVATE (mdg);
+
+  if (priv->proxy_host)
+    g_free (priv->proxy_host);
+  priv->proxy_host = g_strdup (proxy);
+}
+
+void
+sj_metadata_getter_set_proxy_port (SjMetadataGetter *mdg, const int proxy_port)
+{
+  SjMetadataGetterPrivate *priv;
+
+  priv = GETTER_PRIVATE (mdg);
+
+  priv->proxy_port = proxy_port;
+}
+
+static gboolean
+fire_signal_idle (SjMetadataGetterSignal *signal)
+{
+  g_signal_emit_by_name (G_OBJECT (signal->mdg), "metadata",
+  			 signal->albums, signal->error);
+
+  /* This will kill the albums, as
+   * those belong to the metadata backend */
+  if (signal->metadata)
+    g_object_unref (signal->metadata);
+  if (signal->error != NULL)
+    g_error_free (signal->error);
+  g_free (signal);
+
+  return FALSE;
+}
+
+static gpointer
+lookup_cd (SjMetadataGetter *mdg)
+{
+  SjMetadata *metadata;
+  guint i;
+  SjMetadataGetterPrivate *priv;
+  GError *error = NULL;
+  gboolean found = FALSE;
+  GType types[] = {
+#ifdef HAVE_MB3
+    SJ_TYPE_METADATA_MUSICBRAINZ3,
+#endif /* HAVE_MB3 */
+    SJ_TYPE_METADATA_MUSICBRAINZ,
+    SJ_TYPE_METADATA_CDTEXT,
+  };
+
+  priv = GETTER_PRIVATE (mdg);
+
+  g_free (priv->url);
+  priv->url = NULL;
+
+  for (i = 0; i < G_N_ELEMENTS (types); i++) {
+    GList *albums;
+
+    metadata = g_object_new (types[i],
+    			     "device", priv->cdrom,
+    			     "proxy-host", priv->proxy_host,
+    			     "proxy-port", priv->proxy_port,
+    			     NULL);
+    if (priv->url == NULL)
+      albums = sj_metadata_list_albums (metadata, &priv->url, &error);
+    else
+      albums = sj_metadata_list_albums (metadata, NULL, &error);
+
+    if (albums != NULL) {
+      SjMetadataGetterSignal *signal;
+
+      signal = g_new0 (SjMetadataGetterSignal, 1);
+      signal->albums = albums;
+      signal->mdg = mdg;
+      signal->metadata = metadata;
+      g_idle_add ((GSourceFunc)fire_signal_idle, signal);
+      break;
+    }
+
+    g_object_unref (metadata);
+
+    if (error != NULL) {
+      SjMetadataGetterSignal *signal;
+
+      g_assert (found == FALSE);
+
+      signal = g_new0 (SjMetadataGetterSignal, 1);
+      signal->error = error;
+      signal->mdg = mdg;
+      g_idle_add ((GSourceFunc)fire_signal_idle, signal);
+      break;
+    }
+  }
+
+  return NULL;
+}
+
+gboolean
+sj_metadata_getter_list_albums (SjMetadataGetter *mdg, GError **error)
+{
+  GThread *thread;
+
+  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"));
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+char *
+sj_metadata_getter_get_submit_url (SjMetadataGetter *mdg)
+{
+  SjMetadataGetterPrivate *priv;
+
+  priv = GETTER_PRIVATE (mdg);
+
+  if (priv->url)
+    return g_strdup (priv->url);
+  return NULL;
+}
+

Added: trunk/libjuicer/sj-metadata-getter.h
==============================================================================
--- (empty file)
+++ trunk/libjuicer/sj-metadata-getter.h	Wed Sep  3 18:47:17 2008
@@ -0,0 +1,62 @@
+/*
+ * sj-metadata-getter.h
+ * Copyright (C) 2008 Bastien Nocera
+ *
+ * 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_GETTER_H
+#define SJ_METADATA_GETTER_H
+
+#include <glib-object.h>
+#include <glib/gerror.h>
+
+G_BEGIN_DECLS
+
+#define SJ_TYPE_METADATA_GETTER            (sj_metadata_getter_get_type ())
+#define SJ_METADATA_GETTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SJ_TYPE_METADATA_GETTER, SjMetadataGetter))
+#define SJ_METADATA_GETTER_CLASS(vtable)    (G_TYPE_CHECK_CLASS_CAST ((vtable), SJ_TYPE_METADATA_GETTER, SjMetadataGetterClass))
+#define SJ_IS_METADATA_GETTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SJ_TYPE_METADATA_GETTER))
+#define SJ_IS_METADATA_GETTER_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), SJ_TYPE_METADATA_GETTER))
+#define SJ_METADATA_GETTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SJ_TYPE_METADATA_GETTER, SjMetadataGetterClass))
+
+struct _SjMetadataGetter
+{
+  GObject parent;
+};
+
+typedef struct _SjMetadataGetter SjMetadataGetter;
+typedef struct _SjMetadataGetterClass SjMetadataGetterClass;
+
+struct _SjMetadataGetterClass
+{
+  GObjectClass parent;
+
+  /* Signals */
+  void         (*metadata) (SjMetadataGetter *mdg, GList *albums, GError *error);
+};
+
+GType sj_metadata_getter_get_type (void);
+SjMetadataGetter *sj_metadata_getter_new (void);
+void sj_metadata_getter_set_cdrom (SjMetadataGetter *mdg, const char* device);
+void sj_metadata_getter_set_proxy (SjMetadataGetter *mdg, const char* proxy);
+void sj_metadata_getter_set_proxy_port (SjMetadataGetter *mdg, const int proxy_port);
+gboolean sj_metadata_getter_list_albums (SjMetadataGetter *mdg, GError **error);
+char *sj_metadata_getter_get_submit_url (SjMetadataGetter *mdg);
+
+G_END_DECLS
+
+#endif /* SJ_METADATA_GETTER_H */

Modified: trunk/libjuicer/sj-metadata-musicbrainz.c
==============================================================================
--- trunk/libjuicer/sj-metadata-musicbrainz.c	(original)
+++ trunk/libjuicer/sj-metadata-musicbrainz.c	Wed Sep  3 18:47:17 2008
@@ -55,9 +55,7 @@
   char *http_proxy;
   int http_proxy_port;
   char *cdrom;
-  /* TODO: remove and use an async queue? */
   GList *albums;
-  GError *error;
   GRegex *disc_regex;
 };
 
@@ -94,54 +92,6 @@
   return (sectors * BYTES_PER_SECTOR / BYTES_PER_SECOND);
 }
 
-static GList*
-get_offline_track_listing(SjMetadata *metadata, GError **error)
-{
-  SjMetadataMusicbrainzPrivate *priv;
-  GList* list = NULL;
-  AlbumDetails *album;
-  TrackDetails *track;
-  int num_tracks, i;
-
-  g_return_val_if_fail (metadata != NULL, NULL);
-  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
-
-  if (!mb_Query (priv->mb, MBQ_GetCDTOC)) {
-    char message[255];
-    mb_GetQueryError (priv->mb, message, 255);
-    g_set_error (error,
-                 SJ_ERROR, SJ_ERROR_CD_LOOKUP_ERROR,
-                 _("Cannot read CD: %s"), message);
-    return NULL;
-  }
-  
-  num_tracks = mb_GetResultInt (priv->mb, MBE_TOCGetLastTrack);
-
-  album = g_new0 (AlbumDetails, 1);
-  album->artist = g_strdup (_("Unknown Artist"));
-  album->title = g_strdup (_("Unknown Title"));
-  album->genre = NULL;
-  for (i = 1; i <= num_tracks; i++) {
-    track = g_new0 (TrackDetails, 1);
-    track->album = album;
-    track->number = i;
-    track->title = g_strdup_printf (_("Track %d"), i);
-    track->artist = g_strdup (album->artist);
-    track->duration = get_duration_from_sectors (mb_GetResultInt1 (priv->mb, MBE_TOCGetTrackNumSectors, i+1));
-    album->tracks = g_list_append (album->tracks, track);
-    album->number++;
-  }
-  return g_list_append (list, album);
-}
-
-static gboolean
-fire_signal_idle (SjMetadataMusicbrainz *m)
-{
-  g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ (m), FALSE);
-  g_signal_emit_by_name (G_OBJECT (m), "metadata", m->priv->albums, m->priv->error);
-  return FALSE;
-}
-
 /**
  * Virtual methods
  */
@@ -324,8 +274,8 @@
   g_free (iso8859);
 }
 
-static gpointer
-lookup_cd (SjMetadata *metadata)
+static GList *
+mb_list_albums (SjMetadata *metadata, char **url, GError **error)
 {
   /** The size of the buffer used in MusicBrainz lookups */
   SjMetadataMusicbrainzPrivate *priv;
@@ -338,12 +288,10 @@
   NautilusBurnDriveMonitor *monitor;
   NautilusBurnDrive *drive;
 
-  /* TODO: fire error signal */
   g_return_val_if_fail (metadata != NULL, NULL);
   g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ (metadata), NULL);
   priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
   g_return_val_if_fail (priv->cdrom != NULL, NULL);
-  priv->error = NULL; /* TODO: hack */
 
   if (! nautilus_burn_initialized ()) {
     nautilus_burn_init ();
@@ -367,21 +315,24 @@
       msg = g_strdup_printf (_("Device '%s' could not be opened. Check the access permissions on the device."), priv->cdrom);
       err = SJ_ERROR_CD_PERMISSION_ERROR;
     }
-    priv->error = g_error_new (SJ_ERROR, err, _("Cannot read CD: %s"), msg);
+    g_set_error (error, SJ_ERROR, err, _("Cannot read CD: %s"), msg);
     g_free (msg);
 
     priv->albums = NULL;
-    g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
     return NULL;
   }
 
   get_rdf (metadata);
 
+  if (url != NULL) {
+    mb_GetWebSubmitURL(priv->mb, data, sizeof(data));
+    *url = g_strdup(data);
+  }
+
   num_albums = mb_GetResultInt(priv->mb, MBE_GetNumAlbums);
   if (num_albums < 1) {
-    priv->albums = get_offline_track_listing (metadata, &(priv->error));
-    g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
-    return priv->albums;
+    priv->albums = NULL;
+    return NULL;
   }
 
   for (i = 1; i <= num_albums; i++) {
@@ -467,9 +418,8 @@
       g_free (album->title);
       g_free (album);
       g_warning (_("Incomplete metadata for this CD"));
-      priv->albums = get_offline_track_listing (metadata, &(priv->error));
-      g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
-      return priv->albums;
+      priv->albums = NULL;
+      return NULL;
     }
 
     for (j = 1; j <= num_tracks; j++) {
@@ -561,45 +511,9 @@
     }
   }
 
-  priv->albums = albums;
-  g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
   return albums;
 }
 
-static void
-mb_list_albums (SjMetadata *metadata, GError **error)
-{
-  GThread *thread;
-
-  g_return_if_fail (SJ_IS_METADATA_MUSICBRAINZ (metadata));
-
-  thread = g_thread_create ((GThreadFunc)lookup_cd, metadata, TRUE, error);
-  if (thread == NULL) {
-    g_set_error (error,
-                 SJ_ERROR, SJ_ERROR_INTERNAL_ERROR,
-                 _("Could not create CD lookup thread"));
-    return;
-  }
-}
-
-static char *
-mb_get_submit_url (SjMetadata *metadata)
-{
-  SjMetadataMusicbrainzPrivate *priv;
-  char url[1025];
-
-  g_return_val_if_fail (metadata != NULL, NULL);
-
-  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
-
-  if (mb_GetWebSubmitURL(priv->mb, url, 1024)) {
-    return g_strdup(url);
-  } else {
-    return NULL;
-  }
-}
-
-
 /*
  * GObject methods
  */
@@ -609,7 +523,6 @@
 {
   SjMetadataClass *klass = (SjMetadataClass*)g_iface;
   klass->list_albums = mb_list_albums;
-  klass->get_submit_url = mb_get_submit_url;
 }
 
 static void

Added: trunk/libjuicer/sj-metadata-musicbrainz3.c
==============================================================================
--- (empty file)
+++ trunk/libjuicer/sj-metadata-musicbrainz3.c	Wed Sep  3 18:47:17 2008
@@ -0,0 +1,451 @@
+/*
+ * sj-metadata-musicbrainz3.c
+ * Copyright (C) 2008 Ross Burton <ross burtonini 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 <unistd.h>
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
+#include <nautilus-burn.h>
+#include <musicbrainz3/mb_c.h>
+
+#include "sj-metadata-musicbrainz3.h"
+#include "sj-metadata-cdtext.h"
+#include "sj-structures.h"
+#include "sj-error.h"
+
+#define GET(field, function, obj) function (obj, buffer, sizeof (buffer)); if (field) g_free (field); field = g_strdup (buffer);
+
+#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;
+  GList *albums;
+  /* 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;
+  GRegex *disc_regex;
+  GMatchInfo *info;
+  int i;
+
+  g_assert (release);
+
+  album = g_new0 (AlbumDetails, 1);
+
+   /* Some versions of libmusicbrainz3 seem to forget the trailing .html in the URL */
+  GET (album->album_id, mb_release_get_id, release);
+  if (album->album_id && g_str_has_suffix (album->album_id, ".html") == FALSE) {
+    char *tmp;
+    tmp = g_strdup_printf ("%s.html", album->album_id);
+    g_free (album->album_id);
+    album->album_id = tmp;
+  }
+
+  GET (album->title, mb_release_get_title, release);
+  disc_regex = g_regex_new (".+( \\(disc (\\d+).*)", 0, 0, NULL);
+
+  if (g_regex_match (disc_regex, album->title, 0, &info)) {
+    int pos = 0;
+    char *s;
+
+    g_match_info_fetch_pos (info, 1, &pos, NULL);
+    if (pos) {
+	    s = g_strndup (album->title, pos);
+	    g_free (album->title);
+	    album->title = s;
+    }
+
+    s = g_match_info_fetch (info, 2);
+    album->disc_number = atoi (s);
+    g_free (s);
+  }
+
+  g_match_info_free (info);
+  g_regex_unref (disc_regex);
+
+  artist = mb_release_get_artist (release);
+  GET (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;
+    int matched, year=1, month=1, day=1;
+
+    event = mb_release_get_release_event (release, 1);
+    GET (date, mb_release_event_get_date, event);
+    matched = sscanf(date, "%u-%u-%u", &year, &month, &day);
+    if (matched >= 1)
+      album->release_date = g_date_new_dmy ((day == 0) ? 1 : day, (month == 0) ? 1 : month, year);
+    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 < 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 (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_release_get_artist (release);
+    GET (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;
+  MbQuery query;
+  MbReleaseFilter filter;
+  MbResultList results;
+  MbRelease release;
+  char *id = NULL;
+  char buffer[512];
+  int i;
+  NautilusBurnMediaType type;
+  NautilusBurnDriveMonitor *monitor;
+  NautilusBurnDrive *drive;
+
+  g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ3 (metadata), FALSE);
+
+  priv = GET_PRIVATE (metadata);
+
+  if (! nautilus_burn_initialized ()) {
+    nautilus_burn_init ();
+  }
+  monitor = nautilus_burn_get_drive_monitor ();
+  drive = nautilus_burn_drive_monitor_get_drive_for_device (monitor, priv->cdrom);
+  if (drive == NULL) {
+    return NULL;
+  }
+  type = nautilus_burn_drive_get_media_type (drive);
+  nautilus_burn_drive_unref (drive);
+
+  if (type == NAUTILUS_BURN_MEDIA_TYPE_ERROR) {
+    char *msg;
+    SjError err;
+
+    if (access (priv->cdrom, W_OK) == 0) {
+      msg = g_strdup_printf (_("Device '%s' does not contain any media"), priv->cdrom);
+      err = SJ_ERROR_CD_NO_MEDIA;
+    } else {
+      msg = g_strdup_printf (_("Device '%s' could not be opened. Check the access permissions on the device."), priv->cdrom);
+      err = SJ_ERROR_CD_PERMISSION_ERROR;
+    }
+    g_set_error (error, SJ_ERROR, err, _("Cannot read CD: %s"), msg);
+    g_free (msg);
+
+    priv->albums = NULL;
+    return NULL;
+  }
+
+  priv->disc = mb_read_disc (priv->cdrom);
+  if (url != NULL) {
+    mb_get_submission_url (priv->disc, NULL, 0, buffer, sizeof (buffer));
+    *url = g_strdup (buffer);
+  }
+
+  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);
+
+  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);
+    mb_release_get_id (release, buffer, sizeof (buffer));
+    includes = get_release_includes ();
+    release = mb_query_get_release_by_id (query, buffer, includes);
+    mb_release_includes_free (includes);
+
+    album = make_album_from_release (release);
+    album->metadata_source = SOURCE_MUSICBRAINZ;
+    fill_empty_durations (priv->disc, album);
+    priv->albums = g_list_append (priv->albums, album);
+    mb_release_free (release);
+  }
+  mb_result_list_free (results);
+  mb_query_free (query);
+
+  return priv->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;
+  SjMetadataMusicbrainz3Private *priv;
+
+  priv = GET_PRIVATE (self);
+
+  priv->mb = mb_webservice_new();
+
+  gconf_client = gconf_client_get_default ();
+
+  /* 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);
+}

Added: trunk/libjuicer/sj-metadata-musicbrainz3.h
==============================================================================
--- (empty file)
+++ trunk/libjuicer/sj-metadata-musicbrainz3.h	Wed Sep  3 18:47:17 2008
@@ -0,0 +1,55 @@
+/*
+ * sj-metadata-musicbrainz3.h
+ * Copyright (C) 2008 Ross Burton <ross burtonini 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.
+ */
+
+#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 */

Modified: trunk/libjuicer/sj-metadata.c
==============================================================================
--- trunk/libjuicer/sj-metadata.c	(original)
+++ trunk/libjuicer/sj-metadata.c	Wed Sep  3 18:47:17 2008
@@ -27,21 +27,11 @@
   LAST_SIGNAL
 };
 
-static int signals[LAST_SIGNAL] = { 0 };
-
 static void
 sj_metadata_base_init (gpointer g_iface)
 {
   static gboolean initialized = FALSE;
   if (!initialized) {
-    signals[METADATA] = g_signal_new ("metadata",
-                                      G_TYPE_FROM_CLASS (g_iface),
-                                      G_SIGNAL_RUN_LAST,
-                                      G_STRUCT_OFFSET (SjMetadataClass, metadata),
-                                      NULL, NULL,
-                                      metadata_marshal_VOID__POINTER_POINTER,
-                                      G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_POINTER);
-
     /* TODO: make these constructors */
     /* TODO: add nice nick and blurb strings */
     g_object_interface_install_property (g_iface,
@@ -106,17 +96,9 @@
   g_object_set (metadata, "proxy-port", proxy_port, NULL);
 }
 
-void
-sj_metadata_list_albums (SjMetadata *metadata, GError **error)
+GList *
+sj_metadata_list_albums (SjMetadata *metadata, char **url, GError **error)
 {
-  SJ_METADATA_GET_CLASS (metadata)->list_albums (metadata, error);
+  return SJ_METADATA_GET_CLASS (metadata)->list_albums (metadata, url, error);
 }
 
-char *
-sj_metadata_get_submit_url (SjMetadata *metadata)
-{
-  if (SJ_METADATA_GET_CLASS (metadata)->get_submit_url)
-    return SJ_METADATA_GET_CLASS (metadata)->get_submit_url (metadata);
-  else
-    return NULL;
-}

Modified: trunk/libjuicer/sj-metadata.h
==============================================================================
--- trunk/libjuicer/sj-metadata.h	(original)
+++ trunk/libjuicer/sj-metadata.h	Wed Sep  3 18:47:17 2008
@@ -40,20 +40,15 @@
 {
   GTypeInterface g_iface;
 
-  /* Signals */
-  void         (*metadata) (SjMetadata *md, GList *albums, GError *error);
-
   /* Virtual Table */
-  void (*list_albums) (SjMetadata *metadata, GError **error);
-  char *(*get_submit_url) (SjMetadata *metadata);
+  GList * (*list_albums) (SjMetadata *metadata, char **url, GError **error);
 };
 
 GType sj_metadata_get_type (void);
 void sj_metadata_set_cdrom (SjMetadata *metadata, const char* device);
 void sj_metadata_set_proxy (SjMetadata *metadata, const char* proxy);
 void sj_metadata_set_proxy_port (SjMetadata *metadata, const int proxy_port);
-void sj_metadata_list_albums (SjMetadata *metadata, GError **error);
-char *sj_metadata_get_submit_url (SjMetadata *metadata);
+GList * sj_metadata_list_albums (SjMetadata *metadata, char **url, GError **error);
 
 G_END_DECLS
 

Modified: trunk/libjuicer/sj-structures.h
==============================================================================
--- trunk/libjuicer/sj-structures.h	(original)
+++ trunk/libjuicer/sj-structures.h	Wed Sep  3 18:47:17 2008
@@ -35,7 +35,8 @@
   SOURCE_UNKNOWN = 0,
   SOURCE_CDTEXT,
   SOURCE_FREEDB,
-  SOURCE_MUSICBRAINZ
+  SOURCE_MUSICBRAINZ,
+  SOURCE_FALLBACK
 };
 
 struct _TrackDetails {

Modified: trunk/po/POTFILES.in
==============================================================================
--- trunk/po/POTFILES.in	(original)
+++ trunk/po/POTFILES.in	Wed Sep  3 18:47:17 2008
@@ -8,7 +8,9 @@
 libjuicer/sj-extractor.c
 libjuicer/sj-metadata.c
 libjuicer/sj-metadata-cdtext.c
+libjuicer/sj-metadata-getter.c
 libjuicer/sj-metadata-musicbrainz.c
+libjuicer/sj-metadata-musicbrainz3.c
 libjuicer/sj-structures.c
 libjuicer/sj-util.c
 src/egg-play-preview.c

Modified: trunk/src/sj-main.c
==============================================================================
--- trunk/src/sj-main.c	(original)
+++ trunk/src/sj-main.c	Wed Sep  3 18:47:17 2008
@@ -43,8 +43,7 @@
 #include "bacon-message-connection.h"
 #include "gconf-bridge.h"
 #include "sj-about.h"
-#include "sj-metadata.h"
-#include "sj-metadata-musicbrainz.h"
+#include "sj-metadata-getter.h"
 #include "sj-extractor.h"
 #include "sj-structures.h"
 #include "sj-error.h"
@@ -69,7 +68,7 @@
 
 GladeXML *glade;
 
-SjMetadata *metadata;
+SjMetadataGetter *metadata;
 SjExtractor *extractor;
 
 GConfClient *gconf_client;
@@ -797,7 +796,7 @@
 }
 
 static void
-metadata_cb (SjMetadata *m, GList *albums, GError *error)
+metadata_cb (SjMetadataGetter *m, GList *albums, GError *error)
 {
   gboolean realized = GTK_WIDGET_REALIZED (main_window);
 
@@ -825,6 +824,11 @@
     return;
   }
 
+  current_submit_url = sj_metadata_getter_get_submit_url (metadata);
+  if (current_submit_url) {
+    gtk_widget_set_sensitive (submit_menuitem, TRUE);
+  }
+
   /* Free old album details */
   if (current_album != NULL) {
     album_details_free (current_album);
@@ -914,12 +918,7 @@
     return;
   }
 
-  current_submit_url = sj_metadata_get_submit_url (metadata);
-  if (current_submit_url) {
-    gtk_widget_set_sensitive (submit_menuitem, TRUE);
-  }
-
-  sj_metadata_list_albums (metadata, &error);
+  sj_metadata_getter_list_albums (metadata, &error);
 
   if (error && !(error->code == SJ_ERROR_CD_NO_MEDIA && ignore_no_media)) {
     GtkWidget *dialog;
@@ -1046,7 +1045,7 @@
     set_drive_from_device (device);
   }
 
-  sj_metadata_set_cdrom (metadata, device);
+  sj_metadata_getter_set_cdrom (metadata, device);
   sj_extractor_set_device (extractor, device);
   
   if (drive != NULL) {
@@ -1174,16 +1173,16 @@
 http_proxy_setup (GConfClient *client)
 {
   if (!gconf_client_get_bool (client, GCONF_HTTP_PROXY_ENABLE, NULL)) {
-    sj_metadata_set_proxy (metadata, NULL);
+    sj_metadata_getter_set_proxy (metadata, NULL);
   } else {
     char *host;
     int port;
 
     host = gconf_client_get_string (client, GCONF_HTTP_PROXY, NULL);
-    sj_metadata_set_proxy (metadata, host);
+    sj_metadata_getter_set_proxy (metadata, host);
     g_free (host);
     port = gconf_client_get_int (client, GCONF_HTTP_PROXY_PORT, NULL);
-    sj_metadata_set_proxy_port (metadata, port);
+    sj_metadata_getter_set_proxy_port (metadata, port);
   }
 }
 
@@ -1632,7 +1631,7 @@
     bacon_message_connection_set_callback (connection, on_message_received, NULL);
   }
 
-  metadata = SJ_METADATA (sj_metadata_musicbrainz_new ());
+  metadata = sj_metadata_getter_new ();
   g_signal_connect (metadata, "metadata", G_CALLBACK (metadata_cb), NULL);
 
   gconf_client = gconf_client_get_default ();

Modified: trunk/tests/mb-test.c
==============================================================================
--- trunk/tests/mb-test.c	(original)
+++ trunk/tests/mb-test.c	Wed Sep  3 18:47:17 2008
@@ -2,7 +2,7 @@
 #include <stdlib.h>
 #include "sj-structures.h"
 #include "sj-metadata.h"
-#include "sj-metadata-musicbrainz.h"
+#include "sj-metadata-getter.h"
 
 static const char *
 source_to_str (MetadataSource source)
@@ -11,24 +11,31 @@
 		"Unknown",
 		"CD-Text",
 		"FreeDB",
-		"MusicBrainz"
+		"MusicBrainz",
+		"Fallback"
 	};
 	return strs[source];
 }
 
 static void
-metadata_cb (SjMetadata *metadata, GList *albums, GError *error)
+metadata_cb (SjMetadataGetter *metadata, GList *albums, GError *error)
 {
+  char *url;
+
   if (error != NULL) {
     g_print ("Error: %s\n", error->message);
-    g_error_free (error);
     g_object_unref (metadata);
     exit (1);
   }
 
+  url = sj_metadata_getter_get_submit_url (metadata);
+  g_print ("Submit URL: %s\n", url);
+  g_free (url);
+
   while (albums) {
     AlbumDetails *album;
     album = (AlbumDetails*)albums->data;
+    char *disc_number;
     g_print ("Source: %s\n", source_to_str(album->metadata_source));
     if (album->metadata_source == SOURCE_MUSICBRAINZ)
       g_print ("Album ID: %s\n", album->album_id);
@@ -38,7 +45,9 @@
       g_print ("Discogs: %s\n", album->discogs);
     if (album->wikipedia != NULL)
       g_print ("Wikipedia: %s\n", album->wikipedia);
-    g_print ("'%s', by %s\n", album->title, album->artist);
+    disc_number = g_strdup_printf (" (Disc %d)", album->disc_number);
+    g_print ("'%s', by %s%s\n", album->title, album->artist, album->disc_number ? disc_number : "");
+    g_free (disc_number);
     while (album->tracks) {
       TrackDetails *track = (TrackDetails*)album->tracks->data;
       g_print (" Track %d; Title: %s; Artist: %s Duration: %d sec\n", track->number, track->title, track->artist, track->duration);
@@ -53,16 +62,17 @@
 
 int main (int argc, char** argv)
 {
-  SjMetadata *metadata;
+  SjMetadataGetter *metadata;
   GMainLoop *loop;
+  GError *error = NULL;
 
   g_type_init ();
   g_thread_init (NULL);
   
-  metadata = (SjMetadata*)sj_metadata_musicbrainz_new ();
+  metadata = sj_metadata_getter_new ();
 
   if (argc == 2) {
-    sj_metadata_set_cdrom (metadata, argv[1]);
+    sj_metadata_getter_set_cdrom (metadata, argv[1]);
   } else {
     g_print ("Usage: %s [CD device]\n", argv[0]);
     exit (1);
@@ -70,7 +80,11 @@
 
   g_signal_connect (G_OBJECT (metadata), "metadata",
 		    G_CALLBACK (metadata_cb), NULL);
-  sj_metadata_list_albums (metadata, NULL);
+  if (sj_metadata_getter_list_albums (metadata, &error) == FALSE) {
+    g_warning ("Couldn't list tracks on album: %s", error->message);
+    g_error_free (error);
+    return 1;
+  }
 
   loop = g_main_loop_new (NULL, FALSE);
   g_main_loop_run (loop);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]