diff options
Diffstat (limited to 'src/decoder/flac_metadata.c')
-rw-r--r-- | src/decoder/flac_metadata.c | 110 |
1 files changed, 73 insertions, 37 deletions
diff --git a/src/decoder/flac_metadata.c b/src/decoder/flac_metadata.c index 5b94fd426..bd1eaf323 100644 --- a/src/decoder/flac_metadata.c +++ b/src/decoder/flac_metadata.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2003-2010 The Music Player Daemon Project + * Copyright (C) 2003-2011 The Music Player Daemon Project * http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -21,6 +21,8 @@ #include "flac_metadata.h" #include "replay_gain_info.h" #include "tag.h" +#include "tag_handler.h" +#include "tag_table.h" #include <glib.h> @@ -163,69 +165,87 @@ flac_comment_value(const FLAC__StreamMetadata_VorbisComment_Entry *entry, * the comment value into the tag. */ static bool -flac_copy_comment(struct tag *tag, - const FLAC__StreamMetadata_VorbisComment_Entry *entry, +flac_copy_comment(const FLAC__StreamMetadata_VorbisComment_Entry *entry, const char *name, enum tag_type tag_type, - const char *char_tnum) + const char *char_tnum, + const struct tag_handler *handler, void *handler_ctx) { const char *value; size_t value_length; value = flac_comment_value(entry, name, char_tnum, &value_length); if (value != NULL) { - tag_add_item_n(tag, tag_type, value, value_length); + char *p = g_strndup(value, value_length); + tag_handler_invoke_tag(handler, handler_ctx, tag_type, p); + g_free(p); return true; } return false; } -/* tracknumber is used in VCs, MPD uses "track" ..., all the other - * tag names match */ -static const char *VORBIS_COMMENT_TRACK_KEY = "tracknumber"; -static const char *VORBIS_COMMENT_DISC_KEY = "discnumber"; +static const struct tag_table flac_tags[] = { + { "tracknumber", TAG_TRACK }, + { "discnumber", TAG_DISC }, + { "album artist", TAG_ALBUM_ARTIST }, + { NULL, TAG_NUM_OF_ITEM_TYPES } +}; static void -flac_parse_comment(struct tag *tag, const char *char_tnum, - const FLAC__StreamMetadata_VorbisComment_Entry *entry) +flac_scan_comment(const char *char_tnum, + const FLAC__StreamMetadata_VorbisComment_Entry *entry, + const struct tag_handler *handler, void *handler_ctx) { - assert(tag != NULL); + if (handler->pair != NULL) { + char *name = g_strdup((const char*)entry->entry); + char *value = strchr(name, '='); + + if (value != NULL && value > name) { + *value++ = 0; + tag_handler_invoke_pair(handler, handler_ctx, + name, value); + } - if (flac_copy_comment(tag, entry, VORBIS_COMMENT_TRACK_KEY, - TAG_TRACK, char_tnum) || - flac_copy_comment(tag, entry, VORBIS_COMMENT_DISC_KEY, - TAG_DISC, char_tnum) || - flac_copy_comment(tag, entry, "album artist", - TAG_ALBUM_ARTIST, char_tnum)) - return; + g_free(name); + } + + for (const struct tag_table *i = flac_tags; i->name != NULL; ++i) + if (flac_copy_comment(entry, i->name, i->type, char_tnum, + handler, handler_ctx)) + return; for (unsigned i = 0; i < TAG_NUM_OF_ITEM_TYPES; ++i) - if (flac_copy_comment(tag, entry, - tag_item_names[i], i, char_tnum)) + if (flac_copy_comment(entry, + tag_item_names[i], i, char_tnum, + handler, handler_ctx)) return; } -void -flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum, - const FLAC__StreamMetadata_VorbisComment *comment) +static void +flac_scan_comments(const char *char_tnum, + const FLAC__StreamMetadata_VorbisComment *comment, + const struct tag_handler *handler, void *handler_ctx) { for (unsigned i = 0; i < comment->num_comments; ++i) - flac_parse_comment(tag, char_tnum, &comment->comments[i]); + flac_scan_comment(char_tnum, &comment->comments[i], + handler, handler_ctx); } void -flac_tag_apply_metadata(struct tag *tag, const char *track, - const FLAC__StreamMetadata *block) +flac_scan_metadata(const char *track, + const FLAC__StreamMetadata *block, + const struct tag_handler *handler, void *handler_ctx) { switch (block->type) { case FLAC__METADATA_TYPE_VORBIS_COMMENT: - flac_vorbis_comments_to_tag(tag, track, - &block->data.vorbis_comment); + flac_scan_comments(track, &block->data.vorbis_comment, + handler, handler_ctx); break; case FLAC__METADATA_TYPE_STREAMINFO: if (block->data.stream_info.sample_rate > 0) - tag->time = flac_duration(&block->data.stream_info); + tag_handler_invoke_duration(handler, handler_ctx, + flac_duration(&block->data.stream_info)); break; default: @@ -233,10 +253,18 @@ flac_tag_apply_metadata(struct tag *tag, const char *track, } } -struct tag * -flac_tag_load(const char *file, const char *char_tnum) +void +flac_vorbis_comments_to_tag(struct tag *tag, const char *char_tnum, + const FLAC__StreamMetadata_VorbisComment *comment) +{ + flac_scan_comments(char_tnum, comment, + &add_tag_handler, tag); +} + +bool +flac_scan_file2(const char *file, const char *char_tnum, + const struct tag_handler *handler, void *handler_ctx) { - struct tag *tag; FLAC__Metadata_SimpleIterator *it; FLAC__StreamMetadata *block = NULL; @@ -263,22 +291,30 @@ flac_tag_load(const char *file, const char *char_tnum) g_debug("Reading '%s' metadata gave the following error: %s\n", file, err); FLAC__metadata_simple_iterator_delete(it); - return NULL; + return false; } - tag = tag_new(); do { block = FLAC__metadata_simple_iterator_get_block(it); if (!block) break; - flac_tag_apply_metadata(tag, char_tnum, block); + flac_scan_metadata(char_tnum, block, handler, handler_ctx); FLAC__metadata_object_delete(block); } while (FLAC__metadata_simple_iterator_next(it)); FLAC__metadata_simple_iterator_delete(it); - if (!tag_is_defined(tag)) { + return true; +} + +struct tag * +flac_tag_load(const char *file, const char *char_tnum) +{ + struct tag *tag = tag_new(); + + if (!flac_scan_file2(file, char_tnum, &add_tag_handler, tag) || + tag_is_empty(tag)) { tag_free(tag); tag = NULL; } |