~snaggen/rhythmbox/bpm

« back to all changes in this revision

Viewing changes to plugins/audiocd/sj-metadata-musicbrainz.c

  • Committer: Mattias Eriksson
  • Date: 2010-05-27 14:59:38 UTC
  • mfrom: (5129.1.1718)
  • Revision ID: mattias.eriksson@vizrt.com-20100527145938-953igy66p4u17fuz
Re-sync bpm branch with trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#endif /* HAVE_CONFIG_H */
24
24
 
25
25
#include <string.h>
26
 
#include <stdio.h>
27
26
#include <glib-object.h>
28
27
#include <glib/gi18n.h>
29
 
#include <glib/gerror.h>
30
 
#include <glib/glist.h>
31
 
#include <glib/gstrfuncs.h>
32
 
#include <glib/gmessages.h>
 
28
#include <glib.h>
33
29
#include <gconf/gconf-client.h>
34
30
#include <musicbrainz/queries.h>
35
31
#include <musicbrainz/mb_c.h>
36
32
#include <stdlib.h>
37
 
#include <unistd.h>
38
 
 
39
 
#include <nautilus-burn-drive.h>
40
 
#ifndef NAUTILUS_BURN_CHECK_VERSION
41
 
#define NAUTILUS_BURN_CHECK_VERSION(a,b,c) FALSE
42
 
#endif
43
 
 
44
 
#if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
45
 
#include <nautilus-burn.h>
46
 
#endif
47
 
 
48
 
#ifndef HAVE_BURN_DRIVE_UNREF
49
 
#define nautilus_burn_drive_unref nautilus_burn_drive_free
50
 
#endif
51
33
 
52
34
#include "sj-metadata-musicbrainz.h"
53
35
#include "sj-structures.h"
54
36
#include "sj-error.h"
55
37
 
56
 
struct SjMetadataMusicbrainzPrivate {
57
 
  GError *construct_error;
58
 
  musicbrainz_t mb;
59
 
  char *http_proxy;
60
 
  int http_proxy_port;
61
 
  char *cdrom;
62
 
  /* TODO: remove and use an async queue or something l33t */
63
 
  GList *albums;
64
 
  GError *error;
65
 
};
66
 
 
67
 
static GError* mb_get_new_error (SjMetadata *metadata);
68
 
static void mb_set_cdrom (SjMetadata *metadata, const char* device);
69
 
static void mb_set_proxy (SjMetadata *metadata, const char* proxy);
70
 
static void mb_set_proxy_port (SjMetadata *metadata, const int port);
71
 
static void mb_list_albums (SjMetadata *metadata, GError **error);
72
 
static char *mb_get_submit_url (SjMetadata *metadata);
73
 
 
74
38
#define GCONF_MUSICBRAINZ_SERVER "/apps/sound-juicer/musicbrainz_server"
75
39
#define GCONF_PROXY_USE_PROXY "/system/http_proxy/use_http_proxy"
76
40
#define GCONF_PROXY_HOST "/system/http_proxy/host"
79
43
#define GCONF_PROXY_USERNAME "/system/http_proxy/authentication_user"
80
44
#define GCONF_PROXY_PASSWORD "/system/http_proxy/authentication_password"
81
45
 
82
 
/**
83
 
 * GObject methods
84
 
 */
85
 
 
86
 
static GObjectClass *parent_class = NULL;
87
 
 
88
 
static void
89
 
sj_metadata_musicbrainz_finalize (GObject *object)
90
 
{
91
 
  SjMetadataMusicbrainzPrivate *priv;
92
 
  g_return_if_fail (object != NULL);
93
 
  priv = SJ_METADATA_MUSICBRAINZ (object)->priv;
94
 
 
95
 
  g_free (priv->http_proxy);
96
 
  g_free (priv->cdrom);
97
 
  mb_Delete (priv->mb);
98
 
  g_free (priv);
99
 
 
100
 
  parent_class->finalize (object);
101
 
}
102
 
 
103
 
static void
104
 
sj_metadata_musicbrainz_instance_init (GTypeInstance *instance, gpointer g_class)
105
 
