diff options
author | Marcoen Hirschberg <marcoen@gmail.com> | 2007-06-16 18:19:51 +0000 |
---|---|---|
committer | Marcoen Hirschberg <marcoen@gmail.com> | 2007-06-16 18:19:51 +0000 |
commit | 2175d1edf65367fd3fe3cff266b8d6ea12930f2f (patch) | |
tree | 9d6f50ebfc7919b4e2f0853fc8c0cb844cabe995 /apps/metadata/ape.c | |
parent | c3206a455a455fadb282d09f9af482c66b6bdf8e (diff) | |
download | rockbox-2175d1edf65367fd3fe3cff266b8d6ea12930f2f.tar.gz rockbox-2175d1edf65367fd3fe3cff266b8d6ea12930f2f.zip |
split up the metadata parser
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13637 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/metadata/ape.c')
-rw-r--r-- | apps/metadata/ape.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/apps/metadata/ape.c b/apps/metadata/ape.c new file mode 100644 index 0000000000..ac071be6f7 --- /dev/null +++ b/apps/metadata/ape.c | |||
@@ -0,0 +1,132 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Dave Chapman | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <stdio.h> | ||
20 | #include <string.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <ctype.h> | ||
23 | #include <inttypes.h> | ||
24 | |||
25 | #include "system.h" | ||
26 | #include "id3.h" | ||
27 | #include "metadata_common.h" | ||
28 | #include "structec.h" | ||
29 | |||
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 | ||
34 | |||
35 | struct apetag_header | ||
36 | { | ||
37 | char id[8]; | ||
38 | long version; | ||
39 | long length; | ||
40 | long item_count; | ||
41 | long flags; | ||
42 | char reserved[8]; | ||
43 | }; | ||
44 | |||
45 | struct apetag_item_header | ||
46 | { | ||
47 | long length; | ||
48 | long flags; | ||
49 | }; | ||
50 | |||
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. | ||
53 | */ | ||
54 | bool read_ape_tags(int fd, struct mp3entry* id3) | ||
55 | { | ||
56 | struct apetag_header header; | ||
57 | |||
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)))) | ||
61 | { | ||
62 | return false; | ||
63 | } | ||
64 | |||
65 | if ((header.version == 2000) && (header.item_count > 0) | ||
66 | && (header.length > APETAG_HEADER_LENGTH)) | ||
67 | { | ||
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; | ||
72 | int i; | ||
73 | |||
74 | if (lseek(fd, -header.length, SEEK_END) < 0) | ||
75 | { | ||
76 | return false; | ||
77 | } | ||
78 | |||
79 | for (i = 0; i < header.item_count; i++) | ||
80 | { | ||
81 | struct apetag_item_header item; | ||
82 | char name[TAG_NAME_LENGTH]; | ||
83 | char value[TAG_VALUE_LENGTH]; | ||
84 | long r; | ||
85 | |||
86 | if (tag_remaining < sizeof(item)) | ||
87 | { | ||
88 | break; | ||
89 | } | ||
90 | |||
91 | if (ecread(fd, &item, 1, APETAG_ITEM_HEADER_FORMAT, IS_BIG_ENDIAN) < (long) sizeof(item)) | ||
92 | { | ||
93 | return false; | ||
94 | } | ||
95 | |||
96 | tag_remaining -= sizeof(item); | ||
97 | r = read_string(fd, name, sizeof(name), 0, tag_remaining); | ||
98 | |||
99 | if (r == -1) | ||
100 | { | ||
101 | return false; | ||
102 | } | ||
103 | |||
104 | tag_remaining -= r + item.length; | ||
105 | |||
106 | if ((item.flags & APETAG_ITEM_TYPE_MASK) == 0) | ||
107 | { | ||
108 | long len; | ||
109 | |||
110 | if (read_string(fd, value, sizeof(value), -1, item.length) | ||
111 | != item.length) | ||
112 | { | ||
113 | return false; | ||
114 | } | ||
115 | |||
116 | len = parse_tag(name, value, id3, buf, buf_remaining, | ||
117 | TAGTYPE_APE); | ||
118 | buf += len; | ||
119 | buf_remaining -= len; | ||
120 | } | ||
121 | else | ||
122 | { | ||
123 | if (lseek(fd, item.length, SEEK_CUR) < 0) | ||
124 | { | ||
125 | return false; | ||
126 | } | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return true; | ||
132 | } | ||