diff options
author | Sean Bartell <wingedtachikoma@gmail.com> | 2011-06-24 01:25:21 -0400 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2012-03-18 12:00:39 +0100 |
commit | b5716df4cb2837bbbc42195cf1aefcf03e21d6a6 (patch) | |
tree | 130cd712e2e00893b6df9959a375a8d9523a1aca /apps/metadata/metadata_common.c | |
parent | 24bd9d5393dbe39a5c6194877bc00ede669b1d5d (diff) | |
download | rockbox-b5716df4cb2837bbbc42195cf1aefcf03e21d6a6.tar.gz rockbox-b5716df4cb2837bbbc42195cf1aefcf03e21d6a6.zip |
Build librbcodec with DSP and metadata.
All associated files are moved to /lib/rbcodec.
Change-Id: I572ddd2b8a996aae1e98c081d06b1ed356dce222
Diffstat (limited to 'apps/metadata/metadata_common.c')
-rw-r--r-- | apps/metadata/metadata_common.c | 374 |
1 files changed, 0 insertions, 374 deletions
diff --git a/apps/metadata/metadata_common.c b/apps/metadata/metadata_common.c deleted file mode 100644 index e861644025..0000000000 --- a/apps/metadata/metadata_common.c +++ /dev/null | |||
@@ -1,374 +0,0 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2005 Dave Chapman | ||
11 | * | ||
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. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include <stdio.h> | ||
22 | #include "string-extra.h" | ||
23 | #include <stdlib.h> | ||
24 | #include <ctype.h> | ||
25 | #include <inttypes.h> | ||
26 | |||
27 | #include "system.h" | ||
28 | #include "metadata.h" | ||
29 | #include "metadata_common.h" | ||
30 | #include "metadata_parsers.h" | ||
31 | #include "replaygain.h" | ||
32 | |||
33 | /* Read a string from the file. Read up to size bytes, or, if eos != -1, | ||
34 | * until the eos character is found (eos is not stored in buf, unless it is | ||
35 | * nil). Writes up to buf_size chars to buf, always terminating with a nil. | ||
36 | * Returns number of chars read or -1 on read error. | ||
37 | */ | ||
38 | long read_string(int fd, char* buf, long buf_size, int eos, long size) | ||
39 | { | ||
40 | long read_bytes = 0; | ||
41 | char c; | ||
42 | |||
43 | while (size != 0) | ||
44 | { | ||
45 | if (read(fd, &c, 1) != 1) | ||
46 | { | ||
47 | read_bytes = -1; | ||
48 | break; | ||
49 | } | ||
50 | |||
51 | read_bytes++; | ||
52 | size--; | ||
53 | |||
54 | if ((eos != -1) && (eos == (unsigned char) c)) | ||
55 | { | ||
56 | break; | ||
57 | } | ||
58 | |||
59 | if (buf_size > 1) | ||
60 | { | ||
61 | *buf++ = c; | ||
62 | buf_size--; | ||
63 | } | ||
64 | } | ||
65 | |||
66 | *buf = 0; | ||
67 | return read_bytes; | ||
68 | } | ||
69 | /* Read an unsigned 8-bit integer from a file. */ | ||
70 | int read_uint8(int fd, uint8_t* buf) | ||
71 | { | ||
72 | size_t n; | ||
73 | |||
74 | n = read(fd, (char*) buf, 1); | ||
75 | return n; | ||
76 | } | ||
77 | |||
78 | #ifdef ROCKBOX_LITTLE_ENDIAN | ||
79 | /* Read an unsigned 16-bit integer from a big-endian file. */ | ||
80 | int read_uint16be(int fd, uint16_t* buf) | ||
81 | { | ||
82 | size_t n; | ||
83 | |||
84 | n = read(fd, (char*) buf, 2); | ||
85 | *buf = betoh16(*buf); | ||
86 | return n; | ||
87 | } | ||
88 | /* Read an unsigned 32-bit integer from a big-endian file. */ | ||
89 | int read_uint32be(int fd, uint32_t* buf) | ||
90 | { | ||
91 | size_t n; | ||
92 | |||
93 | n = read(fd, (char*) buf, 4); | ||
94 | *buf = betoh32(*buf); | ||
95 | return n; | ||
96 | } | ||
97 | /* Read an unsigned 64-bit integer from a big-endian file. */ | ||
98 | int read_uint64be(int fd, uint64_t* buf) | ||
99 | { | ||
100 | size_t n; | ||
101 | uint8_t data[8]; | ||
102 | int i; | ||
103 | |||
104 | n = read(fd, data, 8); | ||
105 | |||
106 | for (i=0, *buf=0; i<=7; i++) { | ||
107 | *buf <<= 8; | ||
108 | *buf |= data[i]; | ||
109 | } | ||
110 | return n; | ||
111 | } | ||
112 | #else | ||
113 | /* Read unsigned integers from a little-endian file. */ | ||
114 | int read_uint16le(int fd, uint16_t* buf) | ||
115 | { | ||
116 | size_t n; | ||
117 | |||
118 | n = read(fd, (char*) buf, 2); | ||
119 | *buf = letoh16(*buf); | ||
120 | return n; | ||
121 | } | ||
122 | int read_uint32le(int fd, uint32_t* buf) | ||
123 | { | ||
124 | size_t n; | ||
125 | |||
126 | n = read(fd, (char*) buf, 4); | ||
127 | *buf = letoh32(*buf); | ||
128 | return n; | ||
129 | } | ||
130 | int read_uint64le(int fd, uint64_t* buf) | ||
131 | { | ||
132 | size_t n; | ||
133 | uint8_t data[8]; | ||
134 | int i; | ||
135 | |||
136 | n = read(fd, data, 8); | ||
137 | |||
138 | for (i=7, *buf=0; i>=0; i--) { | ||
139 | *buf <<= 8; | ||
140 | *buf |= data[i]; | ||
141 | } | ||
142 | |||
143 | return n; | ||
144 | } | ||
145 | #endif | ||
146 | |||
147 | /* Read an unaligned 64-bit little endian unsigned integer from buffer. */ | ||
148 | uint64_t get_uint64_le(void* buf) | ||
149 | { | ||
150 | unsigned char* p = (unsigned char*) buf; | ||
151 | |||
152 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24) | ((uint64_t)p[4] << 32) | | ||
153 | ((uint64_t)p[5] << 40) | ((uint64_t)p[6] << 48) | ((uint64_t)p[7] << 56); | ||
154 | } | ||
155 | |||
156 | /* Read an unaligned 32-bit little endian long from buffer. */ | ||
157 | uint32_t get_long_le(void* buf) | ||
158 | { | ||
159 | unsigned char* p = (unsigned char*) buf; | ||
160 | |||
161 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
162 | } | ||
163 | |||
164 | /* Read an unaligned 16-bit little endian short from buffer. */ | ||
165 | uint16_t get_short_le(void* buf) | ||
166 | { | ||
167 | unsigned char* p = (unsigned char*) buf; | ||
168 | |||
169 | return p[0] | (p[1] << 8); | ||
170 | } | ||
171 | |||
172 | /* Read an unaligned 32-bit big endian long from buffer. */ | ||
173 | uint32_t get_long_be(void* buf) | ||
174 | { | ||
175 | unsigned char* p = (unsigned char*) buf; | ||
176 | |||
177 | return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; | ||
178 | } | ||
179 | |||
180 | /* Read an unaligned 16-bit little endian short from buffer. */ | ||
181 | uint16_t get_short_be(void* buf) | ||
182 | { | ||
183 | unsigned char* p = (unsigned char*) buf; | ||
184 | |||
185 | return (p[0] << 8) | p[1]; | ||
186 | } | ||
187 | |||
188 | /* Read an unaligned 32-bit little endian long from buffer. */ | ||
189 | int32_t get_slong(void* buf) | ||
190 | { | ||
191 | unsigned char* p = (unsigned char*) buf; | ||
192 | |||
193 | return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); | ||
194 | } | ||
195 | |||
196 | uint32_t get_itunes_int32(char* value, int count) | ||
197 | { | ||
198 | static const char hexdigits[] = "0123456789ABCDEF"; | ||
199 | const char* c; | ||
200 | int r = 0; | ||
201 | |||
202 | while (count-- > 0) | ||
203 | { | ||
204 | while (isspace(*value)) | ||
205 | { | ||
206 | value++; | ||
207 | } | ||
208 | |||
209 | while (*value && !isspace(*value)) | ||
210 | { | ||
211 | value++; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | while (isspace(*value)) | ||
216 | { | ||
217 | value++; | ||
218 | } | ||
219 | |||
220 | while (*value && ((c = strchr(hexdigits, toupper(*value))) != NULL)) | ||
221 | { | ||
222 | r = (r << 4) | (c - hexdigits); | ||
223 | value++; | ||
224 | } | ||
225 | |||
226 | return r; | ||
227 | } | ||
228 | |||
229 | /* Skip an ID3v2 tag if it can be found. We assume the tag is located at the | ||
230 | * start of the file, which should be true in all cases where we need to skip it. | ||
231 | * Returns true if successfully skipped or not skipped, and false if | ||
232 | * something went wrong while skipping. | ||
233 | */ | ||
234 | bool skip_id3v2(int fd, struct mp3entry *id3) | ||
235 | { | ||
236 | char buf[4]; | ||
237 | |||
238 | read(fd, buf, 4); | ||
239 | if (memcmp(buf, "ID3", 3) == 0) | ||
240 | { | ||
241 | /* We have found an ID3v2 tag at the start of the file - find its | ||
242 | length and then skip it. */ | ||
243 | if ((id3->first_frame_offset = getid3v2len(fd)) == 0) | ||
244 | return false; | ||
245 | |||
246 | if ((lseek(fd, id3->first_frame_offset, SEEK_SET) < 0)) | ||
247 | return false; | ||
248 | |||
249 | return true; | ||
250 | } else { | ||
251 | lseek(fd, 0, SEEK_SET); | ||
252 | id3->first_frame_offset = 0; | ||
253 | return true; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | /* Parse the tag (the name-value pair) and fill id3 and buffer accordingly. | ||
258 | * String values to keep are written to buf. Returns number of bytes written | ||
259 | * to buf (including end nil). | ||
260 | */ | ||
261 | long parse_tag(const char* name, char* value, struct mp3entry* id3, | ||
262 | char* buf, long buf_remaining, enum tagtype type) | ||
263 | { | ||
264 | long len = 0; | ||
265 | char** p; | ||
266 | |||
267 | if ((((strcasecmp(name, "track") == 0) && (type == TAGTYPE_APE))) | ||
268 | || ((strcasecmp(name, "tracknumber") == 0) && (type == TAGTYPE_VORBIS))) | ||
269 | { | ||
270 | id3->tracknum = atoi(value); | ||
271 | p = &(id3->track_string); | ||
272 | } | ||
273 | else if (strcasecmp(name, "discnumber") == 0 || strcasecmp(name, "disc") == 0) | ||
274 | { | ||
275 | id3->discnum = atoi(value); | ||
276 | p = &(id3->disc_string); | ||
277 | } | ||
278 | else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE)) | ||
279 | || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS))) | ||
280 | { | ||
281 | /* Date's can be in any format in Vorbis. However most of them | ||
282 | * are in ISO8601 format so if we try and parse the first part | ||
283 | * of the tag as a number, we should get the year. If we get crap, | ||
284 | * then act like we never parsed it. | ||
285 | */ | ||
286 | id3->year = atoi(value); | ||
287 | if (id3->year < 1900) | ||
288 | { /* yeah, not likely */ | ||
289 | id3->year = 0; | ||
290 | } | ||
291 | p = &(id3->year_string); | ||
292 | } | ||
293 | else if (strcasecmp(name, "title") == 0) | ||
294 | { | ||
295 | p = &(id3->title); | ||
296 | } | ||
297 | else if (strcasecmp(name, "artist") == 0) | ||
298 | { | ||
299 | p = &(id3->artist); | ||
300 | } | ||
301 | else if (strcasecmp(name, "album") == 0) | ||
302 | { | ||
303 | p = &(id3->album); | ||
304 | } | ||
305 | else if (strcasecmp(name, "genre") == 0) | ||
306 | { | ||
307 | p = &(id3->genre_string); | ||
308 | } | ||
309 | else if (strcasecmp(name, "composer") == 0) | ||
310 | { | ||
311 | p = &(id3->composer); | ||
312 | } | ||
313 | else if (strcasecmp(name, "comment") == 0) | ||
314 | { | ||
315 | p = &(id3->comment); | ||
316 | } | ||
317 | else if (strcasecmp(name, "albumartist") == 0) | ||
318 | { | ||
319 | p = &(id3->albumartist); | ||
320 | } | ||
321 | else if (strcasecmp(name, "album artist") == 0) | ||
322 | { | ||
323 | p = &(id3->albumartist); | ||
324 | } | ||
325 | else if (strcasecmp(name, "ensemble") == 0) | ||
326 | { | ||
327 | p = &(id3->albumartist); | ||
328 | } | ||
329 | else if (strcasecmp(name, "grouping") == 0) | ||
330 | { | ||
331 | p = &(id3->grouping); | ||
332 | } | ||
333 | else if (strcasecmp(name, "content group") == 0) | ||
334 | { | ||
335 | p = &(id3->grouping); | ||
336 | } | ||
337 | else if (strcasecmp(name, "contentgroup") == 0) | ||
338 | { | ||
339 | p = &(id3->grouping); | ||
340 | } | ||
341 | else if (strcasecmp(name, "musicbrainz_trackid") == 0 | ||
342 | || strcasecmp(name, "http://musicbrainz.org") == 0 ) | ||
343 | { | ||
344 | p = &(id3->mb_track_id); | ||
345 | } | ||
346 | else | ||
347 | { | ||
348 | parse_replaygain(name, value, id3); | ||
349 | p = NULL; | ||
350 | } | ||
351 | |||
352 | /* Do not overwrite already available metadata. Especially when reading | ||
353 | * tags with e.g. multiple genres / artists. This way only the first | ||
354 | * of multiple entries is used, all following are dropped. */ | ||
355 | if (p!=NULL && *p==NULL) | ||
356 | { | ||
357 | len = strlen(value); | ||
358 | len = MIN(len, buf_remaining - 1); | ||
359 | len = MIN(len, ID3V2_MAX_ITEM_SIZE); /* Limit max. item size. */ | ||
360 | |||
361 | if (len > 0) | ||
362 | { | ||
363 | len++; | ||
364 | strlcpy(buf, value, len); | ||
365 | *p = buf; | ||
366 | } | ||
367 | else | ||
368 | { | ||
369 | len = 0; | ||
370 | } | ||
371 | } | ||
372 | |||
373 | return len; | ||
374 | } | ||