{
106
 
  GConfClient *gconf_client;
107
 
  char *server_name = NULL;
108
 
  SjMetadataMusicbrainz *self = (SjMetadataMusicbrainz*)instance;
109
 
  self->priv = g_new0 (SjMetadataMusicbrainzPrivate, 1);
110
 
  self->priv->construct_error = NULL;
111
 
  self->priv->mb = mb_New ();
112
 
  /* TODO: something. :/ */
113
 
  if (!self->priv->mb) {
114
 
    g_set_error (&self->priv->construct_error,
115
 
                 SJ_ERROR, SJ_ERROR_CD_LOOKUP_ERROR,
116
 
                 _("Cannot create MusicBrainz client"));
117
 
    return;
118
 
  }
119
 
  mb_UseUTF8 (self->priv->mb, TRUE);
120
 
 
121
 
  gconf_client = gconf_client_get_default ();
122
 
  server_name = gconf_client_get_string (gconf_client, GCONF_MUSICBRAINZ_SERVER, NULL);
123
 
  if (server_name) {
124
 
    g_strstrip (server_name);
125
 
  }
126
 
  if (server_name && strcmp (server_name, "") != 0) {
127
 
    mb_SetServer (self->priv->mb, server_name, 80);
128
 
    g_free (server_name);
129
 
  }
130
 
  
131
 
  /* Set the HTTP proxy */
132
 
  if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_PROXY, NULL)) {
133
 
    char *proxy_host = gconf_client_get_string (gconf_client, GCONF_PROXY_HOST, NULL);
134
 
    mb_SetProxy (self->priv->mb, proxy_host,
135
 
                 gconf_client_get_int (gconf_client, GCONF_PROXY_PORT, NULL));
136
 
    g_free (proxy_host);
137
 
    if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_AUTHENTICATION, NULL)) {
138
 
#if HAVE_MB_SETPROXYCREDS
139
 
      char *username = gconf_client_get_string (gconf_client, GCONF_PROXY_USERNAME, NULL);
140
 
      char *password = gconf_client_get_string (gconf_client, GCONF_PROXY_PASSWORD, NULL);
141
 
      mb_SetProxyCreds (self->priv->mb, username, password);
142
 
      g_free (username);
143
 
      g_free (password);
144
 
#else
145
 
      g_warning ("mb_SetProxyCreds() not found, no proxy authorisation possible.");
146
 
#endif
147
 
    }
148
 
  }
149
 
 
150
 
  g_object_unref (gconf_client);
151
 
 
152
 
  if (g_getenv("MUSICBRAINZ_DEBUG")) {
153
 
    mb_SetDebug (self->priv->mb, TRUE);
154
 
  }
155
 
}
156
 
 
157
 
static void
158
 
metadata_interface_init (gpointer g_iface, gpointer iface_data)
159
 
{
160
 
  SjMetadataClass *klass = (SjMetadataClass*)g_iface;
161
 
  klass->get_new_error = mb_get_new_error;
162
 
  klass->set_cdrom = mb_set_cdrom;
163
 
  klass->set_proxy = mb_set_proxy;
164
 
  klass->set_proxy_port = mb_set_proxy_port;
165
 
  klass->list_albums = mb_list_albums;
166
 
  klass->get_submit_url = mb_get_submit_url;
167
 
}
168
 
 
169
 
static void
170
 
sj_metadata_musicbrainz_class_init (SjMetadataMusicbrainzClass *class)
171
 
{
172
 
  GObjectClass *object_class;
173
 
  parent_class = g_type_class_peek_parent (class);
174
 
  object_class = (GObjectClass*) class;
175
 
  object_class->finalize = sj_metadata_musicbrainz_finalize;
176
 
}
177
 
 
178
 
GType
179
 
sj_metadata_musicbrainz_get_type (void)
180
 
{
181
 
  static GType type = 0;
182
 
  if (type == 0) {
183
 
    static const GTypeInfo info = {
184
 
      sizeof (SjMetadataMusicbrainzClass),
185
 
      NULL,
186
 
      NULL,
187
 
      (GClassInitFunc)sj_metadata_musicbrainz_class_init,
188
 
      NULL,
189
 
      NULL,
190
 
      sizeof (SjMetadataMusicbrainz),
191
 
      0,
192
 
      sj_metadata_musicbrainz_instance_init,
193
 
      NULL
194
 
    };
195
 
    static const GInterfaceInfo metadata_i_info = {
196
 
      (GInterfaceInitFunc) metadata_interface_init,
197
 
      NULL, NULL
198
 
    };
199
 
    type = g_type_register_static (G_TYPE_OBJECT, "SjMetadataMusicBrainzClass", &info, 0);
200
 
    g_type_add_interface_static (type, SJ_TYPE_METADATA, &metadata_i_info);
201
 
  }
202
 
  return type;
203
 
}
204
 
 
205
 
GObject *
206
 
sj_metadata_musicbrainz_new (void)
207
 
{
208
 
  return g_object_new (sj_metadata_musicbrainz_get_type (), NULL);
209
 
}
210
 
 
211
 
