~ubuntu-branches/ubuntu/utopic/rhythmbox/utopic-proposed

« back to all changes in this revision

Viewing changes to metadata/monkey-media/stream-info-impl/flac-stream-info-impl.c

Tags: upstream-0.9.2
ImportĀ upstreamĀ versionĀ 0.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  monkey-sound
2
 
 *
3
 
 *  arch-tag: Implementation of FLAC metadata loading
4
 
 *
5
 
 *  Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
6
 
 *                     Marco Pesenti Gritti <marco@it.gnome.org>
7
 
 *                     Bastien Nocera <hadess@hadess.net>
8
 
 *                     Seth Nickell <snickell@stanford.edu>
9
 
 *
10
 
 *  This program is free software; you can redistribute it and/or modify
11
 
 *  it under the terms of the GNU General Public License as published by
12
 
 *  the Free Software Foundation; either version 2 of the License, or
13
 
 *  (at your option) any later version.
14
 
 *
15
 
 *  This program is distributed in the hope that it will be useful,
16
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 *  GNU General Public License for more details.
19
 
 *
20
 
 *  You should have received a copy of the GNU General Public License
21
 
 *  along with this program; if not, write to the Free Software
22
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
 
 *
24
 
 */
25
 
 
26
 
#include <libgnomevfs/gnome-vfs.h>
27
 
#include <libgnomevfs/gnome-vfs-mime-utils.h>
28
 
#include <libgnomevfs/gnome-vfs-utils.h>
29
 
#include <string.h>
30
 
#include <stdlib.h>
31
 
 
32
 
#include <id3tag.h>
33
 
 
34
 
#include "id3-vfs/id3-vfs.h"
35
 
 
36
 
#include <FLAC/metadata.h>
37
 
#include <FLAC/stream_decoder.h>
38
 
 
39
 
#include "monkey-media-stream-info.h"
40
 
#include "monkey-media-private.h"
41
 
 
42
 
#include "flac-stream-info-impl.h"
43
 
 
44
 
static void FLAC_stream_info_impl_class_init (FLACStreamInfoImplClass *klass);
45
 
static void FLAC_stream_info_impl_init (FLACStreamInfoImpl *ma);
46
 
static void FLAC_stream_info_impl_finalize (GObject *object);
47
 
static void FLAC_stream_info_impl_open_stream (MonkeyMediaStreamInfo *info);
48
 
static gboolean FLAC_stream_info_impl_get_value (MonkeyMediaStreamInfo *info,
49
 
                                                MonkeyMediaStreamInfoField field,
50
 
                                                int index,
51
 
                                                GValue *value);
52
 
static gboolean FLAC_stream_info_impl_set_value (MonkeyMediaStreamInfo *info,
53
 
                                                MonkeyMediaStreamInfoField field,
54
 
                                                int index,
55
 
                                                const GValue *value);
56
 
static char *FLAC_stream_info_impl_id3_tag_get_utf8 (struct id3_tag *tag,
57
 
                                                    const char *field_name);
58
 
static char* FLAC_stream_info_impl_vc_tag_get_utf8 (MonkeyMediaStreamInfo *info,
59
 
                                                   const char *field_name);
60
 
static int FLAC_stream_info_impl_get_n_values (MonkeyMediaStreamInfo *info,
61
 
                                              MonkeyMediaStreamInfoField field);
62
 
 
63
 
/* FLAC stream decoder callbacks */
64
 
 
65
 
static FLAC__StreamDecoderReadStatus
66
 
FLAC_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
67
 
 
68
 
static FLAC__StreamDecoderWriteStatus
69
 
FLAC_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame,
70
 
                     const FLAC__int32 *const buffer[], void *client_data);
71
 
 
72
 
static void
73
 
FLAC_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
74
 
 
75
 
static void
76
 
FLAC_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
77
 
 
78
 
struct FLACStreamInfoImplPrivate
79
 
{
80
 
        FLAC__StreamMetadata *streaminfo;
81
 
        GnomeVFSFileSize file_size;
82
 
 
83
 
        /* ID3 tag information, if present */
84
 
        struct id3_tag *tag;
85
 
        struct id3_vfs_file *file;
86
 
 
87
 
        /* Vorbis comments, if present */
88
 
        GHashTable *vorbis_comments;
89
 
};
90
 
 
91
 
struct FLACDecoderCallbackContext {
92
 
        FLACStreamInfoImpl *stream_info_impl;
93
 
