Skip to content

Commit f723e42

Browse files
committed
Support multi-value TXXX/WXXX frames in ID3v2
ID3v2.4 allows null-separated multiple strings in TXXX value fields. Audio::Scan previously read only the first value. Add a loop mirroring the existing STRINGLIST handler for standard text frames: returns an arrayref when multiple values are present, scalar when single. This enables plural tags like TXXX:ALBUMARTISTS written by Picard to reach consumers as arrays instead of being truncated. Signed-off-by: Rouzax <GitHub@mgdn.nl>
1 parent f6094e0 commit f723e42

1 file changed

Lines changed: 31 additions & 5 deletions

File tree

src/id3.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -798,24 +798,50 @@ _id3_parse_v2_frame_data(id3info *id3, char const *id, uint32_t size, id3_framet
798798
// Read key and uppercase it
799799
SV *key = NULL;
800800
SV *value = NULL;
801+
AV *array = NULL;
802+
int count = 0;
801803

802804
read += _id3_get_utf8_string(id3, &key, size - read, encoding);
803805

804806
if (key != NULL && SvPOK(key) && sv_len(key)) {
805807
upcase(SvPVX(key));
806808

807-
// Read value
809+
// Read value(s)
808810
if (frametype->fields[2] == ID3_FIELD_TYPE_LATIN1) {
809811
// WXXX frames have a latin1 value field regardless of encoding byte
810812
encoding = ISO_8859_1;
811813
}
812814

813-
read += _id3_get_utf8_string(id3, &value, size - read, encoding);
815+
// ID3v2.4 allows multiple null-separated strings in TXXX value field.
816+
// Loop mirrors the STRINGLIST handler for standard T* frames.
817+
while (read < size) {
818+
if (count++ == 1 && value != NULL) {
819+
array = newAV();
820+
av_push(array, value);
821+
}
822+
value = NULL;
814823

815-
// (T|W)XXX frames don't support multiple strings separated by nulls, even in v2.4
824+
read += _id3_get_utf8_string(id3, &value, size - read, encoding);
816825

817-
// Only one tag per unique key value is allowed, that's why there is no array support here
818-
if (value != NULL && SvPOK(value)) {
826+
if (array != NULL && value != NULL && SvPOK(value)) {
827+
// Bug 16452, do not add an empty string
828+
if (sv_len(value) > 0)
829+
av_push(array, value);
830+
}
831+
}
832+
833+
if (array != NULL) {
834+
if (av_len(array) == 0) {
835+
// Multiple strings but only one non-empty: collapse to scalar
836+
my_hv_store_ent( id3->tags, key, av_shift(array) );
837+
SvREFCNT_dec(array);
838+
}
839+
else {
840+
my_hv_store_ent( id3->tags, key, newRV_noinc( (SV *)array ) );
841+
}
842+
array = NULL;
843+
}
844+
else if (value != NULL && SvPOK(value)) {
819845
my_hv_store_ent( id3->tags, key, value );
820846
}
821847
else {

0 commit comments

Comments
 (0)