diff options
author | Christophe Fergeau <cfergeau@redhat.com> | 2011-08-01 00:16:43 +0200 |
---|---|---|
committer | Christophe Fergeau <cfergeau@redhat.com> | 2012-01-13 00:26:48 +0100 |
commit | feb2589e39c35a2c2e8c2001bfbc97357984c415 (patch) | |
tree | 8b4d3c4bb58de53f590cd873c85c721da9f6b222 /libjuicer | |
parent | 2dae7d743f490a38428607c0b6db6df22aa5f055 (diff) |
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
Diffstat (limited to 'libjuicer')
-rw-r--r-- | 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); |