        GnomeVFSHandle *file;
94
 
}; 
95
 
 
96
 
 
97
 
static GObjectClass *parent_class = NULL;
98
 
 
99
 
GType
100
 
FLAC_stream_info_impl_get_type (void)
101
 
{
102
 
        static GType FLAC_stream_info_impl_type = 0;
103
 
 
104
 
        if (FLAC_stream_info_impl_type == 0)
105
 
        {
106
 
                static const GTypeInfo our_info =
107
 
                {
108
 
                        sizeof (FLACStreamInfoImplClass),
109
 
                        NULL,
110
 
                        NULL,
111
 
                        (GClassInitFunc) FLAC_stream_info_impl_class_init,
112
 
                        NULL,
113
 
                        NULL,
114
 
                        sizeof (FLACStreamInfoImpl),
115
 
                        0,
116
 
                        (GInstanceInitFunc) FLAC_stream_info_impl_init
117
 
                };
118
 
 
119
 
                FLAC_stream_info_impl_type = g_type_register_static (MONKEY_MEDIA_TYPE_STREAM_INFO,
120
 
                                                                       "FLACStreamInfoImpl",
121
 
                                                                       &our_info, 0);
122
 
        }
123
 
 
124
 
        return FLAC_stream_info_impl_type;
125
 
}
126
 
 
127
 
static void
128
 
FLAC_stream_info_impl_class_init (FLACStreamInfoImplClass *klass)
129
 
{
130
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
131
 
        MonkeyMediaStreamInfoClass *info_class = MONKEY_MEDIA_STREAM_INFO_CLASS (klass);
132
 
 
133
 
        parent_class = g_type_class_peek_parent (klass);
134
 
 
135
 
        object_class->finalize = FLAC_stream_info_impl_finalize;
136
 
 
137
 
        info_class->open_stream  = FLAC_stream_info_impl_open_stream;
138
 
        info_class->get_n_values = FLAC_stream_info_impl_get_n_values;
139
 
        info_class->get_value    = FLAC_stream_info_impl_get_value;
140
 
        info_class->set_value    = FLAC_stream_info_impl_set_value;
141
 
}
142
 
 
143
 
static void
144
 
FLAC_stream_info_impl_init (FLACStreamInfoImpl *impl)
145
 
{
146
 
        impl->priv = g_new0 (FLACStreamInfoImplPrivate, 1);
147
 
}
148
 
 
149
 
static void
150
 
FLAC_stream_info_impl_finalize (GObject *object)
151
 
{
152
 
        FLACStreamInfoImpl *impl;
153
 
 
154
 
        g_return_if_fail (object != NULL);
155
 
        g_return_if_fail (IS_FLAC_STREAM_INFO_IMPL (object));
156
 
 
157
 
        impl = FLAC_STREAM_INFO_IMPL (object);
158
 
 
159
 
        g_return_if_fail (impl->priv != NULL);
160
 
 
161
 
        if (impl->priv->file != NULL)
162
 
                id3_vfs_close (impl->priv->file);
163
 
 
164
 
        if (impl->priv->streaminfo)
165
 
                FLAC__metadata_object_delete (impl->priv->streaminfo);
166
 
 
167
 
        if (impl->priv->vorbis_comments)
168
 
        {
169
 
                /* because we constructed the table with g_hash_table_new_full,
170
 
                 * all of the keys and values will be freed on destroy */
171
 
                g_hash_table_destroy (impl->priv->vorbis_comments);
172
 
        }
173
 
 
174
 
        g_free (impl->priv);
175
 
 
176
 
        G_OBJECT_CLASS (parent_class)->finalize (object);
177
 
}
178
 
 
179
 
static void
180
 
FLAC_stream_info_impl_open_stream (MonkeyMediaStreamInfo *info)
181
 