/**
 
46
 
 
47
struct SjMetadataMusicbrainzPrivate {
 
48
  musicbrainz_t mb;
 
49
  char *http_proxy;
 
50
  int http_proxy_port;
 
51
  char *cdrom;
 
52
  GList *albums;
 
53
};
 
54
 
 
55
#define GET_PRIVATE(o)  \
 
56
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), SJ_TYPE_METADATA_MUSICBRAINZ, SjMetadataMusicbrainzPrivate))
 
57
 
 
58
enum {
 
59
  PROP_0,
 
60
  PROP_DEVICE,
 
61
  PROP_USE_PROXY,
 
62
  PROP_PROXY_HOST,
 
63
  PROP_PROXY_PORT,
 
64
};
 
65
 
 
66
static void metadata_interface_init (gpointer g_iface, gpointer iface_data);
 
67
 
 
68
G_DEFINE_TYPE_WITH_CODE (SjMetadataMusicbrainz,
 
69
                         sj_metadata_musicbrainz,
 
70
                         G_TYPE_OBJECT,
 
71
                         G_IMPLEMENT_INTERFACE (SJ_TYPE_METADATA,
 
72
                                                metadata_interface_init));
 
73
 
 
74
 
 
75
/*
212
76
 * Private methods
213
77
 */
214
78
 
 
79
static int
 
80
get_duration_from_sectors (int sectors)
 
81
{
215
82
#define BYTES_PER_SECTOR 2352
216
83
#define BYTES_PER_SECOND (44100 / 8) / 16 / 2
217
 
 
218
 
static int
219
 
get_duration_from_sectors (int sectors)
220
 
{
 
84
  
221
85
  return (sectors * BYTES_PER_SECTOR / BYTES_PER_SECOND);
222
86
}
223
87
 
224
 
static GList*
225
 
get_offline_track_listing(SjMetadata *metadata, GError **error)
226
 
{
227
 
  SjMetadataMusicbrainzPrivate *priv;
228
 
  GList* list = NULL;
229
 
  AlbumDetails *album;
230
 
  TrackDetails *track;
231
 
  int num_tracks, i;
232
 
 
233
 
  g_return_val_if_fail (metadata != NULL, NULL);
234
 
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
235
 
 
236
 
  if (!mb_Query (priv->mb, MBQ_GetCDTOC)) {
237
 
    char message[255];
238
 
    mb_GetQueryError (priv->mb, message, 255);
239
 
    g_set_error (error,
240
 
                 SJ_ERROR, SJ_ERROR_CD_LOOKUP_ERROR,
241
 
                 _("Cannot read CD: %s"), message);
242
 
    return NULL;
243
 
  }
244
 
  
245
 
  num_tracks = mb_GetResultInt (priv->mb, MBE_TOCGetLastTrack);
246
 
 
247
 
  album = g_new0 (AlbumDetails, 1);
248
 
  album->artist = g_strdup (_("Unknown Artist"));
249
 
  album->title = g_strdup (_("Unknown Title"));
250
 
  album->genre = NULL;
251
 
  for (i = 1; i <= num_tracks; i++) {
252
 
    track = g_new0 (TrackDetails, 1);
253
 
    track->album = album;
254
 
    track->number = i;
255
 
    track->title = g_strdup_printf (_("Track %d"), i);
256
 
    track->artist = g_strdup (album->artist);
257
 
    track->duration = get_duration_from_sectors (mb_GetResultInt1 (priv->mb, MBE_TOCGetTrackNumSectors, i+1));
258
 
    album->tracks = g_list_append (album->tracks, track);
259
 
    album->number++;
260
 
  }
261
 
  return g_list_append (list, album);
262
 
}
263
 
 
264
 
static gboolean
265
 
fire_signal_idle (SjMetadataMusicbrainz *m)
266
 
{
267
 
  g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ (m), FALSE);
268
 
  g_signal_emit_by_name (G_OBJECT (m), "metadata", m->priv->albums, m->priv->error);
269
 
  return FALSE;
270
 
}
271
 
 
272
 
/**
 
88
/*
273
89
 * Virtual methods
274
90
 */
275
91
 
276
 
static GError*
277
 
mb_get_new_error (SjMetadata *metadata)
278
 
{
279
 
  GError *error = NULL;
280
 
  if (metadata == NULL || SJ_METADATA_MUSICBRAINZ (metadata)->priv == NULL) {
281
 
    g_set_error (&error,
282
 
                 SJ_ERROR, SJ_ERROR_INTERNAL_ERROR,
283
 
                 _("MusicBrainz metadata object is not valid. This is bad, check your console for errors."));
284
 
    return error;
285
 
  }
286
 
  return SJ_METADATA_MUSICBRAINZ (metadata)->priv->construct_error;
287
 
}
288
 
 
289
 
