aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2012-07-29 18:44:03 +0200
committerMax Kellermann <max@duempel.org>2012-07-29 18:44:03 +0200
commit1dedb96478ab324104181a02bf65d928cc8e3766 (patch)
tree38cab087a23b62833a72920762c3e20b29fae27b
parent7537722a44df34411a2c23ea393a1143d88681d3 (diff)
downloadmpd-1dedb96478ab324104181a02bf65d928cc8e3766.tar.gz
mpd-1dedb96478ab324104181a02bf65d928cc8e3766.tar.xz
mpd-1dedb96478ab324104181a02bf65d928cc8e3766.zip
tag_ape: return false if no usable tag was found
Ignore APE tags that have no usable tags, and use the ID3 tag instead. This is useful when the APE tag only contains replay gain, and the real tags are stored as ID3. This implements feature request Mantis #0003521.
-rw-r--r--NEWS1
-rw-r--r--src/tag_ape.c28
2 files changed, 22 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index 85bee6bd6..0334fd045 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ ver 0.17.1 (2012/??/??)
- require appropriate permissions for searchadd{,pl}
* tags:
- aiff: support the AIFC format
+ - ape: check for ID3 if no usable APE tag was found
* playlist:
- cue: support file types "MP3", "AIFF"
* output:
diff --git a/src/tag_ape.c b/src/tag_ape.c
index 31c177aa7..b941a29bc 100644
--- a/src/tag_ape.c
+++ b/src/tag_ape.c
@@ -40,43 +40,55 @@ tag_ape_name_parse(const char *name)
return type;
}
-static void
+/**
+ * @return true if the item was recognized
+ */
+static bool
tag_ape_import_item(unsigned long flags,
const char *key, const char *value, size_t value_length,
const struct tag_handler *handler, void *handler_ctx)
{
/* we only care about utf-8 text tags */
if ((flags & (0x3 << 1)) != 0)
- return;
+ return false;
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;
+ return false;
+ bool recognized = false;
const char *end = value + value_length;
while (true) {
/* multiple values are separated by null bytes */
const char *n = memchr(value, 0, end - value);
if (n != NULL) {
- if (n > value)
+ if (n > value) {
tag_handler_invoke_tag(handler, handler_ctx,
type, value);
+ recognized = true;
+ }
+
value = n + 1;
} else {
char *p = g_strndup(value, end - value);
tag_handler_invoke_tag(handler, handler_ctx,
type, p);
g_free(p);
+ recognized = true;
break;
}
}
+
+ return recognized;
}
struct tag_ape_ctx {
const struct tag_handler *handler;
void *handler_ctx;
+
+ bool recognized;
};
static bool
@@ -85,8 +97,8 @@ tag_ape_callback(unsigned long flags, const char *key,
{
struct tag_ape_ctx *ctx = _ctx;
- tag_ape_import_item(flags, key, value, value_length,
- ctx->handler, ctx->handler_ctx);
+ ctx->recognized |= tag_ape_import_item(flags, key, value, value_length,
+ ctx->handler, ctx->handler_ctx);
return true;
}
@@ -97,7 +109,9 @@ tag_ape_scan2(const char *path_fs,
struct tag_ape_ctx ctx = {
.handler = handler,
.handler_ctx = handler_ctx,
+ .recognized = false,
};
- return tag_ape_scan(path_fs, tag_ape_callback, &ctx);
+ return tag_ape_scan(path_fs, tag_ape_callback, &ctx) &&
+ ctx.recognized;
}