{
182
 
        FLACStreamInfoImpl *impl = FLAC_STREAM_INFO_IMPL (info);
183
 
        char *uri;
184
 
        GError *error;
185
 
        GnomeVFSHandle *file;
186
 
 
187
 
        g_object_get (G_OBJECT (info),
188
 
                      "error", &error,
189
 
                      "location", &uri,
190
 
                      NULL);
191
 
 
192
 
        impl->priv->file = id3_vfs_open (uri, ID3_FILE_MODE_READONLY);
193
 
        if (impl->priv->file == NULL)
194
 
        {
195
 
                error = g_error_new (MONKEY_MEDIA_STREAM_INFO_ERROR,
196
 
                                     MONKEY_MEDIA_STREAM_INFO_ERROR_OPEN_FAILED,
197
 
                                     _("Failed to open file for reading"));
198
 
                g_object_set (G_OBJECT (info), "error", error, NULL);
199
 
                g_free (uri);
200
 
                return;
201
 
        }
202
 
 
203
 
        impl->priv->tag = id3_vfs_tag (impl->priv->file);
204
 
 
205
 
        /* read FLAC STREAMINFO block and any VORBISCOMMENT blocks */
206
 
 
207
 
        if (gnome_vfs_open (&file, uri, GNOME_VFS_OPEN_READ) == GNOME_VFS_OK)
208
 
        {
209
 
                FLAC__StreamDecoder *flac_decoder;
210
 
                struct FLACDecoderCallbackContext flac_decoder_callback_context = { impl, file };
211
 
                GnomeVFSFileInfo *fi;
212
 
 
213
 
                /* get file size, useful for several calculations later on */
214
 
 
215
 
                fi = gnome_vfs_file_info_new ();
216
 
 
217
 
                if (gnome_vfs_get_file_info_from_handle (file, fi, GNOME_VFS_FILE_INFO_FOLLOW_LINKS) == GNOME_VFS_OK)
218
 
                        impl->priv->file_size = fi->size;
219
 
                else
220
 
                        impl->priv->file_size = 1;  /* not zero to prevent divide-by-zero errors */
221
 
 
222
 
                gnome_vfs_file_info_unref (fi);
223
 
 
224
 
                /* Set up and run FLAC stream decoder to decode metadata */
225
 
 
226
 
                impl->priv->vorbis_comments = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
227
 
                impl->priv->streaminfo = NULL;
228
 
                flac_decoder = FLAC__stream_decoder_new ();
229
 
 
230
 
                FLAC__stream_decoder_set_read_callback (flac_decoder, FLAC_read_callback);
231
 
                FLAC__stream_decoder_set_write_callback (flac_decoder, FLAC_write_callback);
232
 
                FLAC__stream_decoder_set_metadata_callback (flac_decoder, FLAC_metadata_callback);
233
 
                FLAC__stream_decoder_set_error_callback (flac_decoder, FLAC_error_callback);
234
 
                FLAC__stream_decoder_set_client_data (flac_decoder, &flac_decoder_callback_context);
235
 
 
236
 
                /* by default, only the STREAMINFO block is parsed and passed to
237
 
                 * the metadata callback.  Here we instruct the decoder to also
238
 
                 * pass us the VORBISCOMMENT block if there is one. */
239
 
                FLAC__stream_decoder_set_metadata_respond (flac_decoder, FLAC__METADATA_TYPE_VORBIS_COMMENT);
240
 
 
241
 
                FLAC__stream_decoder_init (flac_decoder);
242
 
 
243
 
                /* this runs the decoding process, calling the callbacks as appropriate */
244
 
                if ((FLAC__stream_decoder_process_until_end_of_metadata (flac_decoder) == 0)
245
 
                    || (impl->priv->streaminfo == NULL))
246
 
                {
247
 
                        error = g_error_new (MONKEY_MEDIA_STREAM_INFO_ERROR,
248
 
                                             MONKEY_MEDIA_STREAM_INFO_ERROR_OPEN_FAILED,
249
 
                                             _("Error decoding FLAC file"));
250
 
                        g_object_set (G_OBJECT (info), "error", error, NULL);
251
 
 
252
 
                        FLAC__stream_decoder_delete (flac_decoder);
253
 
                        gnome_vfs_close (file);
254
 
                        return;
255
 
                }
256
 
 
257
 
                FLAC__stream_decoder_finish (flac_decoder);
258
 
                FLAC__stream_decoder_delete (flac_decoder);
259
 
 
260
 
                gnome_vfs_close (file);
261
 
        }
262
 
        else
263
 
        {
264
 
                error = g_error_new (MONKEY_MEDIA_STREAM_INFO_ERROR,
265
 
                                     MONKEY_MEDIA_STREAM_INFO_ERROR_OPEN_FAILED,
266
 
                                     _("Failed to open file for reading"));
267
 
                g_object_set (G_OBJECT (info), "error", error, NULL);
268
 
                g_free (uri);
269
 
                return;
270
 
        }
271
 
        g_free (uri);
272
 
}
273
 
 
274
 