static void
290
 
mb_set_cdrom (SjMetadata *metadata, const char* device)
291
 
{
292
 
  SjMetadataMusicbrainzPrivate *priv;
293
 
  g_return_if_fail (metadata != NULL);
294
 
  g_return_if_fail (device != NULL);
295
 
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
296
 
 
297
 
  if (priv->cdrom) {
298
 
    g_free (priv->cdrom);
299
 
  }
300
 
  priv->cdrom = g_strdup (device);
301
 
  mb_SetDevice (priv->mb, priv->cdrom);
302
 
}
303
 
 
304
 
static void
305
 
mb_set_proxy (SjMetadata *metadata, const char* proxy)
306
 
{
307
 
  SjMetadataMusicbrainzPrivate *priv;
308
 
  g_return_if_fail (metadata != NULL);
309
 
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
310
 
 
311
 
  if (proxy == NULL) {
312
 
    proxy = "";
313
 
  }
314
 
  if (priv->http_proxy) {
315
 
    g_free (priv->http_proxy);
316
 
  }
317
 
  priv->http_proxy = g_strdup (proxy);
318
 
  mb_SetProxy (priv->mb, priv->http_proxy, priv->http_proxy_port);
319
 
}
320
 
 
321
 
static void
322
 
mb_set_proxy_port (SjMetadata *metadata, const int port)
323
 
{
324
 
  SjMetadataMusicbrainzPrivate *priv;
325
 
  g_return_if_fail (metadata != NULL);
326
 
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
327
 
 
328
 
  priv->http_proxy_port = port;
329
 
  mb_SetProxy (priv->mb, priv->http_proxy, priv->http_proxy_port);
330
 
}
331
 
 
332
92
/* Data imported from FreeDB is horrendeous for compilations,
333
93
 * Try to split the 'Various' artist */
334
94
static void
336
96
{
337
97
  char *slash, **split;
338
98
 
339
 
  if (g_ascii_strncasecmp (MBI_VARIOUS_ARTIST_ID, track->album->artist_id, 64) != 0 && track->album->artist_id[0] != '\0' && track->artist_id[0] != '\0') {
 
99
  if (g_ascii_strncasecmp (track->album->album_id, "freedb:", 7) != 0 && track->album->artist_id[0] != '\0' && track->artist_id[0] != '\0') {
340
100
    track->title = g_strdup (data);
341
101
    return;
342
102
  }
353
113
}
354
114
 
355
115
#if WITH_CACHE
356
 
/**
 
116
/*
357
117
 * Write the RDF in the MusicBrainz object to the file specified.
358
118
 */
359
119
static void
385
145
  g_free (rdf);
386
146
}
387
147
 
388
 
/**
 
148
/*
389
149
 * Load into the MusicBrainz object the RDF from the specified cache file if it
390
150
 * exists and is valid then return TRUE, otherwise return FALSE.
391
151
 */
428
188
}
429
189
#endif
430
190
 
431
 
/**
 
191
/*
432
192
 * Fill the MusicBrainz object with RDF.  Basically get the CD Index and check
433
193
 * the local cache, if that fails then lookup the data online.
434
194
 */
479
239
  g_free (cdindex);
480
240
}
481
241
 
482
 
static NautilusBurnMediaType
483
 
get_drive_media_type (SjMetadata *metadata)
 
242
/*
 
243
 * Magic character set encoding to try and repair brain-dead FreeDB encoding,
 
244
 * converting it to the current locale's encoding (which is likely to be the
 
245
 * intended encoding).
 
246
 */
 
247
static void
 
