1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
29 #include "metadata_common.h"
30 #include "metadata_parsers.h"
33 #define APETAG_HEADER_LENGTH 32
34 #define APETAG_HEADER_FORMAT "8llll8"
35 #define APETAG_ITEM_HEADER_FORMAT "ll"
36 #define APETAG_ITEM_TYPE_MASK 3
48 struct apetag_item_header
54 /* Read the items in an APEV2 tag. Only looks for a tag at the end of a
55 * file. Returns true if a tag was found and fully read, false otherwise.
57 bool read_ape_tags(int fd
, struct mp3entry
* id3
)
59 struct apetag_header header
;
61 if ((lseek(fd
, -APETAG_HEADER_LENGTH
, SEEK_END
) < 0)
62 || (ecread(fd
, &header
, 1, APETAG_HEADER_FORMAT
, IS_BIG_ENDIAN
) != APETAG_HEADER_LENGTH
)
63 || (memcmp(header
.id
, "APETAGEX", sizeof(header
.id
))))
68 if ((header
.version
== 2000) && (header
.item_count
> 0)
69 && (header
.length
> APETAG_HEADER_LENGTH
))
71 char *buf
= id3
->id3v2buf
;
72 unsigned int buf_remaining
= sizeof(id3
->id3v2buf
)
73 + sizeof(id3
->id3v1buf
);
74 unsigned int tag_remaining
= header
.length
- APETAG_HEADER_LENGTH
;
77 if (lseek(fd
, -header
.length
, SEEK_END
) < 0)
82 for (i
= 0; i
< header
.item_count
; i
++)
84 struct apetag_item_header item
;
85 char name
[TAG_NAME_LENGTH
];
86 char value
[TAG_VALUE_LENGTH
];
89 if (tag_remaining
< sizeof(item
))
94 if (ecread(fd
, &item
, 1, APETAG_ITEM_HEADER_FORMAT
, IS_BIG_ENDIAN
) < (long) sizeof(item
))
99 tag_remaining
-= sizeof(item
);
100 r
= read_string(fd
, name
, sizeof(name
), 0, tag_remaining
);
107 tag_remaining
-= r
+ item
.length
;
109 if ((item
.flags
& APETAG_ITEM_TYPE_MASK
) == 0)
113 if (read_string(fd
, value
, sizeof(value
), -1, item
.length
)
119 len
= parse_tag(name
, value
, id3
, buf
, buf_remaining
,
122 buf_remaining
-= len
;
126 if (lseek(fd
, item
.length
, SEEK_CUR
) < 0)