/*
275
 
 * FLAC Stream Decoder callbacks
276
 
 */
277
 
 
278
 
static FLAC__StreamDecoderReadStatus
279
 
FLAC_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
280
 
{
281
 
        struct FLACDecoderCallbackContext *context = (struct FLACDecoderCallbackContext*) client_data;
282
 
        GnomeVFSFileSize read;
283
 
        GnomeVFSResult result;
284
 
 
285
 
        result = gnome_vfs_read (context->file, buffer, *bytes, &read);
286
 
 
287
 
        if (result == GNOME_VFS_OK)
288
 
        {
289
 
                *bytes = read;
290
 
                return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
291
 
        }
292
 
        else if (result == GNOME_VFS_ERROR_EOF)
293
 
        {
294
 
                return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
295
 
        }
296
 
        else
297
 
        {
298
 
                return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
299
 
        }
300
 
}
301
 
 
302
 
static FLAC__StreamDecoderWriteStatus
303
 
FLAC_write_callback (const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, 
304
 
                     const FLAC__int32 *const buffer[], void *client_data)
305
 
{
306
 
        /* This callback should never be called, because we request that
307
 
         * FLAC only decodes metadata, never actual sound data. */
308
 
        return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
309
 
}
310
 
 
311
 
static void
312
 
FLAC_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
313
 
{
314
 
        struct FLACDecoderCallbackContext *context = (struct FLACDecoderCallbackContext*) client_data;
315
 
 
316
 
        if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
317
 
        {
318
 
                context->stream_info_impl->priv->streaminfo = FLAC__metadata_object_clone (metadata);
319
 
        }
320
 
        else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
321
 
        {
322
 
                GHashTable *vorbis_comments = context->stream_info_impl->priv->vorbis_comments;
323
 
                const FLAC__StreamMetadata_VorbisComment *vc_block = &metadata->data.vorbis_comment;
324
 
                int c;
325
 
 
326
 
                for (c = 0; c < vc_block->num_comments; c++)
327
 
                {
328
 
                        FLAC__StreamMetadata_VorbisComment_Entry entry = vc_block->comments[c];
329
 
                        char *null_terminated_comment = malloc (entry.length + 1);
330
 
                        gchar* upcase_fieldname;
331
 
                        gchar** parts;
332
 
 
333
 
                        memcpy (null_terminated_comment, entry.entry, entry.length);
334
 
                        null_terminated_comment[entry.length] = '\0';
335
 
                        parts = g_strsplit (null_terminated_comment, "=", 2);
336
 
 
337
 
                        if (parts[0] == NULL || parts[1] == NULL)
338
 
                                goto free_continue;
339
 
 
340
 
                        /* Make sure the fieldname is uppercase */
341
 
                        upcase_fieldname = g_utf8_strup (parts[0], -1);
342
 
                        if (upcase_fieldname == NULL)
343
 
                                goto free_continue;
344
 
 
345
 
                        g_free (parts[0]);
346
 
                        parts[0] = upcase_fieldname;
347
 
 
348
 
                        /* if an earlier comment had this same key name, it will be replaced.
349
 
                         * a possible improvement is to make the values of the hash table
350
 
                         * lists of strings instead of single strings. */
351
 
                        g_hash_table_insert (vorbis_comments, g_strdup (parts[0]), g_strdup (parts[1]));
352
 
 
353
 
                free_continue:
354
 
                        g_strfreev (parts);
355
 
                        free (null_terminated_comment);
356
 
                }
357
 
        }
358
 
}
359
 
 
360
 
static void
361
 
FLAC_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
362
 
{
363
 
}
364
 
 
365
 
/*
366
 
 * End FLAC Stream Decoder callbacks
367
 
 */
368
 
 
369
 
static int
370
 
FLAC_stream_info_impl_get_n_values (MonkeyMediaStreamInfo *info,
371
 
                                   MonkeyMediaStreamInfoField field)
372
 
{
373
 
        FLACStreamInfoImpl *impl;
374
 
        FLAC__StreamMetadata_StreamInfo stream_info;
375
 
        char *tmp;
376
 
        gboolean ret = FALSE;
377
 
        
378
 
        g_return_val_if_fail (IS_FLAC_STREAM_INFO_IMPL (info), 0);
379
 
 
380
 
        impl = FLAC_STREAM_INFO_IMPL (info);
381
 
 
382
 
        stream_info = impl->priv->streaminfo->data.stream_info;
383
 
 
384
 
        switch (field)
385
 
        {
386
 
        /* tags */
387
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_TITLE:
388
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "TITLE");
389
 
                if (tmp == NULL)
390
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TITLE);
391
 
                ret = (tmp != NULL);
