[sound-juicer] mb4: add CD info retrieval using libmusicbrainz4



commit feb2589e39c35a2c2e8c2001bfbc97357984c415
Author: Christophe Fergeau <cfergeau redhat com>
Date:   Mon Aug 1 00:16:43 2011 +0200

    mb4: add CD info retrieval using libmusicbrainz4
    
    This code should be able to retrieve at least as much information
    from musicbrainz as the libmusicbrainz3 code, with the added
    advantage that multi-disc CDs are working as expected. However,
    extraction of the discid of a physical CD is no longer done by
    libmusicbrainz4 and will have to be done using libdiscid

 libjuicer/sj-metadata-musicbrainz4.c |  473 +++++++++++++++++++++++++---------
 1 files changed, 348 insertions(+), 125 deletions(-)
---
diff --git a/libjuicer/sj-metadata-musicbrainz4.c b/libjuicer/sj-metadata-musicbrainz4.c
index 9f12692..e9abc6a 100644
--- a/libjuicer/sj-metadata-musicbrainz4.c
+++ b/libjuicer/sj-metadata-musicbrainz4.c
@@ -2,6 +2,7 @@
  * sj-metadata-musicbrainz4.c
  * Copyright (C) 2008 Ross Burton <ross burtonini com>
  * Copyright (C) 2008 Bastien Nocera <hadess hadess net>
+ * Copyright (C) 2011 Christophe Fergeau <cfergeau redhat com>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -28,7 +29,7 @@
 #include <glib.h>
 #include <glib-object.h>
 #include <gconf/gconf-client.h>
-#include <musicbrainz4/mb_c.h>
+#include <musicbrainz4/mb4_c.h>
 
 #include "sj-metadata-musicbrainz4.h"
 #include "sj-structures.h"
@@ -71,10 +72,10 @@
 #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 {
-  MbWebService mb;
-  MbDisc disc;
+  Mb4Query mb;
   char *cdrom;
   /* Proxy */
   char *http_proxy;
@@ -105,45 +106,287 @@ G_DEFINE_TYPE_WITH_CODE (SjMetadataMusicbrainz4,
  * Private methods
  */
 
+
+struct _SjMb4ArtistDetails {
+  char *id;
+  char *name;
+  char *sortname;
+  char *disambiguation;
+  char *gender;
+  char *country;
+
+  /* doesn't belong in here, prevent sharing the artist structure between
+   * distinct ReleaseGroups - more convenient for now */
+  char *joinphrase;
+};
+typedef struct _SjMb4ArtistDetails SjMb4ArtistDetails;
+
+struct _SjMb4AlbumDetails {
+    AlbumDetails parent;
+    GList *artists;
+    char *status;
+    char *quality;
+    char *disambiguation;
+    char *packaging;
+    char *country;
+    char *barcode;
+    char *type;
+    char *comment;
+    char *format;
+};
+typedef struct _SjMb4AlbumDetails SjMb4AlbumDetails;
+
+struct _SjMb4TrackDetails {
+    TrackDetails parent;
+    GList *artists;
+};
+typedef struct _SjMb4TrackDetails SjMb4TrackDetails;
+
+static void
+sj_mb4_artist_details_free (SjMb4ArtistDetails *details)
+{
+  g_free (details->id);
+  g_free (details->name);
+  g_free (details->sortname);
+  g_free (details->disambiguation);
+  g_free (details->gender);
+  g_free (details->country);
+  g_free (details->joinphrase);
+  g_free (details);
+}
+
+static void
+sj_mb4_track_details_free (SjMb4TrackDetails *details)
+{
+  g_list_foreach (details->artists, (GFunc)sj_mb4_artist_details_free, NULL);
+  g_list_free (details->artists);
+  track_details_free ((TrackDetails *)details);
+}
+
+static void
+sj_mb4_album_details_free (SjMb4AlbumDetails *details)
+{
+  g_list_foreach (details->artists, (GFunc)sj_mb4_artist_details_free, NULL);
+  g_list_free (details->artists);
+  g_free (details->status);
+  g_free (details->quality);
+  g_free (details->disambiguation);
+  g_free (details->packaging);
+  g_free (details->country);
+  g_free (details->barcode);
+  g_free (details->type);
+  g_free (details->comment);
+  g_free (details->format);
+  g_list_foreach (details->parent.tracks, (GFunc)sj_mb4_track_details_free, NULL);
+  g_list_free (details->parent.tracks);
+  /* prevent album_details_free from double-freeing ::tracks */
+  details->parent.tracks = NULL;
+  album_details_free ((AlbumDetails *)details);
+}
+
+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;
+    SjMb4ArtistDetails *details;
+
+    name_credit = mb4_namecredit_list_item (name_list, i);
+    details = g_new0 (SjMb4ArtistDetails, 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);
+      mb4_namecredit_delete (name_credit);
+      continue;
+    }
+
+    GET_ID (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);
+    mb4_namecredit_delete (name_credit);
+  }
+
+  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) {
+    SjMb4ArtistDetails *details = (SjMb4ArtistDetails *)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 {
+      SjMb4ArtistDetails *details = (SjMb4ArtistDetails *)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_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;
+    SjMb4TrackDetails *mb4_track;
+
+    mbt = mb4_track_list_item (track_list, i);
+    if (!mbt)
+      continue;
+
+    mb4_track = g_new0 (SjMb4TrackDetails, 1);
+    track = &mb4_track->parent;
+
+    track->album = album;
+
+    track->number = mb4_track_get_position (mbt);
+    GET_ID (track->track_id, mb_track_get_id, mbt);
+    recording = mb4_track_get_recording (mbt);
+    if (recording != NULL) {
+      GET (track->title, mb4_recording_get_title, 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);
+      }
+      mb4_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);
+    mb4_track_delete (mbt);
+  }
+  album->tracks = g_list_reverse (tracks);
+}
+
 static AlbumDetails *
