make sure closing the application aborts the remaining HttpGet objects. Should fix...
[Rockbox.git] / apps / metadata / metadata_common.c
blobe3579473f0eeb0ad8d9aeb106d17b3a764c029d9
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <inttypes.h>
25 #include "system.h"
26 #include "id3.h"
27 #include "metadata_common.h"
28 #include "replaygain.h"
29 #include "atoi.h"
31 /* Skip an ID3v2 tag if it can be found. We assume the tag is located at the
32 * start of the file, which should be true in all cases where we need to skip it.
33 * Returns true if successfully skipped or not skipped, and false if
34 * something went wrong while skipping.
36 bool skip_id3v2(int fd, struct mp3entry *id3)
38 char buf[4];
40 read(fd, buf, 4);
41 if (memcmp(buf, "ID3", 3) == 0)
43 /* We have found an ID3v2 tag at the start of the file - find its
44 length and then skip it. */
45 if ((id3->first_frame_offset = getid3v2len(fd)) == 0)
46 return false;
48 if ((lseek(fd, id3->first_frame_offset, SEEK_SET) < 0))
49 return false;
51 return true;
52 } else {
53 lseek(fd, 0, SEEK_SET);
54 id3->first_frame_offset = 0;
55 return true;
60 /* Read a string from the file. Read up to size bytes, or, if eos != -1,
61 * until the eos character is found (eos is not stored in buf, unless it is
62 * nil). Writes up to buf_size chars to buf, always terminating with a nil.
63 * Returns number of chars read or -1 on read error.
65 long read_string(int fd, char* buf, long buf_size, int eos, long size)
67 long read_bytes = 0;
68 char c;
70 while (size != 0)
72 if (read(fd, &c, 1) != 1)
74 read_bytes = -1;
75 break;
78 read_bytes++;
79 size--;
81 if ((eos != -1) && (eos == (unsigned char) c))
83 break;
86 if (buf_size > 1)
88 *buf++ = c;
89 buf_size--;
93 *buf = 0;
94 return read_bytes;
97 #ifdef ROCKBOX_LITTLE_ENDIAN
98 /* Read an unsigned 32-bit integer from a big-endian file. */
99 int read_uint32be(int fd, unsigned int* buf)
101 size_t n;
103 n = read(fd, (char*) buf, 4);
104 *buf = betoh32(*buf);
105 return n;
107 #else
108 /* Read unsigned integers from a little-endian file. */
109 int read_uint16le(int fd, uint16_t* buf)
111 size_t n;
113 n = read(fd, (char*) buf, 2);
114 *buf = letoh16(*buf);
115 return n;
117 int read_uint32le(int fd, uint32_t* buf)
119 size_t n;
121 n = read(fd, (char*) buf, 4);
122 *buf = letoh32(*buf);
123 return n;
125 int read_uint64le(int fd, uint64_t* buf)
127 size_t n;
128 uint8_t data[8];
129 int i;
131 n = read(fd, data, 8);
133 for (i=7, *buf=0; i>=0; i--) {
134 *buf <<= 8;
135 *buf |= data[i];
138 return n;
140 #endif
142 /* Read an unaligned 32-bit little endian long from buffer. */
143 unsigned long get_long_le(void* buf)
145 unsigned char* p = (unsigned char*) buf;
147 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
150 /* Read an unaligned 16-bit little endian short from buffer. */
151 unsigned short get_short_le(void* buf)
153 unsigned char* p = (unsigned char*) buf;
155 return p[0] | (p[1] << 8);
158 /* Read an unaligned 32-bit big endian long from buffer. */
159 unsigned long get_long_be(void* buf)
161 unsigned char* p = (unsigned char*) buf;
163 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
166 /* Read an unaligned 32-bit little endian long from buffer. */
167 long get_slong(void* buf)
169 unsigned char* p = (unsigned char*) buf;
171 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
174 static char* skip_space(char* str)
176 while (isspace(*str))
178 str++;
181 return str;
184 unsigned long get_itunes_int32(char* value, int count)
186 static const char hexdigits[] = "0123456789ABCDEF";
187 const char* c;
188 int r = 0;
190 while (count-- > 0)
192 value = skip_space(value);
194 while (*value && !isspace(*value))
196 value++;
200 value = skip_space(value);
202 while (*value && ((c = strchr(hexdigits, toupper(*value))) != NULL))
204 r = (r << 4) | (c - hexdigits);
205 value++;
208 return r;
211 /* Parse the tag (the name-value pair) and fill id3 and buffer accordingly.
212 * String values to keep are written to buf. Returns number of bytes written
213 * to buf (including end nil).
215 long parse_tag(const char* name, char* value, struct mp3entry* id3,
216 char* buf, long buf_remaining, enum tagtype type)
218 long len = 0;
219 char** p;
221 if ((((strcasecmp(name, "track") == 0) && (type == TAGTYPE_APE)))
222 || ((strcasecmp(name, "tracknumber") == 0) && (type == TAGTYPE_VORBIS)))
224 id3->tracknum = atoi(value);
225 p = &(id3->track_string);
227 else if (strcasecmp(name, "discnumber") == 0 || strcasecmp(name, "disc") == 0)
229 id3->discnum = atoi(value);
230 p = &(id3->disc_string);
232 else if (((strcasecmp(name, "year") == 0) && (type == TAGTYPE_APE))
233 || ((strcasecmp(name, "date") == 0) && (type == TAGTYPE_VORBIS)))
235 /* Date's can be in any format in Vorbis. However most of them
236 * are in ISO8601 format so if we try and parse the first part
237 * of the tag as a number, we should get the year. If we get crap,
238 * then act like we never parsed it.
240 id3->year = atoi(value);
241 if (id3->year < 1900)
242 { /* yeah, not likely */
243 id3->year = 0;
245 p = &(id3->year_string);
247 else if (strcasecmp(name, "title") == 0)
249 p = &(id3->title);
251 else if (strcasecmp(name, "artist") == 0)
253 p = &(id3->artist);
255 else if (strcasecmp(name, "album") == 0)
257 p = &(id3->album);
259 else if (strcasecmp(name, "genre") == 0)
261 p = &(id3->genre_string);
263 else if (strcasecmp(name, "composer") == 0)
265 p = &(id3->composer);
267 else if (strcasecmp(name, "comment") == 0)
269 p = &(id3->comment);
271 else if (strcasecmp(name, "albumartist") == 0)
273 p = &(id3->albumartist);
275 else if (strcasecmp(name, "album artist") == 0)
277 p = &(id3->albumartist);
279 else if (strcasecmp(name, "ensemble") == 0)
281 p = &(id3->albumartist);
283 else if (strcasecmp(name, "grouping") == 0)
285 p = &(id3->grouping);
287 else if (strcasecmp(name, "content group") == 0)
289 p = &(id3->grouping);
291 else if (strcasecmp(name, "contentgroup") == 0)
293 p = &(id3->grouping);
295 else
297 len = parse_replaygain(name, value, id3, buf, buf_remaining);
298 p = NULL;
301 if (p)
303 len = strlen(value);
304 len = MIN(len, buf_remaining - 1);
306 if (len > 0)
308 strncpy(buf, value, len);
309 buf[len] = 0;
310 *p = buf;
311 len++;
313 else
315 len = 0;
319 return len;