aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-02-11 19:24:51 +0100
committerMax Kellermann <max@duempel.org>2012-02-12 13:41:48 +0100
commitffea273a28179d2b5bbc24f967517bcf80940c63 (patch)
tree5891ed63a60ba0eed7c2b4433ea72f566f982822
parent1783aac4384ccc53d9ad25c237d4286ccdbccbc0 (diff)
downloadmpd-ffea273a28179d2b5bbc24f967517bcf80940c63.tar.gz
mpd-ffea273a28179d2b5bbc24f967517bcf80940c63.tar.xz
mpd-ffea273a28179d2b5bbc24f967517bcf80940c63.zip
tag_handler: handle arbitrary name/value pairs
The new method pair() receives an arbitrary name/value pair. Support for this is being added to a few decoder plugins.
Diffstat (limited to '')
-rw-r--r--src/decoder/ffmpeg_metadata.c20
-rw-r--r--src/decoder/flac_metadata.c13
-rw-r--r--src/decoder/mp4ff_decoder_plugin.c2
-rw-r--r--src/decoder/vorbis_comments.c13
-rw-r--r--src/decoder/wavpack_decoder_plugin.c27
-rw-r--r--src/tag_ape.c2
-rw-r--r--src/tag_handler.h18
-rw-r--r--src/tag_id3.c19
-rw-r--r--test/read_tags.c9
9 files changed, 114 insertions, 9 deletions
diff --git a/src/decoder/ffmpeg_metadata.c b/src/decoder/ffmpeg_metadata.c
index 5325c1cae..df700fc01 100644
--- a/src/decoder/ffmpeg_metadata.c
+++ b/src/decoder/ffmpeg_metadata.c
@@ -50,6 +50,21 @@ ffmpeg_copy_metadata(enum tag_type type,
type, mt->value);
}
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,5,0)
+
+static void
+ffmpeg_scan_pairs(AVDictionary *dict,
+ const struct tag_handler *handler, void *handler_ctx)
+{
+ AVDictionaryEntry *i = NULL;
+
+ while ((i = av_dict_get(dict, "", i, AV_DICT_IGNORE_SUFFIX)) != NULL)
+ tag_handler_invoke_pair(handler, handler_ctx,
+ i->key, i->value);
+}
+
+#endif
+
void
ffmpeg_scan_dictionary(AVDictionary *dict,
const struct tag_handler *handler, void *handler_ctx)
@@ -62,4 +77,9 @@ ffmpeg_scan_dictionary(AVDictionary *dict,
i->name != NULL; ++i)
ffmpeg_copy_metadata(i->type, dict, i->name,
handler, handler_ctx);
+
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(51,5,0)
+ if (handler->pair != NULL)
+ ffmpeg_scan_pairs(dict, handler, handler_ctx);
+#endif
}
diff --git a/src/decoder/flac_metadata.c b/src/decoder/flac_metadata.c
index 9e138ef96..bd1eaf323 100644
--- a/src/decoder/flac_metadata.c
+++ b/src/decoder/flac_metadata.c
@@ -196,6 +196,19 @@ flac_scan_comment(const char *char_tnum,
const FLAC__StreamMetadata_VorbisComment_Entry *entry,
const struct tag_handler *handler, void *handler_ctx)
{
+ 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);
+ }
+
+ 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))
diff --git a/src/decoder/mp4ff_decoder_plugin.c b/src/decoder/mp4ff_decoder_plugin.c
index e1e48770a..ca78a22d0 100644
--- a/src/decoder/mp4ff_decoder_plugin.c
+++ b/src/decoder/mp4ff_decoder_plugin.c
@@ -414,6 +414,8 @@ mp4ff_scan_stream(struct input_stream *is,
mp4ff_meta_get_by_index(mp4fh, i, &item, &value);
+ tag_handler_invoke_pair(handler, handler_ctx, item, value);
+
enum tag_type type = mp4ff_tag_name_parse(item);
if (type != TAG_NUM_OF_ITEM_TYPES)
tag_handler_invoke_tag(handler, handler_ctx,
diff --git a/src/decoder/vorbis_comments.c b/src/decoder/vorbis_comments.c
index e94ee3d0a..6c2d57b72 100644
--- a/src/decoder/vorbis_comments.c
+++ b/src/decoder/vorbis_comments.c
@@ -106,6 +106,19 @@ static void
vorbis_scan_comment(const char *comment,
const struct tag_handler *handler, void *handler_ctx)
{
+ if (handler->pair != NULL) {
+ char *name = g_strdup((const char*)comment);
+ char *value = strchr(name, '=');
+
+ if (value != NULL && value > name) {
+ *value++ = 0;
+ tag_handler_invoke_pair(handler, handler_ctx,
+ name, value);
+ }
+
+ g_free(name);
+ }
+
for (const struct tag_table *i = vorbis_tags; i->name != NULL; ++i)
if (vorbis_copy_comment(comment, i->name, i->type,
handler, handler_ctx))
diff --git a/src/decoder/wavpack_decoder_plugin.c b/src/decoder/wavpack_decoder_plugin.c
index 7ba50ba32..88a4854b8 100644
--- a/src/decoder/wavpack_decoder_plugin.c
+++ b/src/decoder/wavpack_decoder_plugin.c
@@ -286,6 +286,19 @@ wavpack_scan_tag_item(WavpackContext *wpc, const char *name,
}
+static void
+wavpack_scan_pair(WavpackContext *wpc, const char *name,
+ const struct tag_handler *handler, void *handler_ctx)
+{
+ char buffer[1024];
+ int len = WavpackGetTagItem(wpc, name, buffer, sizeof(buffer));
+ if (len <= 0 || (unsigned)len >= sizeof(buffer))
+ return;
+
+ tag_handler_invoke_pair(handler, handler_ctx, name, buffer);
+
+}
+
/*
* Reads metainfo from the specified file.
*/
@@ -313,6 +326,20 @@ wavpack_scan_file(const char *fname,
wavpack_scan_tag_item(wpc, i->name, i->type,
handler, handler_ctx);
+ if (handler->pair != NULL) {
+ char name[64];
+
+ for (int i = 0, n = WavpackGetNumTagItems(wpc);
+ i < n; ++i) {
+ int len = WavpackGetTagItemIndexed(wpc, i, name,
+ sizeof(name));
+ if (len <= 0 || (unsigned)len >= sizeof(name))
+ continue;
+
+ wavpack_scan_pair(wpc, name, handler, handler_ctx);
+ }
+ }
+
WavpackCloseFile(wpc);
return true;
diff --git a/src/tag_ape.c b/src/tag_ape.c
index 93d935b75..068a9aa6d 100644
--- a/src/tag_ape.c
+++ b/src/tag_ape.c
@@ -49,6 +49,8 @@ tag_ape_import_item(unsigned long flags,
if ((flags & (0x3 << 1)) != 0)
return;
+ tag_handler_invoke_pair(handler, handler_ctx, key, value);
+
enum tag_type type = tag_ape_name_parse(key);
if (type == TAG_NUM_OF_ITEM_TYPES)
return;
diff --git a/src/tag_handler.h b/src/tag_handler.h
index 13e40f38d..653918588 100644
--- a/src/tag_handler.h
+++ b/src/tag_handler.h
@@ -43,6 +43,12 @@ struct tag_handler {
* invalid after returning
*/
void (*tag)(enum tag_type type, const char *value, void *ctx);
+
+ /**
+ * A name-value pair has been read. It is the codec specific
+ * representation of tags.
+ */
+ void (*pair)(const char *key, const char *value, void *ctx);
};
static inline void
@@ -67,6 +73,18 @@ tag_handler_invoke_tag(const struct tag_handler *handler, void *ctx,
handler->tag(type, value, ctx);
}
+static inline void
+tag_handler_invoke_pair(const struct tag_handler *handler, void *ctx,
+ const char *name, const char *value)
+{
+ assert(handler != NULL);
+ assert(name != NULL);
+ assert(value != NULL);
+
+ if (handler->pair != NULL)
+ handler->pair(name, value, ctx);
+}
+
/**
* This #tag_handler implementation adds tag values to a #tag object
* (casted from the context pointer).
diff --git a/src/tag_id3.c b/src/tag_id3.c
index 8becb481c..058701524 100644
--- a/src/tag_id3.c
+++ b/src/tag_id3.c
@@ -282,18 +282,21 @@ tag_id3_import_musicbrainz(struct id3_tag *id3_tag,
if (name == NULL)
continue;
- type = tag_id3_parse_txxx_name((const char*)name);
- free(name);
-
- if (type == TAG_NUM_OF_ITEM_TYPES)
- continue;
-
value = tag_id3_getstring(frame, 2);
if (value == NULL)
continue;
- tag_handler_invoke_tag(handler, handler_ctx,
- type, (const char*)value);
+ tag_handler_invoke_pair(handler, handler_ctx,
+ (const char *)name,
+ (const char *)value);
+
+ type = tag_id3_parse_txxx_name((const char*)name);
+ free(name);
+
+ if (type != TAG_NUM_OF_ITEM_TYPES)
+ tag_handler_invoke_tag(handler, handler_ctx,
+ type, (const char*)value);
+
free(value);
}
}
diff --git a/test/read_tags.c b/test/read_tags.c
index 9fcf1acfe..b5ca8e55a 100644
--- a/test/read_tags.c
+++ b/test/read_tags.c
@@ -145,13 +145,20 @@ print_duration(unsigned seconds, G_GNUC_UNUSED void *ctx)
static void
print_tag(enum tag_type type, const char *value, G_GNUC_UNUSED void *ctx)
{
- g_print("%s=%s\n", tag_item_names[type], value);
+ g_print("[%s]=%s\n", tag_item_names[type], value);
empty = false;
}
+static void
+print_pair(const char *name, const char *value, G_GNUC_UNUSED void *ctx)
+{
+ g_print("\"%s\"=%s\n", name, value);
+}
+
static const struct tag_handler print_handler = {
.duration = print_duration,
.tag = print_tag,
+ .pair = print_pair,
};
int main(int argc, char **argv)