-make_album_from_release (MbRelease *release)
+make_album_from_release (Mb4Release release, Mb4Medium medium)
 {
   AlbumDetails *album;
-  char buffer[512];
-  MbArtist artist;
+  SjMb4AlbumDetails *mb4_album;
+  Mb4ArtistCredit credit;
+  Mb4ReleaseGroup group;
+  GList *artists;
+  char *date = NULL;
   char *new_title;
-  int i;
+  char buffer[512]; /* for the GET macro */
 
   g_assert (release);
+  g_return_val_if_fail (medium != NULL, NULL);
 
-  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;
-  }
+  mb4_album = g_new0 (SjMb4AlbumDetails, 1);
+  album = &mb4_album->parent;
 
-  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);
+  GET_ID (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);
 
-  if (mb_release_get_num_release_events (release) >= 1) {
-    MbReleaseEvent event;
-    char *date = NULL;
+  credit = mb4_release_get_artistcredit (release);
 
-    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);
+  artists = get_artist_list (credit);
+  if (artists) {
+    get_artist_info (artists, &album->artist,
+                     &album->artist_sortname,
+                     &album->artist_id);
   }
+  mb4_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 (mb4_album->status, mb4_release_get_status, release);
+  GET (mb4_album->quality, mb4_release_get_quality, release);
+  GET (mb4_album->disambiguation, mb4_release_get_disambiguation, release);
+  GET (mb4_album->packaging, mb4_release_get_packaging, release);
+  GET (mb4_album->country, mb4_release_get_country, release);
+  GET (mb4_album->barcode, mb4_release_get_barcode, release);
+  group = mb4_release_get_releasegroup (release);
+  if (group) {
+    GET (mb4_album->type, mb4_releasegroup_get_type, group);
+    GET (mb4_album->comment, mb4_releasegroup_get_comment, group);
+  }
+  GET(mb4_album->format, mb4_medium_get_format, medium);
 
-  album->number = mb_release_get_num_tracks (release);
-  GET (album->asin, mb_release_get_asin, release);
-
+#if 0
   for (i = 0; i < mb_release_get_num_relations (release); i++) {
     MbRelation relation;
     char *type = NULL;
@@ -158,7 +401,11 @@ make_album_from_release (MbRelease *release)
     }
     g_free (type);
   }
+#else
+  g_warning("Relations not handled");
+#endif
 
+#if 0
   for (i = 0; i < mb_release_get_num_types (release); i++) {
     mb_release_get_type (release, i, buffer, sizeof(buffer));
 
@@ -169,80 +416,41 @@ make_album_from_release (MbRelease *release)
       break;
     }
   }
+#else
+  /* If it ReleaseGroup::type that we want or something else? */
+  g_warning("Recording type not handled");
+#endif
 