392
 
                g_free (tmp);
393
 
                return ret;
394
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ARTIST:
395
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ARTIST");
396
 
                if (tmp == NULL)
397
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ARTIST);
398
 
                ret = (tmp != NULL);
399
 
                g_free (tmp);
400
 
                return ret;
401
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ALBUM:
402
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ALBUM");
403
 
                if (tmp == NULL)
404
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ALBUM);
405
 
                ret = (tmp != NULL);
406
 
                g_free (tmp);
407
 
                return ret;
408
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_DATE:
409
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "DATE");
410
 
                if (tmp == NULL)
411
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_YEAR);
412
 
                ret = (tmp != NULL);
413
 
                g_free (tmp);
414
 
                return ret;
415
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_GENRE:
416
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "GENRE");
417
 
                if (tmp == NULL)
418
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_GENRE);
419
 
                ret = (tmp != NULL);
420
 
                g_free (tmp);
421
 
                return ret;
422
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_COMMENT:
423
 
                tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_COMMENT);
424
 
                ret = (tmp != NULL);
425
 
                g_free (tmp);
426
 
                return ret;
427
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_TRACK_NUMBER:
428
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "TRACKNUMBER");
429
 
                if (tmp != NULL)
430
 
                {
431
 
                        g_free (tmp);
432
 
                        return TRUE;
433
 
                }
434
 
                else
435
 
                {
436
 
                        char **parts;
437
 
                        
438
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
439
 
                        if (tmp == NULL)
440
 
                        {
441
 
                                g_free (tmp);
442
 
                                return 0;
443
 
                        }
444
 
                        
445
 
                        parts = g_strsplit (tmp, "/", -1);
446
 
 
447
 
                        if (parts[0] != NULL)
448
 
                                ret = TRUE;
449
 
 
450
 
                        g_strfreev (parts);
451
 
                        g_free (tmp);
452
 
 
453
 
                        return ret;
454
 
                }
455
 
                break;
456
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_MAX_TRACK_NUMBER:
457
 
                {
458
 
                        char **parts;
459
 
                        
460
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
461
 
                        if (tmp == NULL)
462
 
                        {
463
 
                                g_free (tmp);
464
 
                                return 0;
465
 
                        }
466
 
 
467
 
                        parts = g_strsplit (tmp, "/", -1);
468
 
 
469
 
                        if (parts[0] != NULL && parts[1] != NULL)
470
 
                                ret = TRUE;
471
 
 
472
 
                        g_strfreev (parts);
473
 
                        g_free (tmp);
474
 
 
475
 
                        return ret;
476
 
                }
477
 
                break;
478
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_LOCATION:
479
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "LOCATION");
480
 
                ret = (tmp != NULL);
481
 
                g_free (tmp);
482
 
                return ret;
483
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_DESCRIPTION:
484
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "DESCRIPTION");
485
 
                ret = (tmp != NULL);
486
 
                g_free (tmp);
487
 
                return ret;
488
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_VERSION:
489
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "VERSION");
490
 
                ret = (tmp != NULL);
491
 
                g_free (tmp);
492
 
                return ret;
493
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ISRC:
494
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ISRC");
495
 
                ret = (tmp != NULL);
496
 
                g_free (tmp);
497
 
                return ret;
498
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ORGANIZATION:
499
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ORGANIZATION");
500
 
                ret = (tmp != NULL);
501
 
                g_free (tmp);
502
 
                return ret;
503
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_COPYRIGHT:
504
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "COPYRIGHT");
505
 
                ret = (tmp != NULL);
506
 
                g_free (tmp);
507
 
                return ret;
508
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_CONTACT:
509
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "CONTACT");
510
 
                ret = (tmp != NULL);
511
 
                g_free (tmp);
512
 
                return ret;
513
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_LICENSE:
514
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "LICENSE");
515
 
                ret = (tmp != NULL);
516
 
                g_free (tmp);
517
 
                return ret;
518
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_PERFORMER:
519
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "PERFORMER");
520
 
                ret = (tmp != NULL);
521
 
                g_free (tmp);
522
 
                return ret;
523
 
 
524
 
        /* generic bits */
