1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Dave Chapman
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
27 #include "metadata_common.h"
30 #define APETAG_HEADER_LENGTH 32
31 #define APETAG_HEADER_FORMAT "8llll8"
32 #define APETAG_ITEM_HEADER_FORMAT "ll"
33 #define APETAG_ITEM_TYPE_MASK 3
45 struct apetag_item_header
51 /* Read the items in an APEV2 tag. Only looks for a tag at the end of a
52 * file. Returns true if a tag was found and fully read, false otherwise.
54 bool read_ape_tags(int fd
, struct mp3entry
* id3
)
56 struct apetag_header header
;
58 if ((lseek(fd
, -APETAG_HEADER_LENGTH
, SEEK_END
) < 0)
59 || (ecread(fd
, &header
, 1, APETAG_HEADER_FORMAT
, IS_BIG_ENDIAN
) != APETAG_HEADER_LENGTH
)
60 || (memcmp(header
.id
, "APETAGEX", sizeof(header
.id
))))
65 if ((header
.version
== 2000) && (header
.item_count
> 0)
66 && (header
.length
> APETAG_HEADER_LENGTH
))
68 char *buf
= id3
->id3v2buf
;
69 unsigned int buf_remaining
= sizeof(id3
->id3v2buf
)
70 + sizeof(id3
->id3v1buf
);
71 unsigned int tag_remaining
= header
.length
- APETAG_HEADER_LENGTH
;
74 if (lseek(fd
, -header
.length
, SEEK_END
) < 0)
79 for (i
= 0; i
< header
.item_count
; i
++)
81 struct apetag_item_header item
;
82 char name
[TAG_NAME_LENGTH
];
83 char value
[TAG_VALUE_LENGTH
];
86 if (tag_remaining
< sizeof(item
))
91 if (ecread(fd
, &item
, 1, APETAG_ITEM_HEADER_FORMAT
, IS_BIG_ENDIAN
) < (long) sizeof(item
))
96 tag_remaining
-= sizeof(item
);
97 r
= read_string(fd
, name
, sizeof(name
), 0, tag_remaining
);
104 tag_remaining
-= r
+ item
.length
;
106 if ((item
.flags
& APETAG_ITEM_TYPE_MASK
) == 0)
110 if (read_string(fd
, value
, sizeof(value
), -1, item
.length
)
116 len
= parse_tag(name
, value
, id3
, buf
, buf_remaining
,
119 buf_remaining
-= len
;
123 if (lseek(fd
, item
.length
, SEEK_CUR
) < 0)