-  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);
-  }
+  album->disc_number = mb4_medium_get_position (medium);
+  fill_tracks_from_medium (medium, album);
 
   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)
+mb4_list_albums (SjMetadata *metadata, char **url, GError **error)
 {
   SjMetadataMusicbrainz4Private *priv;
   GList *albums = NULL;
-  MbQuery query;
-  MbReleaseFilter filter;
-  MbResultList results;
-  MbRelease release;
-  char *id = NULL;
+  Mb4ReleaseList releases;
+  Mb4Release release;
+  char *discid = NULL;
   char buffer[1024];
   int i;
   g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ4 (metadata), NULL);
 
   priv = GET_PRIVATE (metadata);
 
+#if 0
   if (sj_metadata_helper_check_media (priv->cdrom, error) == FALSE) {
     return NULL;
   }
+#endif
 
+#if 0
   priv->disc = mb_read_disc (priv->cdrom);
   if (priv->disc == NULL)
     return NULL;
@@ -251,54 +459,68 @@ mb_list_albums (SjMetadata *metadata, char **url, GError **error)
     mb_get_submission_url (priv->disc, NULL, 0, buffer, sizeof (buffer));
     *url = g_strdup (buffer);
   }
+#endif
+  g_warning("no reading of disc");
+  /* priv->disc = NULL; */
+  g_warning("no setting of url");
+  *url = NULL;
 
   if (g_getenv("MUSICBRAINZ_FORCE_DISC_ID")) {
-    id = g_strdup (g_getenv("MUSICBRAINZ_FORCE_DISC_ID"));
+    discid = g_strdup (g_getenv("MUSICBRAINZ_FORCE_DISC_ID"));
   } else {
-    GET(id, mb_disc_get_id, priv->disc);
+    g_warning("no MusicBrainz ID, use MISICBRAINZ_FORCE_DISC_ID");
+    //GET(discid, 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);
+  releases = mb4_query_lookup_discid(priv->mb, discid);
 
-  if (results == NULL) {
-    mb_query_free (query);
+  if (releases == NULL) {
+    g_free (discid);
     return NULL;
   }
 
-  if (mb_result_list_get_size (results) == 0) {
-    mb_result_list_free (results);
-    mb_query_free (query);
+  if (mb4_release_list_size (releases) == 0) {
+    mb4_release_list_delete (releases);
+    g_free (discid);
     return NULL;
   }
 
-  for (i = 0; i < mb_result_list_get_size (results); i++) {
+  for (i = 0; i < mb4_release_list_size (releases); 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);
+
+    release = mb4_release_list_item (releases, i);
+    if (release) {
+      char *releaseid;
+      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;
+        unsigned int j;
+
+        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 (full_release, medium);
+            album->metadata_source = SOURCE_MUSICBRAINZ;
+            albums = g_list_append (albums, album);
+            mb4_medium_delete (medium);
+          }
+        }
+        mb4_medium_list_delete (media);
+        mb4_release_delete (full_release);
       }
+      mb4_release_delete (release);
     }
   }
-  mb_result_list_free (results);
-  mb_query_free (query);
-
+  mb4_release_list_delete (releases);
+  g_free (discid);
   return albums;
 }
 
@@ -311,7 +533,7 @@ metadata_interface_init (gpointer g_iface, gpointer iface_data)
 {
   SjMetadataClass *klass = (SjMetadataClass*)g_iface;
 
-  klass->list_albums = mb_list_albums;
+  klass->list_albums = mb4_list_albums;
 }
 
 static void
@@ -324,39 +546,40 @@ sj_metadata_musicbrainz4_init (SjMetadataMusicbrainz4 *self)
 
   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);
+  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);
-    mb_webservice_set_proxy_host (priv->mb, proxy_host);
+    mb4_query_set_proxyhost (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);
+    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);
-      mb_webservice_set_proxy_username (priv->mb, username);
+      mb4_query_set_proxyusername (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);
+      mb4_query_set_proxypassword (priv->mb, password);
       g_free (password);
     }
   }
@@ -405,11 +628,11 @@ sj_metadata_musicbrainz4_set_property (GObject *object, guint property_id,
     }
     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);
+    mb4_query_set_proxyhost (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);
+    mb4_query_set_proxyport (priv->mb, priv->http_proxy_port);
     break;
   default:
     G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);



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