248
convert_encoding(char **str)
484
249
{
485
 
  SjMetadataMusicbrainzPrivate *priv;
486
 
  NautilusBurnDrive *drive;
487
 
  NautilusBurnMediaType type;
488
 
#if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
489
 
  NautilusBurnDriveMonitor *monitor;
490
 
#endif
491
 
 
492
 
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
493
 
#if NAUTILUS_BURN_CHECK_VERSION(2,15,3)
494
 
  if (! nautilus_burn_initialized ()) {
495
 
    nautilus_burn_init ();
496
 
  }
497
 
  monitor = nautilus_burn_get_drive_monitor ();
498
 
  drive = nautilus_burn_drive_monitor_get_drive_for_device (monitor, priv->cdrom);
499
 
#else
500
 
  drive = nautilus_burn_drive_new_from_path (priv->cdrom);
501
 
#endif
502
 
 
503
 
  if (drive == NULL) {
504
 
    return NAUTILUS_BURN_MEDIA_TYPE_ERROR;
505
 
  }
506
 
  type = nautilus_burn_drive_get_media_type (drive);
507
 
  nautilus_burn_drive_unref (drive);
508
 
  return type;
 
250
  char *iso8859;
 
251
  char *converted;
 
252
 
 
253
  if (str == NULL || *str == NULL)
 
254
    return;
 
255
 
 
256
  iso8859 = g_convert (*str, -1, "ISO-8859-1", "UTF-8", NULL, NULL, NULL);
 
257
 
 
258
  if (iso8859) {
 
259
    converted = g_locale_to_utf8 (iso8859, -1, NULL, NULL, NULL);
 
260
 
 
261
    if (converted) {
 
262
      g_free (*str);
 
263
      *str = converted;
 
264
    }
 
265
  }
 
266
 
 
267
  g_free (iso8859);
509
268
}
510
269
 
511
 
static gpointer
512
 
lookup_cd (SjMetadata *metadata)
 
270
static GList *
 
