Fix red. read_uint32be() was not implemented in sim builds for HWCODEC targets.
[kugel-rb.git] / apps / metadata / metadata_common.c
blobbde48d423bc7cc5b2c051132f526f516e2a0b10c
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 #include "replaygain.h"
32 #include "misc.h"
34 /* Read a string from the file. Read up to size bytes, or, if eos != -1,
35 * until the eos character is found (eos is not stored in buf, unless it is
36 * nil). Writes up to buf_size chars to buf, always terminating with a nil.
37 * Returns number of chars read or -1 on read error.
39 long read_string(int fd, char* buf, long buf_size, int eos, long size)
41 long read_bytes = 0;
42 char c;
44 while (size != 0)
46 if (read(fd, &c, 1) != 1)
48 read_bytes = -1;
49 break;
52 read_bytes++;
53 size--;
55 if ((eos != -1) && (eos == (unsigned char) c))
57 break;
60 if (buf_size > 1)
62 *buf++ = c;
63 buf_size--;
67 *buf = 0;
68 return read_bytes;
70 /* Read an unsigned 8-bit integer from a file. */
71 int read_uint8(int fd, uint8_t* buf)
73 size_t n;
75 n = read(fd, (char*) buf, 1);
76 return n;
79 #ifdef ROCKBOX_LITTLE_ENDIAN
80 /* Read an unsigned 16-bit integer from a big-endian file. */
81 int read_uint16be(int fd, uint16_t* buf)
83 size_t n;
85 n = read(fd, (char*) buf, 2);
86 *buf = betoh16(*buf);
87 return n;
89 /* Read an unsigned 32-bit integer from a big-endian file. */
90 int read_uint32be(int fd, uint32_t* buf)
92 size_t n;
94 n = read(fd, (char*) buf, 4);
95 *buf = betoh32(*buf);
96 return n;
98 /* Read an unsigned 64-bit integer from a big-endian file. */
99 int read_uint64be(int fd, uint64_t* buf)
101 size_t n;
102 uint8_t data[8];
103 int i;
105 n = read(fd, data, 8);
107 for (i=0, *buf=0; i<=7; i++) {
108 *buf <<= 8;
109 *buf |= data[i];
111 return n;
113 #else
114 /* Read unsigned integers from a little-endian file. */
115 int read_uint16le(int fd, uint16_t* buf)
117 size_t n;
119 n = read(fd, (char*) buf, 2);
120 *buf = letoh16(*buf);
121 return n;
123 int read_uint32le(int fd, uint32_t* buf)
125 size_t n;
127 n = read(fd, (char*) buf, 4);
128 *buf = letoh32(*buf);
129 return n;
131 int read_uint64le(int fd, uint64_t* buf)
133 size_t n;
134 uint8_t data[8];
135 int i;
137 n = read(fd, data, 8);
139 for (i=7, *buf=0; i>=0; i--) {
140 *buf <<= 8;
141 *buf |= data[i];
144 return n;
146 #endif
148 /* Read an unaligned 64-bit little endian unsigned integer from buffer. */
149 uint64_t get_uint64_le(void* buf)
151 unsigned char* p = (unsigned char*) buf;
153 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24) | ((uint64_t)p[4] << 32) |
154 ((uint64_t)p[5] << 40) | ((uint64_t)p[6] << 48) | ((uint64_t)p[7] << 56);
157 /* Read an unaligned 32-bit little endian long from buffer. */
158 unsigned long get_long_le(void* buf)
160 unsigned char* p = (unsigned char*) buf;
162 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
165 /* Read an unaligned 16-bit little endian short from buffer. */
166 unsigned short get_short_le(void* buf)
168 unsigned char* p = (unsigned char*) buf;
170 return p[0] | (p[1] << 8);
173 /* Read an unaligned 32-bit big endian long from buffer. */
174 unsigned long get_long_be(void* buf)
176 unsigned char* p = (unsigned char*) buf;
178 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
181 /* Read an unaligned 32-bit little endian long from buffer. */
182 long get_slong(void* buf)
184 unsigned char* p = (unsigned char*) buf;
186 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
189 unsigned long get_itunes_int32(char* value, int count)
191 static const char hexdigits[] = "0123456789ABCDEF";
192 const char* c;
193 int r = 0;
195 while (count-- > 0)
197 value = skip_whitespace(value);
199 while (*value && !isspace(*value))
201 value++;
205 value = skip_whitespace(value);
207 while (*value && ((c = strchr(hexdigits, toupper(*value))) != NULL))
209 r = (r << 4) | (c - hexdigits);
210 value++;
213 return r;
216 #if CONFIG_CODEC == SWCODEC
217 /* Skip an ID3v2 tag if it can be found. We assume the tag is located at the
218 * start of the file, which should be true in all cases where we need to skip it.
219 * Returns true if successfully skipped or not skipped, and false if
220 * something went wrong while skipping.
222 bool skip_id3v2(int fd, struct mp3entry *id3)
224 char buf[4];
226 read(fd, buf, 4);
227 if (memcmp(buf, "ID3", 3) == 0)
229 /* We have found an ID3v2 tag at the start of the file - find its
230 length and then skip it. */
231 if ((id3->first_frame_offset = getid3v2len(fd)) == 0)
232 return false;
234 if ((lseek(fd, id3->first_frame_offset, SEEK_SET) < 0))
235 return false;
237 return true;
238 } else {
239 lseek(fd, 0, SEEK_SET);
240 id3->first_frame_offset = 0;
241 return true;
245 /* Parse the tag (the name-value pair) and fill id3 and buffer accordingly.
246 * String values to keep are written to buf. Returns number of bytes written
247 * to buf (including end nil).
249 long parse_tag(const char* name, char* value, struct mp3entry* id3,
250 char* buf, long buf_remaining, enum tagtype type)
252 long len = 0;
253 char** p;
255 if ((((strcasecmp(name, "track") == 0) && (type == TAGTYPE_APE)))
256 || ((strcasecmp(name, "tracknumber") == 0) && (type == TAGTYPE_VORBIS)))
258 id3->tracknum = atoi(value);
259 p = &(id3->track_string);
261 else if (strcasecmp(name, "discnumber") == 0 || strcasecmp(name, "disc") == 0)
263 id3->discnum = atoi(value);
264 p = &(id3->disc_string);
266 else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE))
267 || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS)))
269 /* Date's can be in any format in Vorbis. However most of them
270 * are in ISO8601 format so if we try and parse the first part
271 * of the tag as a number, we should get the year. If we get crap,
272 * then act like we never parsed it.
274 id3->year = atoi(value);
275 if (id3->year < 1900)
276 { /* yeah, not likely */
277 id3->year = 0;
279 p = &(id3->year_string);
281 else if (strcasecmp(name, "title") == 0)
283 p = &(id3->title);
285 else if (strcasecmp(name, "artist") == 0)
287 p = &(id3->artist);
289 else if (strcasecmp(name, "album") == 0)
291 p = &(id3->album);
293 else if (strcasecmp(name, "genre") == 0)
295 p = &(id3->genre_string);
297 else if (strcasecmp(name, "composer") == 0)
299 p = &(id3->composer);
301 else if (strcasecmp(name, "comment") == 0)
303 p = &(id3->comment);
305 else if (strcasecmp(name, "albumartist") == 0)
307 p = &(id3->albumartist);
309 else if (strcasecmp(name, "album artist") == 0)
311 p = &(id3->albumartist);
313 else if (strcasecmp(name, "ensemble") == 0)
315 p = &(id3->albumartist);
317 else if (strcasecmp(name, "grouping") == 0)
319 p = &(id3->grouping);
321 else if (strcasecmp(name, "content group") == 0)
323 p = &(id3->grouping);
325 else if (strcasecmp(name, "contentgroup") == 0)
327 p = &(id3->grouping);
329 else if (strcasecmp(name, "musicbrainz_trackid") == 0
330 || strcasecmp(name, "http://musicbrainz.org") == 0 )
332 p = &(id3->mb_track_id);
334 else
336 parse_replaygain(name, value, id3);
337 p = NULL;
340 /* Do not overwrite already available metadata. Especially when reading
341 * tags with e.g. multiple genres / artists. This way only the first
342 * of multiple entries is used, all following are dropped. */
343 if (p!=NULL && *p==NULL)
345 len = strlen(value);
346 len = MIN(len, buf_remaining - 1);
347 len = MIN(len, ID3V2_MAX_ITEM_SIZE); /* Limit max. item size. */
349 if (len > 0)
351 len++;
352 strlcpy(buf, value, len);
353 *p = buf;
355 else
357 len = 0;
361 return len;
363 #endif