mp3: when ID3 tags are not found, search APE tags
[kugel-rb.git] / apps / metadata / metadata_common.c
blob4130fcfd14dabcb0383411c81add8e209776e18f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include <stdio.h>
22 #include "string-extra.h"
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include <inttypes.h>
27 #include "system.h"
28 #include "metadata.h"
29 #include "metadata_common.h"
30 #include "metadata_parsers.h"
31 #if CONFIG_CODEC == SWCODEC
32 #include "replaygain.h"
33 #endif
34 #include "misc.h"
36 /* Skip an ID3v2 tag if it can be found. We assume the tag is located at the
37 * start of the file, which should be true in all cases where we need to skip it.
38 * Returns true if successfully skipped or not skipped, and false if
39 * something went wrong while skipping.
41 bool skip_id3v2(int fd, struct mp3entry *id3)
43 char buf[4];
45 read(fd, buf, 4);
46 if (memcmp(buf, "ID3", 3) == 0)
48 /* We have found an ID3v2 tag at the start of the file - find its
49 length and then skip it. */
50 if ((id3->first_frame_offset = getid3v2len(fd)) == 0)
51 return false;
53 if ((lseek(fd, id3->first_frame_offset, SEEK_SET) < 0))
54 return false;
56 return true;
57 } else {
58 lseek(fd, 0, SEEK_SET);
59 id3->first_frame_offset = 0;
60 return true;
65 /* Read a string from the file. Read up to size bytes, or, if eos != -1,
66 * until the eos character is found (eos is not stored in buf, unless it is
67 * nil). Writes up to buf_size chars to buf, always terminating with a nil.
68 * Returns number of chars read or -1 on read error.
70 long read_string(int fd, char* buf, long buf_size, int eos, long size)
72 long read_bytes = 0;
73 char c;
75 while (size != 0)
77 if (read(fd, &c, 1) != 1)
79 read_bytes = -1;
80 break;
83 read_bytes++;
84 size--;
86 if ((eos != -1) && (eos == (unsigned char) c))
88 break;
91 if (buf_size > 1)
93 *buf++ = c;
94 buf_size--;
98 *buf = 0;
99 return read_bytes;
101 /* Read an unsigned 8-bit integer from a file. */
102 int read_uint8(int fd, uint8_t* buf)
104 size_t n;
106 n = read(fd, (char*) buf, 1);
107 return n;
110 #ifdef ROCKBOX_LITTLE_ENDIAN
111 /* Read an unsigned 16-bit integer from a big-endian file. */
112 int read_uint16be(int fd, uint16_t* buf)
114 size_t n;
116 n = read(fd, (char*) buf, 2);
117 *buf = betoh16(*buf);
118 return n;
120 /* Read an unsigned 32-bit integer from a big-endian file. */
121 int read_uint32be(int fd, uint32_t* buf)
123 size_t n;
125 n = read(fd, (char*) buf, 4);
126 *buf = betoh32(*buf);
127 return n;
129 /* Read an unsigned 64-bit integer from a big-endian file. */
130 int read_uint64be(int fd, uint64_t* buf)
132 size_t n;
133 uint8_t data[8];
134 int i;
136 n = read(fd, data, 8);
138 for (i=0, *buf=0; i<=7; i++) {
139 *buf <<= 8;
140 *buf |= data[i];
142 return n;
144 #else
145 /* Read unsigned integers from a little-endian file. */
146 int read_uint16le(int fd, uint16_t* buf)
148 size_t n;
150 n = read(fd, (char*) buf, 2);
151 *buf = letoh16(*buf);
152 return n;
154 int read_uint32le(int fd, uint32_t* buf)
156 size_t n;
158 n = read(fd, (char*) buf, 4);
159 *buf = letoh32(*buf);
160 return n;
162 int read_uint64le(int fd, uint64_t* buf)
164 size_t n;
165 uint8_t data[8];
166 int i;
168 n = read(fd, data, 8);
170 for (i=7, *buf=0; i>=0; i--) {
171 *buf <<= 8;
172 *buf |= data[i];
175 return n;
177 #endif
179 /* Read an unaligned 64-bit little endian unsigned integer from buffer. */
180 uint64_t get_uint64_le(void* buf)
182 unsigned char* p = (unsigned char*) buf;
184 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24) | ((uint64_t)p[4] << 32) |
185 ((uint64_t)p[5] << 40) | ((uint64_t)p[6] << 48) | ((uint64_t)p[7] << 56);
188 /* Read an unaligned 32-bit little endian long from buffer. */
189 unsigned long get_long_le(void* buf)
191 unsigned char* p = (unsigned char*) buf;
193 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
196 /* Read an unaligned 16-bit little endian short from buffer. */
197 unsigned short get_short_le(void* buf)
199 unsigned char* p = (unsigned char*) buf;
201 return p[0] | (p[1] << 8);
204 /* Read an unaligned 32-bit big endian long from buffer. */
205 unsigned long get_long_be(void* buf)
207 unsigned char* p = (unsigned char*) buf;
209 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
212 /* Read an unaligned 32-bit little endian long from buffer. */
213 long get_slong(void* buf)
215 unsigned char* p = (unsigned char*) buf;
217 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
220 unsigned long get_itunes_int32(char* value, int count)
222 static const char hexdigits[] = "0123456789ABCDEF";
223 const char* c;
224 int r = 0;
226 while (count-- > 0)
228 value = skip_whitespace(value);
230 while (*value && !isspace(*value))
232 value++;
236 value = skip_whitespace(value);
238 while (*value && ((c = strchr(hexdigits, toupper(*value))) != NULL))
240 r = (r << 4) | (c - hexdigits);
241 value++;
244 return r;
247 /* Parse the tag (the name-value pair) and fill id3 and buffer accordingly.
248 * String values to keep are written to buf. Returns number of bytes written
249 * to buf (including end nil).
251 long parse_tag(const char* name, char* value, struct mp3entry* id3,
252 char* buf, long buf_remaining, enum tagtype type)
254 long len = 0;
255 char** p = NULL;
257 if ((((strcasecmp(name, "track") == 0) && (type == TAGTYPE_APE)))
258 || ((strcasecmp(name, "tracknumber") == 0) && (type == TAGTYPE_VORBIS)))
260 id3->tracknum = atoi(value);
261 p = &(id3->track_string);
263 else if (strcasecmp(name, "discnumber") == 0 || strcasecmp(name, "disc") == 0)
265 id3->discnum = atoi(value);
266 p = &(id3->disc_string);
268 else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE))
269 || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS)))
271 /* Date's can be in any format in Vorbis. However most of them
272 * are in ISO8601 format so if we try and parse the first part
273 * of the tag as a number, we should get the year. If we get crap,
274 * then act like we never parsed it.
276 id3->year = atoi(value);
277 if (id3->year < 1900)
278 { /* yeah, not likely */
279 id3->year = 0;
281 p = &(id3->year_string);
283 else if (strcasecmp(name, "title") == 0)
285 p = &(id3->title);
287 else if (strcasecmp(name, "artist") == 0)
289 p = &(id3->artist);
291 else if (strcasecmp(name, "album") == 0)
293 p = &(id3->album);
295 else if (strcasecmp(name, "genre") == 0)
297 p = &(id3->genre_string);
299 else if (strcasecmp(name, "composer") == 0)
301 p = &(id3->composer);
303 else if (strcasecmp(name, "comment") == 0)
305 p = &(id3->comment);
307 else if (strcasecmp(name, "albumartist") == 0)
309 p = &(id3->albumartist);
311 else if (strcasecmp(name, "album artist") == 0)
313 p = &(id3->albumartist);
315 else if (strcasecmp(name, "ensemble") == 0)
317 p = &(id3->albumartist);
319 else if (strcasecmp(name, "grouping") == 0)
321 p = &(id3->grouping);
323 else if (strcasecmp(name, "content group") == 0)
325 p = &(id3->grouping);
327 else if (strcasecmp(name, "contentgroup") == 0)
329 p = &(id3->grouping);
331 else if (strcasecmp(name, "musicbrainz_trackid") == 0
332 || strcasecmp(name, "http://musicbrainz.org") == 0 )
334 p = &(id3->mb_track_id);
336 #if CONFIG_CODEC == SWCODEC
337 else
339 len = parse_replaygain(name, value, id3, buf, buf_remaining);
340 p = NULL;
342 #endif
344 if (p)
346 len = strlen(value);
347 len = MIN(len, buf_remaining - 1);
349 if (len > 0)
351 len++;
352 strlcpy(buf, value, len);
353 *p = buf;
355 else
357 len = 0;
361 return len;