271
mb_list_albums (SjMetadata *metadata, char **url, GError **error)
513
272
{
514
 
  /** The size of the buffer used in MusicBrainz lookups */
 
273
  /* The size of the buffer used in MusicBrainz lookups */
515
274
  SjMetadataMusicbrainzPrivate *priv;
516
275
  GList *albums = NULL;
517
276
  GList *al, *tl;
518
 
  char data[256];
 
277
  char data[1024];
519
278
  int num_albums, i, j;
520
 
  NautilusBurnMediaType type;
521
279
 
522
 
  /* TODO: fire error signal */
523
280
  g_return_val_if_fail (metadata != NULL, NULL);
524
281
  g_return_val_if_fail (SJ_IS_METADATA_MUSICBRAINZ (metadata), NULL);
525
282
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
526
283
  g_return_val_if_fail (priv->cdrom != NULL, NULL);
527
 
  priv->error = NULL; /* TODO: hack */
528
 
 
529
 
  type = get_drive_media_type (metadata);
530
 
 
531
 
  if (type == NAUTILUS_BURN_MEDIA_TYPE_ERROR) {
532
 
    char *msg;
533
 
    SjError err;
534
 
 
535
 
    if (access (priv->cdrom, W_OK) == 0) {
536
 
      msg = g_strdup_printf (_("Device '%s' does not contain any media"), priv->cdrom);
537
 
      err = SJ_ERROR_CD_NO_MEDIA;
538
 
    } else {
539
 
      msg = g_strdup_printf (_("Device '%s' could not be opened. Check the access permissions on the device."), priv->cdrom);
540
 
      err = SJ_ERROR_CD_PERMISSION_ERROR;
541
 
    }
542
 
    priv->error = g_error_new (SJ_ERROR, err, _("Cannot read CD: %s"), msg);
543
 
    g_free (msg);
544
 
 
 
284
 
 
285
  if (sj_metadata_helper_check_media (priv->cdrom, error) == FALSE) {
545
286
    priv->albums = NULL;
546
 
    g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
547
287
    return NULL;
548
288
  }
549
289
 
550
290
  get_rdf (metadata);
551
291
 
 
292
  if (url != NULL) {
 
293
    mb_GetWebSubmitURL(priv->mb, data, sizeof(data));
 
294
    *url = g_strdup(data);
 
295
  }
 
296
 
552
297
  num_albums = mb_GetResultInt(priv->mb, MBE_GetNumAlbums);
553
298
  if (num_albums < 1) {
554
 
    priv->albums = get_offline_track_listing (metadata, &(priv->error));
555
 
    g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
556
 
    return priv->albums;
 
299
    priv->albums = NULL;
 
300
    return NULL;
557
301
  }
558
302
 
559
303
  for (i = 1; i <= num_albums; i++) {
560
304
    int num_tracks;
561
305
    AlbumDetails *album;
 
306
    gboolean from_freedb = FALSE;
562
307
 
563
308
    mb_Select1(priv->mb, MBS_SelectAlbum, i);
564
309
    album = g_new0 (AlbumDetails, 1);
565
310
 
566
311
    if (mb_GetResultData(priv->mb, MBE_AlbumGetAlbumId, data, sizeof (data))) {
 
312
      from_freedb = strstr(data, "freedb:") == data;
 
313
 
567
314
      mb_GetIDFromURL (priv->mb, data, data, sizeof (data));
568
315
      album->album_id = g_strdup (data);
569
316
    }
571
318
    if (mb_GetResultData (priv->mb, MBE_AlbumGetAlbumArtistId, data, sizeof (data))) {
572
319
      mb_GetIDFromURL (priv->mb, data, data, sizeof (data));
573
320
      album->artist_id = g_strdup (data);
574
 
      if (g_ascii_strncasecmp (MBI_VARIOUS_ARTIST_ID, data, 64) == 0) {
575
 
        album->artist = g_strdup (_("Various"));
 
321
 
 
322
      if (mb_GetResultData (priv->mb, MBE_AlbumGetAlbumArtistName, data, sizeof (data))) {
 
323
        album->artist = g_strdup (data);
576
324
      } else {
577
 
        if (*data && mb_GetResultData1(priv->mb, MBE_AlbumGetArtistName, data, sizeof (data), 1)) {
578
 
          album->artist = g_strdup (data);
 
325
        if (g_ascii_strcasecmp (MBI_VARIOUS_ARTIST_ID, album->artist_id) == 0) {
 
326
          album->artist = g_strdup (_("Various"));
579
327
        } else {
580
328
          album->artist = g_strdup (_("Unknown Artist"));
581
329
        }
582
 
        if (*data && mb_GetResultData1(priv->mb, MBE_AlbumGetArtistSortName, data, sizeof (data), 1)) {
583
 
          album->artist_sortname = g_strdup (data);
584
 
        }
 
330
      }
 
331
      if (mb_GetResultData(priv->mb, MBE_AlbumGetAlbumArtistSortName, data, sizeof (data))) {
 
332
        album->artist_sortname = g_strdup (data);
585
333
      }
586
334
    }
587
335
 
588
336
    if (mb_GetResultData(priv->mb, MBE_AlbumGetAlbumName, data, sizeof (data))) {
589
 
      album->title = g_strdup (data);
 
337
      char *new_title;
 
338
      new_title = sj_metadata_helper_scan_disc_number (data, &album->disc_number);
 
339
      if (new_title)
 
340
        album->title = new_title;
 
341
      else
 
342
        album->title = g_strdup (data);
590
343
    } else {
591
344
      album->title = g_strdup (_("Unknown Title"));
592
345
    }
593
346
 
 
347
    if (mb_GetResultData(priv->mb, MBE_AlbumGetAmazonAsin, data, sizeof (data))) {
 
348
      album->asin = g_strdup (data);
 
349
    }
 
350
 
594
351
    {
595
352
      int num_releases;
596
353
      num_releases = mb_GetResultInt (priv->mb, MBE_AlbumGetNumReleaseDates);
597
354
      if (num_releases > 0) {
598
355
        mb_Select1(priv->mb, MBS_SelectReleaseDate, 1);
599
356
        if (mb_GetResultData(priv->mb, MBE_ReleaseGetDate, data, sizeof (data))) {
600
 
          int matched, year=1, month=1, day=1;
601
 
          matched = sscanf(data, "%u-%u-%u", &year, &month, &day);
602
 
          if (matched >= 1) {
603
 
            album->release_date = g_date_new_dmy ((day == 0) ? 1 : day, (month == 0) ? 1 : month, year);
604
 
          }
 
357
          album->release_date = sj_metadata_helper_scan_date (data);
605
358
        }
606
359
        mb_Select(priv->mb, MBS_Back);
607
360
      }
614
367
      g_free (album->title);
615
368
      g_free (album);
616
369
      g_warning (_("Incomplete metadata for this CD"));
617
 
      priv->albums = get_offline_track_listing (metadata, &(priv->error));
618
 
      g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
619
 
      return priv->albums;
 
370
      priv->albums = NULL;
 
371
      return NULL;
620
372
    }
621
373
 
622
374
    for (j = 1; j <= num_tracks; j++) {
643
395
        } else {
644
396
          track->title = g_strdup (data);
645
397
        }
 
398
      } else {
 
399
        track->title = g_strdup (_("[Untitled]"));
646
400
      }
647
401
 
648
402
      if (track->artist == NULL && mb_GetResultData1(priv->mb, MBE_AlbumGetArtistName, data, sizeof (data), j)) {
656
410
      if (mb_GetResultData1(priv->mb, MBE_AlbumGetTrackDuration, data, sizeof (data), j)) {
657
411
        track->duration = atoi (data) / 1000;
658
412
      }
 
413
 
 
414
      if (from_freedb) {
 
415
        convert_encoding(&track->title);
 
416
        convert_encoding(&track->artist);
 
417
        convert_encoding(&track->artist_sortname);
 
418
      }
659
419
      
660
420
      album->tracks = g_list_append (album->tracks, track);
661
421
      album->number++;
662
422
    }
663
423
 
 
424
    if (from_freedb) {
 
425
      convert_encoding(&album->title);
 
426
      convert_encoding(&album->artist);
 
427
      convert_encoding(&album->artist_sortname);
 
428
    }
 
429
 
 
430
    if (from_freedb) {
 
431
      album->metadata_source = SOURCE_FREEDB;
 
432
    } else {
 
433
      album->metadata_source = SOURCE_MUSICBRAINZ;
 
434
    }
 
435
 
664
436
    albums = g_list_append (albums, album);
665
437
 
666
438
    mb_Select (priv->mb, MBS_Rewind);
688
460
    }
689
461
  }
690
462
 
691
 
  priv->albums = albums;
692
 
  g_idle_add ((GSourceFunc)fire_signal_idle, metadata);
693
463
  return albums;
694
464
}
695
465
 
696
 
static void
697
 
mb_list_albums (SjMetadata *metadata, GError **error)
698
 
{
699
 
  GThread *thread;
700
 
 
701
 
  g_return_if_fail (SJ_IS_METADATA_MUSICBRAINZ (metadata));
702
 
 
703
 
  thread = g_thread_create ((GThreadFunc)lookup_cd, metadata, TRUE, error);
704
 
  if (thread == NULL) {
705
 
    g_set_error (error,
706
 
                 SJ_ERROR, SJ_ERROR_INTERNAL_ERROR,
707
 
                 _("Could not create CD lookup thread"));
708
 
    return;
709
 
  }
710
 
}
711
 
 
712
 
static char *
713
 
mb_get_submit_url (SjMetadata *metadata)
 
466
/*
 
467
 * GObject methods
 
468
 */
 
469
 
 
470
static void
 
471
metadata_interface_init (gpointer g_iface, gpointer iface_data)
 
472
{
 
473
  SjMetadataClass *klass = (SjMetadataClass*)g_iface;
 
474
  klass->list_albums = mb_list_albums;
 
475
}
 
476
 
 
477
static void
 
478
sj_metadata_musicbrainz_init (SjMetadataMusicbrainz *self)
 
479
{
 
480
  GConfClient *gconf_client;
 
481
  char *server_name = NULL;
 
482
 
 
483
  self->priv = GET_PRIVATE (self);
 
484
  self->priv->mb = mb_New ();
 
485
  mb_UseUTF8 (self->priv->mb, TRUE);
 
486
 
 
487
  gconf_client = gconf_client_get_default ();
 
488
  server_name = gconf_client_get_string (gconf_client, GCONF_MUSICBRAINZ_SERVER, NULL);
 
489
  if (server_name) {
 
490
    g_strstrip (server_name);
 
491
  }
 
492
  if (server_name && strcmp (server_name, "") != 0) {
 
493
    mb_SetServer (self->priv->mb, server_name, 80);
 
494
    g_free (server_name);
 
495
  }
 
496
  
 
497
  /* Set the HTTP proxy */
 
498
  if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_PROXY, NULL)) {
 
499
    char *proxy_host = gconf_client_get_string (gconf_client, GCONF_PROXY_HOST, NULL);
 
500
    mb_SetProxy (self->priv->mb, proxy_host,
 
501
                 gconf_client_get_int (gconf_client, GCONF_PROXY_PORT, NULL));
 
502
    g_free (proxy_host);
 
503
    if (gconf_client_get_bool (gconf_client, GCONF_PROXY_USE_AUTHENTICATION, NULL)) {
 
504
#if HAVE_MB_SETPROXYCREDS
 
505
      char *username = gconf_client_get_string (gconf_client, GCONF_PROXY_USERNAME, NULL);
 
506
      char *password = gconf_client_get_string (gconf_client, GCONF_PROXY_PASSWORD, NULL);
 
507
      mb_SetProxyCreds (self->priv->mb, username, password);
 
508
      g_free (username);
 
509
      g_free (password);
 
510
#else
 
511
      g_warning ("mb_SetProxyCreds() not found, no proxy authorisation possible.");
 
512
#endif
 
513
    }
 
514
  }
 