525
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_FILE_SIZE:
526
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_DURATION:
527
 
                return 1;
528
 
 
529
 
        /* audio bits */
530
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_AUDIO:
531
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CODEC_INFO:
532
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_BIT_RATE:
533
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_AVERAGE_BIT_RATE:
534
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VARIABLE_BIT_RATE:
535
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SAMPLE_RATE:
536
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CHANNELS:
537
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRM_ID:
538
 
                return 1;
539
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SERIAL_NUMBER:
540
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VENDOR:
541
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_GAIN:
542
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_GAIN:
543
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_PEAK:
544
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_PEAK:
545
 
                return 0;
546
 
 
547
 
        /* video bits */
548
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_VIDEO:
549
 
                return 1;
550
 
 
551
 
        /* default */
552
 
        default:
553
 
                return 0;
554
 
        }
555
 
}
556
 
 
557
 
static gboolean
558
 
FLAC_stream_info_impl_get_value (MonkeyMediaStreamInfo *info,
559
 
                                MonkeyMediaStreamInfoField field,
560
 
                                int index,
561
 
                                GValue *value)
562
 
{
563
 
        FLACStreamInfoImpl *impl;
564
 
        FLAC__StreamMetadata_StreamInfo *stream_info;
565
 
        char *tmp;
566
 
        
567
 
        g_return_val_if_fail (IS_FLAC_STREAM_INFO_IMPL (info), FALSE);
568
 
        g_return_val_if_fail (value != NULL, FALSE);
569
 
 
570
 
        impl = FLAC_STREAM_INFO_IMPL (info);
571
 
 
572
 
        stream_info = &impl->priv->streaminfo->data.stream_info;
573
 
 
574
 
        if (FLAC_stream_info_impl_get_n_values (info, field) <= 0)
575
 
                return FALSE;
576
 
 
577
 
        switch (field)
578
 
        {
579
 
        /* tags */
580
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_TITLE:
581
 
                g_value_init (value, G_TYPE_STRING);
582
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "TITLE");
583
 
                if (tmp == NULL)
584
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TITLE);
585
 
                g_value_set_string (value, tmp);
586
 
                g_free (tmp);
587
 
                break;
588
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ARTIST:
589
 
                g_value_init (value, G_TYPE_STRING);
590
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ARTIST");
591
 
                if (tmp == NULL)
592
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ARTIST);
593
 
                g_value_set_string (value, tmp);
594
 
                g_free (tmp);
595
 
                break;
596
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ALBUM:
597
 
                g_value_init (value, G_TYPE_STRING);
598
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ALBUM");
599
 
                if (tmp == NULL)
600
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ALBUM);
601
 
                g_value_set_string (value, tmp);
602
 
                g_free (tmp);
603
 
                break;
604
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_DATE:
605
 
                g_value_init (value, G_TYPE_STRING);
606
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "DATE");
607
 
                if (tmp == NULL)
608
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_YEAR);
609
 
                g_value_set_string (value, tmp);
610
 
                g_free (tmp);
611
 
                break;
612
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_GENRE:
613
 
                g_value_init (value, G_TYPE_STRING);
614
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "GENRE");
615
 
                if (tmp == NULL)
616
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_GENRE);
617
 
                g_value_set_string (value, tmp);
618
 
                g_free (tmp);
619
 
                break;
620
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_COMMENT:
621
 
                g_value_init (value, G_TYPE_STRING);
622
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "COMMENT");
623
 
                if (tmp == NULL)
624
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_COMMENT);
625
 
                g_value_set_string (value, tmp);
626
 
                g_free (tmp);
627
 
                break;
628
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_TRACK_NUMBER:
629
 
                g_value_init (value, G_TYPE_INT);
630
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "TRACKNUMBER");
631
 
                if (tmp != NULL)
632
 
                {
633
 
                        g_value_set_int (value, atoi(tmp));
634
 
                        g_free (tmp);
635
 
                }
636
 
                else
637
 
                {
638
 
                        char **parts;
639
 
                        int num = -1;
640
 
                        
641
 
 
642
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
643
 
                        if (tmp == NULL)
644
 
                        {
645
 
                                g_free (tmp);
646
 
                                g_value_set_int (value, -1);
647
 
                                break;
648
 
                        }
649
 
 
650
 
                        parts = g_strsplit (tmp, "/", -1);
651
 
 
652
 
                        if (parts[0] != NULL)
653
 
                                num = atoi (parts[0]);
654
 
 
655
 
                        g_value_set_int (value, num);
656
 
 
657
 
                        g_strfreev (parts);
658
 
                        g_free (tmp);
659
 
                }
