Fix FS#10197 by setting the viewport before calculating the string size.
[kugel-rb.git] / apps / metadata / asap.c
blob128a18d6426c686ac6ac2f82df5a8b789932228e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 Dominik Wenger
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.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 "rbunicode.h"
32 #include "debug.h"
34 #define MAX_SONGS 32
36 static bool parse_dec(int *retval, const char *p, int minval, int maxval)
38 int r = 0;
39 do {
40 char c = *p;
41 if (c >= '0' && c <= '9')
42 r = 10 * r + c - '0';
43 else
44 return false;
45 if (r > maxval)
46 return false;
47 } while (*++p != '\0');
48 if (r < minval)
49 return false;
50 *retval = r;
51 return true;
54 static bool parse_text(char *retval, const char *p)
56 int i;
57 if (*p != '"')
58 return false;
59 p++;
60 if (p[0] == '<' && p[1] == '?' && p[2] == '>' && p[3] == '"')
61 return true;
62 i = 0;
63 while (*p != '"') {
64 if (i >= 127)
65 return false;
66 if (*p == '\0')
67 return false;
68 retval[i++] = *p++;
70 retval[i] = '\0';
71 return true;
74 static int ASAP_ParseDuration(const char *s)
76 int r;
77 if (*s < '0' || *s > '9')
78 return -1;
79 r = *s++ - '0';
80 if (*s >= '0' && *s <= '9')
81 r = 10 * r + *s++ - '0';
82 if (*s == ':') {
83 s++;
84 if (*s < '0' || *s > '5')
85 return -1;
86 r = 60 * r + (*s++ - '0') * 10;
87 if (*s < '0' || *s > '9')
88 return -1;
89 r += *s++ - '0';
91 r *= 1000;
92 if (*s != '.')
93 return r;
94 s++;
95 if (*s < '0' || *s > '9')
96 return r;
97 r += 100 * (*s++ - '0');
98 if (*s < '0' || *s > '9')
99 return r;
100 r += 10 * (*s++ - '0');
101 if (*s < '0' || *s > '9')
102 return r;
103 r += *s - '0';
104 return r;
107 static bool read_asap_string(char* source,char** buf,char** buffer_end,char** dest)
109 if(parse_text(*buf,source) == false) return false;
111 /* set dest pointer */
112 *dest = *buf;
114 /* move buf ptr */
115 *buf += strlen(*buf)+1;
117 /* check size */
118 if(*buf >= *buffer_end)
120 DEBUGF("Buffer full\n");
121 return false;
123 return true;
126 static bool parse_sap_header(int fd,struct mp3entry* id3,int file_len)
128 int module_index = 0;
129 int sap_signature = -1;
130 int duration_index = 0;
131 unsigned char cur_char = 0;
132 int i;
134 /* set defaults */
135 int numSongs=1;
136 int defSong=0;
137 int numChannels=1;
138 int durations[MAX_SONGS];
139 int loops[MAX_SONGS];
140 for (i = 0; i < MAX_SONGS; i++) {
141 durations[i] = -1;
142 loops[i] = 0;
145 /* use id3v2 buffer for our strings */
146 char* buffer = id3->id3v2buf;
147 char* buffer_end = id3->id3v2buf + ID3V2_BUF_SIZE;
149 /* parse file */
150 while (1)
152 char line[256];
153 char *p;
155 if (module_index + 8 >= file_len)
156 return false;
157 /* read a char */
158 read(fd,&cur_char,1);
159 /* end of header */
160 if (cur_char == 0xff)
161 break;
163 i = 0;
164 while (cur_char != 0x0d)
166 line[i++] = cur_char;
167 module_index++;
168 if (module_index >= file_len || (unsigned)i >= sizeof(line) - 1)
169 return false;
170 /* read a char */
171 read(fd,&cur_char,1);
173 if (++module_index >= file_len )
174 return false;
175 /* read a char */
176 read(fd,&cur_char,1);
177 if ( cur_char != 0x0a)
178 return false;
180 line[i] = '\0';
181 for (p = line; *p != '\0'; p++) {
182 if (*p == ' ') {
183 *p++ = '\0';
184 break;
188 /* parse tags */
189 if(strcmp(line, "SAP") == 0)
190 sap_signature = 1;
191 if (sap_signature == -1)
192 return false;
193 if (strcmp(line,"AUTHOR") == 0)
195 if(read_asap_string(p,&buffer,&buffer_end,&id3->artist) == false)
196 return false;
198 else if(strcmp(line,"NAME")==0)
200 if(read_asap_string(p,&buffer,&buffer_end,&id3->title) == false)
201 return false;
203 else if(strcmp(line,"DATE")==0)
205 if(read_asap_string(p,&buffer,&buffer_end,&id3->year_string) == false)
206 return false;
208 else if (strcmp(line,"SONGS")==0)
210 if (parse_dec(&numSongs, p,1,MAX_SONGS) == false )
211 return false;
213 else if (strcmp(line,"DEFSONG")==0)
215 if (parse_dec(&defSong, p,0,MAX_SONGS) == false)
216 return false;
218 else if (strcmp(line,"STEREO")==0)
220 numChannels = 2;
222 else if (strcmp(line,"TIME") == 0)
224 int durationTemp = ASAP_ParseDuration(p);
225 if (durationTemp < 0 || duration_index >= MAX_SONGS)
226 return false;
227 durations[duration_index] = durationTemp;
228 if (strstr(p, "LOOP") != NULL)
229 loops[duration_index] = 1;
230 duration_index++;
234 /* set length: */
235 int length = durations[defSong];
236 if (length < 0)
237 length = 180 * 1000;
238 id3->length = length;
240 lseek(fd,0,SEEK_SET);
241 return true;
245 bool get_asap_metadata(int fd, struct mp3entry* id3)
248 int filelength = filesize(fd);
250 if(parse_sap_header(fd,id3,filelength) == false)
252 DEBUGF("parse sap header failed.\n");
253 return false;
256 id3->bitrate = 706;
257 id3->frequency = 44100;
259 id3->vbr = false;
260 id3->filesize = filelength;
262 return true;