515
 
 
516
  g_object_unref (gconf_client);
 
517
 
 
518
  if (g_getenv("MUSICBRAINZ_DEBUG")) {
 
519
    mb_SetDebug (self->priv->mb, TRUE);
 
520
  }
 
521
}
 
522
 
 
523
static void
 
524
sj_metadata_musicbrainz_get_property (GObject *object, guint property_id,
 
525
                                      GValue *value, GParamSpec *pspec)
 
526
{
 
527
  SjMetadataMusicbrainzPrivate *priv = SJ_METADATA_MUSICBRAINZ (object)->priv;
 
528
  g_assert (priv);
 
529
 
 
530
  switch (property_id) {
 
531
  case PROP_DEVICE:
 
532
    g_value_set_string (value, priv->cdrom);
 
533
    break;
 
534
  case PROP_PROXY_HOST:
 
535
    g_value_set_string (value, priv->http_proxy);
 
536
    break;
 
537
  case PROP_PROXY_PORT:
 
538
    g_value_set_int (value, priv->http_proxy_port);
 
539
    break;
 
540
  default:
 
541
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
542
  }
 
543
}
 
544
 
 
545
static void
 
546
sj_metadata_musicbrainz_set_property (GObject *object, guint property_id,
 
547
                                      const GValue *value, GParamSpec *pspec)
 