660
 
                break;
661
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_MAX_TRACK_NUMBER:
662
 
                {
663
 
                        char **parts;
664
 
                        int num = -1;
665
 
                        
666
 
                        g_value_init (value, G_TYPE_INT);
667
 
 
668
 
                        tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
669
 
                        if (tmp == NULL)
670
 
                        {
671
 
                                g_free (tmp);
672
 
                                g_value_set_int (value, -1);
673
 
                                break;
674
 
                        }
675
 
 
676
 
                        parts = g_strsplit (tmp, "/", -1);
677
 
 
678
 
                        if (parts[0] != NULL && parts[1] != NULL)
679
 
                                num = atoi (parts[1]);
680
 
 
681
 
                        g_value_set_int (value, num);
682
 
 
683
 
                        g_strfreev (parts);
684
 
                        g_free (tmp);
685
 
                }
686
 
                break;
687
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_LOCATION:
688
 
                g_value_init (value, G_TYPE_STRING);
689
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "LOCATION");
690
 
                g_value_set_string (value, tmp);
691
 
                g_free (tmp);
692
 
                break;
693
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_DESCRIPTION:
694
 
                g_value_init (value, G_TYPE_STRING);
695
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "DESCRIPTION");
696
 
                g_value_set_string (value, tmp);
697
 
                g_free (tmp);
698
 
                break;
699
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_VERSION:
700
 
                g_value_init (value, G_TYPE_STRING);
701
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "VERSION");
702
 
                g_value_set_string (value, tmp);
703
 
                g_free (tmp);
704
 
                break;
705
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ISRC:
706
 
                g_value_init (value, G_TYPE_STRING);
707
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ISRC");
708
 
                g_value_set_string (value, tmp);
709
 
                g_free (tmp);
710
 
                break;
711
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_ORGANIZATION:
712
 
                g_value_init (value, G_TYPE_STRING);
713
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ORGANIZATION");
714
 
                g_value_set_string (value, tmp);
715
 
                g_free (tmp);
716
 
                break;
717
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_COPYRIGHT:
718
 
                g_value_init (value, G_TYPE_STRING);
719
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "COPYRIGHT");
720
 
                g_value_set_string (value, tmp);
721
 
                g_free (tmp);
722
 
                break;
723
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_CONTACT:
724
 
                g_value_init (value, G_TYPE_STRING);
725
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "CONTACT");
726
 
                g_value_set_string (value, tmp);
727
 
                g_free (tmp);
728
 
                break;
729
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_LICENSE:
730
 
                g_value_init (value, G_TYPE_STRING);
731
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "LICENSE");
732
 
                g_value_set_string (value, tmp);
733
 
                g_free (tmp);
734
 
                break;
735
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_PERFORMER:
736
 
                g_value_init (value, G_TYPE_STRING);
737
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "PERFORMER");
738
 
                g_value_set_string (value, tmp);
739
 
                g_free (tmp);
740
 
                break;
741
 
 
742
 
        /* generic bits */
743
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_FILE_SIZE:
744
 
                g_value_init (value, G_TYPE_LONG);
745
 
                g_value_set_long (value, impl->priv->file_size);
746
 
                break;
747
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_DURATION:
748
 
                g_value_init (value, G_TYPE_LONG);
749
 
                g_value_set_long (value, stream_info->total_samples / stream_info->sample_rate);
750
 
                break;
751
 
 
752
 
        /* audio bits */
753
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_AUDIO:
754
 
                g_value_init (value, G_TYPE_BOOLEAN);
755
 
                g_value_set_boolean (value, TRUE);
756
 
                break;
757
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CODEC_INFO:
758
 
                {
759
 
                        tmp = g_strdup_printf (_("FLAC"));
760
 
                        g_value_init (value, G_TYPE_STRING);
761
 
                        g_value_set_string (value, tmp);
762
 
                        g_free (tmp);
763
 
                }
764
 
                break;
765
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_BIT_RATE:
766
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_AVERAGE_BIT_RATE:
767
 
                g_value_init (value, G_TYPE_INT);
768
 
                g_value_set_int (value, impl->priv->file_size * 8 / 1024.0f /  /* kilobits */
769
 
                                        ((float)stream_info->total_samples / stream_info->sample_rate)); /* seconds */
