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"
28 #include "metadata_parsers.h"
31 #define APETAG_HEADER_LENGTH 32
32 #define APETAG_HEADER_FORMAT "8llll8"
33 #define APETAG_ITEM_HEADER_FORMAT "ll"
34 #define APETAG_ITEM_TYPE_MASK 3
46 struct apetag_item_header
52 /* Read the items in an APEV2 tag. Only looks for a tag at the end of a
53 * file. Returns true if a tag was found and fully read, false otherwise.
55 bool read_ape_tags(int fd
, struct mp3entry
* id3
)
57 struct apetag_header header
;
59 if ((lseek(fd
, -APETAG_HEADER_LENGTH
, SEEK_END
) < 0)
60 || (ecread(fd
, &header
, 1, APETAG_HEADER_FORMAT
, IS_BIG_ENDIAN
) != APETAG_HEADER_LENGTH
)
61 || (memcmp(header
.id
, "APETAGEX", sizeof(header
.id
))))
66 if ((header
.version
== 2000) && (header
.item_count
> 0)
67 && (header
.length
> APETAG_HEADER_LENGTH
))
69 char *buf
= id3
->id3v2buf
;
70 unsigned int buf_remaining
= sizeof(id3
->id3v2buf
)
71 + sizeof(id3
->id3v1buf
);
72 unsigned int tag_remaining
= header
.length
- APETAG_HEADER_LENGTH
;
75 if (lseek(fd
, -header
.length
, SEEK_END
) < 0)
80 for (i
= 0; i
< header
.item_count
; i
++)
82 struct apetag_item_header item
;
83 char name
[TAG_NAME_LENGTH
];
84 char value
[TAG_VALUE_LENGTH
];
87 if (tag_remaining
< sizeof(item
))
92 if (ecread(fd
, &item
, 1, APETAG_ITEM_HEADER_FORMAT
, IS_BIG_ENDIAN
) < (long) sizeof(item
))
97 tag_remaining
-= sizeof(item
);
98 r
= read_string(fd
, name
, sizeof(name
), 0, tag_remaining
);
105 tag_remaining
-= r
+ item
.length
;
107 if ((item
.flags
& APETAG_ITEM_TYPE_MASK
) == 0)
111 if (read_string(fd
, value
, sizeof(value
), -1, item
.length
)
117 len
= parse_tag(name
, value
, id3
, buf
, buf_remaining
,
120 buf_remaining
-= len
;
124 if (lseek(fd
, item
.length
, SEEK_CUR
) < 0)