548
{
 
549
  SjMetadataMusicbrainzPrivate *priv = SJ_METADATA_MUSICBRAINZ (object)->priv;
 
550
  g_assert (priv);
 
551
 
 
552
  switch (property_id) {
 
553
  case PROP_DEVICE:
 
554
    if (priv->cdrom)
 
555
      g_free (priv->cdrom);
 
556
    priv->cdrom = g_value_dup_string (value);
 
557
    if (priv->cdrom)
 
558
      mb_SetDevice (priv->mb, priv->cdrom);
 
559
    break;
 
560
  case PROP_PROXY_HOST:
 
561
    if (priv->http_proxy) {
 
562
      g_free (priv->http_proxy);
 
563
    }
 
564
    priv->http_proxy = g_value_dup_string (value);
 
565
    /* TODO: check this unsets the proxy if NULL, or should we pass "" ? */
 
566
    mb_SetProxy (priv->mb, priv->http_proxy, priv->http_proxy_port);
 
567
    break;
 
568
  case PROP_PROXY_PORT:
 
569
    priv->http_proxy_port = g_value_get_int (value);
 
570
    mb_SetProxy (priv->mb, priv->http_proxy, priv->http_proxy_port);
 
571
    break;
 
572
  default:
 
573
    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
574
  }
 
575
}
 
576
 
 
577
static void
 
578
sj_metadata_musicbrainz_finalize (GObject *object)
714
579
{
715
580
  SjMetadataMusicbrainzPrivate *priv;
716
 
  char url[1025];
717
 
 
718
 
  g_return_val_if_fail (metadata != NULL, NULL);
719
 
 
720
 
  priv = SJ_METADATA_MUSICBRAINZ (metadata)->priv;
721
 
 
722
 
  if (mb_GetWebSubmitURL(priv->mb, url, 1024)) {
723
 
    return g_strdup(url);
724
 
  } else {
725
 
    return NULL;
726
 
  }
 
581
  
 
582
  priv = SJ_METADATA_MUSICBRAINZ (object)->priv;
 
583
 
 
584
  g_free (priv->http_proxy);
 
585
  g_free (priv->cdrom);
 
586
  mb_Delete (priv->mb);
 
587
 
 
588
  G_OBJECT_CLASS (sj_metadata_musicbrainz_parent_class)->finalize (object);
 
589
}
 
590
 
 
591
static void
 
592
sj_metadata_musicbrainz_class_init (SjMetadataMusicbrainzClass *class)
 
593
{
 
594
  GObjectClass *object_class = (GObjectClass*)class;
 
595
 
 
596
  g_type_class_add_private (class, sizeof (SjMetadataMusicbrainzPrivate));
 
597
 
 
598
  object_class->get_property = sj_metadata_musicbrainz_get_property;
 
599
  object_class->set_property = sj_metadata_musicbrainz_set_property;
 
600
  object_class->finalize = sj_metadata_musicbrainz_finalize;
 
601
 
 
602
  g_object_class_override_property (object_class, PROP_DEVICE, "device");
 
603
  g_object_class_override_property (object_class, PROP_PROXY_HOST, "proxy-host");
 
604
  g_object_class_override_property (object_class, PROP_PROXY_PORT, "proxy-port");
 
605
}
 
606
 
 
607
 
 
608
/*
 
609
 * Public methods.
 
610
 */
 
611
 
 
612
GObject *
 
613
sj_metadata_musicbrainz_new (void)
 
614
{
 
615
  return g_object_new (SJ_TYPE_METADATA_MUSICBRAINZ, NULL);
727
616
}