3
* arch-tag: Implementation of FLAC metadata loading
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>
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.
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.
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.
26
#include <libgnomevfs/gnome-vfs.h>
27
#include <libgnomevfs/gnome-vfs-mime-utils.h>
28
#include <libgnomevfs/gnome-vfs-utils.h>
34
#include "id3-vfs/id3-vfs.h"
36
#include <FLAC/metadata.h>
37
#include <FLAC/stream_decoder.h>
39
#include "monkey-media-stream-info.h"
40
#include "monkey-media-private.h"
42
#include "flac-stream-info-impl.h"
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,
52
static gboolean FLAC_stream_info_impl_set_value (MonkeyMediaStreamInfo *info,
53
MonkeyMediaStreamInfoField field,
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);
63
/* FLAC stream decoder callbacks */
65
static FLAC__StreamDecoderReadStatus
66
FLAC_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
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);
73
FLAC_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
76
FLAC_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
78
struct FLACStreamInfoImplPrivate
80
FLAC__StreamMetadata *streaminfo;
81
GnomeVFSFileSize file_size;
83
/* ID3 tag information, if present */
85
struct id3_vfs_file *file;
87
/* Vorbis comments, if present */
88
GHashTable *vorbis_comments;
91
struct FLACDecoderCallbackContext {
92
FLACStreamInfoImpl *stream_info_impl;
97
static GObjectClass *parent_class = NULL;
100
FLAC_stream_info_impl_get_type (void)
102
static GType FLAC_stream_info_impl_type = 0;
104
if (FLAC_stream_info_impl_type == 0)
106
static const GTypeInfo our_info =
108
sizeof (FLACStreamInfoImplClass),
111
(GClassInitFunc) FLAC_stream_info_impl_class_init,
114
sizeof (FLACStreamInfoImpl),
116
(GInstanceInitFunc) FLAC_stream_info_impl_init
119
FLAC_stream_info_impl_type = g_type_register_static (MONKEY_MEDIA_TYPE_STREAM_INFO,
120
"FLACStreamInfoImpl",
124
return FLAC_stream_info_impl_type;
128
FLAC_stream_info_impl_class_init (FLACStreamInfoImplClass *klass)
130
GObjectClass *object_class = G_OBJECT_CLASS (klass);
131
MonkeyMediaStreamInfoClass *info_class = MONKEY_MEDIA_STREAM_INFO_CLASS (klass);
133
parent_class = g_type_class_peek_parent (klass);
135
object_class->finalize = FLAC_stream_info_impl_finalize;
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;
144
FLAC_stream_info_impl_init (FLACStreamInfoImpl *impl)
146
impl->priv = g_new0 (FLACStreamInfoImplPrivate, 1);
150
FLAC_stream_info_impl_finalize (GObject *object)
152
FLACStreamInfoImpl *impl;
154
g_return_if_fail (object != NULL);
155
g_return_if_fail (IS_FLAC_STREAM_INFO_IMPL (object));
157
impl = FLAC_STREAM_INFO_IMPL (object);
159
g_return_if_fail (impl->priv != NULL);
161
if (impl->priv->file != NULL)
162
id3_vfs_close (impl->priv->file);
164
if (impl->priv->streaminfo)
165
FLAC__metadata_object_delete (impl->priv->streaminfo);
167
if (impl->priv->vorbis_comments)
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);
176
G_OBJECT_CLASS (parent_class)->finalize (object);
180
FLAC_stream_info_impl_open_stream (MonkeyMediaStreamInfo *info)
182
FLACStreamInfoImpl *impl = FLAC_STREAM_INFO_IMPL (info);
185
GnomeVFSHandle *file;
187
g_object_get (G_OBJECT (info),
192
impl->priv->file = id3_vfs_open (uri, ID3_FILE_MODE_READONLY);
193
if (impl->priv->file == NULL)
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);
203
impl->priv->tag = id3_vfs_tag (impl->priv->file);
205
/* read FLAC STREAMINFO block and any VORBISCOMMENT blocks */
207
if (gnome_vfs_open (&file, uri, GNOME_VFS_OPEN_READ) == GNOME_VFS_OK)
209
FLAC__StreamDecoder *flac_decoder;
210
struct FLACDecoderCallbackContext flac_decoder_callback_context = { impl, file };
211
GnomeVFSFileInfo *fi;
213
/* get file size, useful for several calculations later on */
215
fi = gnome_vfs_file_info_new ();
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;
220
impl->priv->file_size = 1; /* not zero to prevent divide-by-zero errors */
222
gnome_vfs_file_info_unref (fi);
224
/* Set up and run FLAC stream decoder to decode metadata */
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 ();
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);
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);
241
FLAC__stream_decoder_init (flac_decoder);
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))
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);
252
FLAC__stream_decoder_delete (flac_decoder);
253
gnome_vfs_close (file);
257
FLAC__stream_decoder_finish (flac_decoder);
258
FLAC__stream_decoder_delete (flac_decoder);
260
gnome_vfs_close (file);
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);
275
* FLAC Stream Decoder callbacks
278
static FLAC__StreamDecoderReadStatus
279
FLAC_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
281
struct FLACDecoderCallbackContext *context = (struct FLACDecoderCallbackContext*) client_data;
282
GnomeVFSFileSize read;
283
GnomeVFSResult result;
285
result = gnome_vfs_read (context->file, buffer, *bytes, &read);
287
if (result == GNOME_VFS_OK)
290
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
292
else if (result == GNOME_VFS_ERROR_EOF)
294
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
298
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
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)
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;
312
FLAC_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
314
struct FLACDecoderCallbackContext *context = (struct FLACDecoderCallbackContext*) client_data;
316
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
318
context->stream_info_impl->priv->streaminfo = FLAC__metadata_object_clone (metadata);
320
else if (metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT)
322
GHashTable *vorbis_comments = context->stream_info_impl->priv->vorbis_comments;
323
const FLAC__StreamMetadata_VorbisComment *vc_block = &metadata->data.vorbis_comment;
326
for (c = 0; c < vc_block->num_comments; c++)
328
FLAC__StreamMetadata_VorbisComment_Entry entry = vc_block->comments[c];
329
char *null_terminated_comment = malloc (entry.length + 1);
330
gchar* upcase_fieldname;
333
memcpy (null_terminated_comment, entry.entry, entry.length);
334
null_terminated_comment[entry.length] = '\0';
335
parts = g_strsplit (null_terminated_comment, "=", 2);
337
if (parts[0] == NULL || parts[1] == NULL)
340
/* Make sure the fieldname is uppercase */
341
upcase_fieldname = g_utf8_strup (parts[0], -1);
342
if (upcase_fieldname == NULL)
346
parts[0] = upcase_fieldname;
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]));
355
free (null_terminated_comment);
361
FLAC_error_callback (const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
366
* End FLAC Stream Decoder callbacks
370
FLAC_stream_info_impl_get_n_values (MonkeyMediaStreamInfo *info,
371
MonkeyMediaStreamInfoField field)
373
FLACStreamInfoImpl *impl;
374
FLAC__StreamMetadata_StreamInfo stream_info;
376
gboolean ret = FALSE;
378
g_return_val_if_fail (IS_FLAC_STREAM_INFO_IMPL (info), 0);
380
impl = FLAC_STREAM_INFO_IMPL (info);
382
stream_info = impl->priv->streaminfo->data.stream_info;
387
case MONKEY_MEDIA_STREAM_INFO_FIELD_TITLE:
388
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "TITLE");
390
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TITLE);
394
case MONKEY_MEDIA_STREAM_INFO_FIELD_ARTIST:
395
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ARTIST");
397
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ARTIST);
401
case MONKEY_MEDIA_STREAM_INFO_FIELD_ALBUM:
402
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ALBUM");
404
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ALBUM);
408
case MONKEY_MEDIA_STREAM_INFO_FIELD_DATE:
409
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "DATE");
411
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_YEAR);
415
case MONKEY_MEDIA_STREAM_INFO_FIELD_GENRE:
416
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "GENRE");
418
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_GENRE);
422
case MONKEY_MEDIA_STREAM_INFO_FIELD_COMMENT:
423
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_COMMENT);
427
case MONKEY_MEDIA_STREAM_INFO_FIELD_TRACK_NUMBER:
428
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "TRACKNUMBER");
438
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
445
parts = g_strsplit (tmp, "/", -1);
447
if (parts[0] != NULL)
456
case MONKEY_MEDIA_STREAM_INFO_FIELD_MAX_TRACK_NUMBER:
460
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
467
parts = g_strsplit (tmp, "/", -1);
469
if (parts[0] != NULL && parts[1] != NULL)
478
case MONKEY_MEDIA_STREAM_INFO_FIELD_LOCATION:
479
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "LOCATION");
483
case MONKEY_MEDIA_STREAM_INFO_FIELD_DESCRIPTION:
484
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "DESCRIPTION");
488
case MONKEY_MEDIA_STREAM_INFO_FIELD_VERSION:
489
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "VERSION");
493
case MONKEY_MEDIA_STREAM_INFO_FIELD_ISRC:
494
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ISRC");
498
case MONKEY_MEDIA_STREAM_INFO_FIELD_ORGANIZATION:
499
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "ORGANIZATION");
503
case MONKEY_MEDIA_STREAM_INFO_FIELD_COPYRIGHT:
504
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "COPYRIGHT");
508
case MONKEY_MEDIA_STREAM_INFO_FIELD_CONTACT:
509
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "CONTACT");
513
case MONKEY_MEDIA_STREAM_INFO_FIELD_LICENSE:
514
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "LICENSE");
518
case MONKEY_MEDIA_STREAM_INFO_FIELD_PERFORMER:
519
tmp = FLAC_stream_info_impl_vc_tag_get_utf8 (info, "PERFORMER");
525
case MONKEY_MEDIA_STREAM_INFO_FIELD_FILE_SIZE:
526
case MONKEY_MEDIA_STREAM_INFO_FIELD_DURATION:
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:
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:
548
case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_VIDEO:
558
FLAC_stream_info_impl_get_value (MonkeyMediaStreamInfo *info,
559
MonkeyMediaStreamInfoField field,
563
FLACStreamInfoImpl *impl;
564
FLAC__StreamMetadata_StreamInfo *stream_info;
567
g_return_val_if_fail (IS_FLAC_STREAM_INFO_IMPL (info), FALSE);
568
g_return_val_if_fail (value != NULL, FALSE);
570
impl = FLAC_STREAM_INFO_IMPL (info);
572
stream_info = &impl->priv->streaminfo->data.stream_info;
574
if (FLAC_stream_info_impl_get_n_values (info, field) <= 0)
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");
584
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TITLE);
585
g_value_set_string (value, tmp);
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");
592
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ARTIST);
593
g_value_set_string (value, tmp);
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");
600
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_ALBUM);
601
g_value_set_string (value, tmp);
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");
608
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_YEAR);
609
g_value_set_string (value, tmp);
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");
616
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_GENRE);
617
g_value_set_string (value, tmp);
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");
624
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_COMMENT);
625
g_value_set_string (value, tmp);
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");
633
g_value_set_int (value, atoi(tmp));
642
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
646
g_value_set_int (value, -1);
650
parts = g_strsplit (tmp, "/", -1);
652
if (parts[0] != NULL)
653
num = atoi (parts[0]);
655
g_value_set_int (value, num);
661
case MONKEY_MEDIA_STREAM_INFO_FIELD_MAX_TRACK_NUMBER:
666
g_value_init (value, G_TYPE_INT);
668
tmp = FLAC_stream_info_impl_id3_tag_get_utf8 (impl->priv->tag, ID3_FRAME_TRACK);
672
g_value_set_int (value, -1);
676
parts = g_strsplit (tmp, "/", -1);
678
if (parts[0] != NULL && parts[1] != NULL)
679
num = atoi (parts[1]);
681
g_value_set_int (value, num);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
753
case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_AUDIO:
754
g_value_init (value, G_TYPE_BOOLEAN);
755
g_value_set_boolean (value, TRUE);
757
case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_CODEC_INFO:
759
tmp = g_strdup_printf (_("FLAC"));
760
g_value_init (value, G_TYPE_STRING);
761
g_value_set_string (value, tmp);
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 */
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);
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);
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);
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);
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);
794
case MONKEY_MEDIA_STREAM_INFO_FIELD_AUDIO_VENDOR:
795
g_value_init (value, G_TYPE_STRING);
796
g_value_set_string (value, "");
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);
809
case MONKEY_MEDIA_STREAM_INFO_FIELD_HAS_VIDEO:
810
g_value_init (value, G_TYPE_BOOLEAN);
811
g_value_set_boolean (value, FALSE);
816
g_warning ("Invalid field!");
817
g_value_init (value, G_TYPE_NONE);
825
FLAC_stream_info_impl_set_value (MonkeyMediaStreamInfo *info,
826
MonkeyMediaStreamInfoField field,
835
FLAC_stream_info_impl_id3_tag_get_utf8 (struct id3_tag *tag, const char *field_name)
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;
843
frame = id3_tag_findframe (tag, field_name, 0);
847
field = &frame->fields[1];
848
nstrings = id3_field_getnstrings (field);
849
for (j = 0; j < nstrings; j++)
851
ucs4 = id3_field_getstrings (field, j);
853
if (strcmp (field_name, ID3_FRAME_GENRE) == 0)
854
ucs4 = id3_genre_name (ucs4);
856
utf8 = id3_ucs4_utf8duplicate (ucs4);
863
FLAC_stream_info_impl_vc_tag_get_utf8 (MonkeyMediaStreamInfo *info, const char *field_name)
865
FLACStreamInfoImpl *impl;
868
g_return_val_if_fail (IS_FLAC_STREAM_INFO_IMPL (info), NULL);
869
g_return_val_if_fail (field_name != NULL, NULL);
871
impl = FLAC_STREAM_INFO_IMPL (info);
873
utf8 = g_hash_table_lookup (impl->priv->vorbis_comments, field_name);
874
return g_strdup (utf8);