770
 
                break;
771
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRM_ID:
772
 
                g_value_init (value, G_TYPE_STRING);
773
 
                tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "MUSICBRAINZ_TRMID");
774
 
                g_value_set_string (value, tmp);
775
 
                g_free (tmp);
776
 
                break;
777
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VARIABLE_BIT_RATE:
778
 
                g_value_init (value, G_TYPE_BOOLEAN);
779
 
                /* FLAC is VBR by nature */
780
 
                g_value_set_boolean (value, true);
781
 
                break;
782
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SAMPLE_RATE:
783
 
                g_value_init (value, G_TYPE_LONG);
784
 
                g_value_set_long (value, stream_info->sample_rate);
785
 
                break;
786
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CHANNELS:
787
 
                g_value_init (value, G_TYPE_INT);
788
 
                g_value_set_int (value, stream_info->channels);
789
 
                break;
790
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_SERIAL_NUMBER:
791
 
                g_value_init (value, G_TYPE_LONG);
792
 
                g_value_set_long (value, 0);
793
 
                break;
794
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VENDOR:
795
 
                g_value_init (value, G_TYPE_STRING);
796
 
                g_value_set_string (value, "");
797
 
                break;
798
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_GAIN:
799
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_GAIN:
800
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_ALBUM_PEAK:
801
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_TRACK_PEAK:
802
 
                /* FIXME i believe flac does support this */
803
 
                /* [JH] I don't think it does */
804
 
                g_value_init (value, G_TYPE_DOUBLE);
805
 
                g_value_set_double (value, 0.0);
806
 
                break;
807
 
 
808
 
        /* video bits */
809
 
        case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_VIDEO:
810
 
                g_value_init (value, G_TYPE_BOOLEAN);
811
 
                g_value_set_boolean (value, FALSE);
812
 
                break;
813
 
 
814
 
        /* default */
815
 
        default:
816
 
                g_warning ("Invalid field!");
817
 
                g_value_init (value, G_TYPE_NONE);
818
 
                break;
819
 
        }
820
 
 
821
 
        return TRUE;
822
 
}
823
 
 
824
 
static gboolean
825
 
FLAC_stream_info_impl_set_value (MonkeyMediaStreamInfo *info,
826
 
                                MonkeyMediaStreamInfoField field,
827
 
                                int index,
828
 
                                const GValue *value)
829
 
{
830
 
        /* FIXME */
831
 
        return FALSE;
832
 
}
833
 
 
834
 
static char *
835
 
FLAC_stream_info_impl_id3_tag_get_utf8 (struct id3_tag *tag, const char *field_name)
836
 
{
837
 
        unsigned int nstrings, j;
838
 
        const struct id3_frame *frame;
839
 
        const union id3_field *field;
840
 
        const id3_ucs4_t *ucs4;
841
 
        id3_utf8_t *utf8 = NULL;
842
 
 
843
 
        frame = id3_tag_findframe (tag, field_name, 0);
844
 
        if (frame == 0)
845
 
                return NULL;
846
 
 
847
 
        field = &frame->fields[1];
848
 
        nstrings = id3_field_getnstrings (field);
849
 
        for (j = 0; j < nstrings; j++)
850
 
        {
851
 
                ucs4 = id3_field_getstrings (field, j);
852
 
 
853
 
                if (strcmp (field_name, ID3_FRAME_GENRE) == 0)
854
 
                        ucs4 = id3_genre_name (ucs4);
855
 
 
856
 
                utf8 = id3_ucs4_utf8duplicate (ucs4);
857
 
        }
858
 
 
859
 
        return utf8;
860
 
}
861
 
 
862
 
static char*
863
 
FLAC_stream_info_impl_vc_tag_get_utf8 (MonkeyMediaStreamInfo *info, const char *field_name)
864
 
{
865
 
        FLACStreamInfoImpl *impl;
866
 
        char *utf8;
867
 
 
868
 
        g_return_val_if_fail (IS_FLAC_STREAM_INFO_IMPL (info), NULL);
869
 
        g_return_val_if_fail (field_name != NULL, NULL);
870
 
 
871
 
        impl = FLAC_STREAM_INFO_IMPL (info);
872
 
 
873
 
        utf8 = g_hash_table_lookup (impl->priv->vorbis_comments, field_name);
874
 
        return g_strdup (utf8);
875
 
}
876