summaryrefslogtreecommitdiff
path: root/lib/rbcodec/metadata/asap.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/metadata/asap.c')
-rw-r--r--lib/rbcodec/metadata/asap.c254
1 files changed, 254 insertions, 0 deletions
diff --git a/lib/rbcodec/metadata/asap.c b/lib/rbcodec/metadata/asap.c
new file mode 100644
index 0000000000..9e7f227031
--- /dev/null
+++ b/lib/rbcodec/metadata/asap.c
@@ -0,0 +1,254 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 Dominik Wenger
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.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 "rbunicode.h"
32#include "debug.h"
33
34#define MAX_SONGS 32
35
36static bool parse_dec(int *retval, const char *p, int minval, int maxval)
37{
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;
52}
53
54static bool parse_text(char *retval, const char *p)
55{
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++;
69 }
70 retval[i] = '\0';
71 return true;
72}
73
74static int ASAP_ParseDuration(const char *s)
75{
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';
90 }
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;
105}
106
107static bool read_asap_string(char* source, char** buf, char** buffer_end, char** dest)
108{
109 if(parse_text(*buf,source) == false)
110 return false;
111
112 /* set dest pointer */
113 *dest = *buf;
114
115 /* move buf ptr */
116 *buf += strlen(*buf)+1;
117
118 /* check size */
119 if(*buf >= *buffer_end)
120 {
121 DEBUGF("Buffer full\n");
122 return false;
123 }
124 return true;
125}
126
127static bool parse_sap_header(int fd, struct mp3entry* id3, int file_len)
128{
129 int module_index = 0;
130 int sap_signature = -1;
131 int duration_index = 0;
132 unsigned char cur_char = 0;
133 int i;
134
135 /* set defaults */
136 int numSongs = 1;
137 int defSong = 0;
138 int durations[MAX_SONGS];
139 for (i = 0; i < MAX_SONGS; i++)
140 durations[i] = -1;
141
142 /* use id3v2 buffer for our strings */
143 char* buffer = id3->id3v2buf;
144 char* buffer_end = id3->id3v2buf + ID3V2_BUF_SIZE;
145
146 /* parse file */
147 while (1)
148 {
149 char line[256];
150 char *p;
151
152 if (module_index + 8 >= file_len)
153 return false;
154 /* read a char */
155 read(fd,&cur_char,1);
156 /* end of header */
157 if (cur_char == 0xff)
158 break;
159
160 i = 0;
161 while (cur_char != 0x0d)
162 {
163 line[i++] = cur_char;
164 module_index++;
165 if (module_index >= file_len || (unsigned)i >= sizeof(line) - 1)
166 return false;
167 /* read a char */
168 read(fd,&cur_char,1);
169 }
170 if (++module_index >= file_len )
171 return false;
172 /* read a char */
173 read(fd,&cur_char,1);
174 if ( cur_char != 0x0a)
175 return false;
176
177 line[i] = '\0';
178 for (p = line; *p != '\0'; p++) {
179 if (*p == ' ') {
180 *p++ = '\0';
181 break;
182 }
183 }
184
185 /* parse tags */
186 if(strcmp(line, "SAP") == 0)
187 sap_signature = 1;
188 if (sap_signature == -1)
189 return false;
190 if (strcmp(line, "AUTHOR") == 0)
191 {
192 if(read_asap_string(p, &buffer, &buffer_end, &id3->artist) == false)
193 return false;
194 }
195 else if(strcmp(line, "NAME") == 0)
196 {
197 if(read_asap_string(p, &buffer, &buffer_end, &id3->title) == false)
198 return false;
199 }
200 else if(strcmp(line, "DATE") == 0)
201 {
202 if(read_asap_string(p, &buffer, &buffer_end, &id3->year_string) == false)
203 return false;
204 }
205 else if (strcmp(line, "SONGS") == 0)
206 {
207 if (parse_dec(&numSongs, p, 1, MAX_SONGS) == false )
208 return false;
209 }
210 else if (strcmp(line, "DEFSONG") == 0)
211 {
212 if (parse_dec(&defSong, p, 0, MAX_SONGS) == false)
213 return false;
214 }
215 else if (strcmp(line, "TIME") == 0)
216 {
217 int durationTemp = ASAP_ParseDuration(p);
218 if (durationTemp < 0 || duration_index >= MAX_SONGS)
219 return false;
220 durations[duration_index++] = durationTemp;
221 }
222 }
223
224 /* set length: */
225 int length = durations[defSong];
226 if (length < 0)
227 length = 180 * 1000;
228 id3->length = length;
229
230 lseek(fd, 0, SEEK_SET);
231 return true;
232}
233
234
235bool get_asap_metadata(int fd, struct mp3entry* id3)
236{
237
238 int filelength = filesize(fd);
239
240 if(parse_sap_header(fd, id3, filelength) == false)
241 {
242 DEBUGF("parse sap header failed.\n");
243 return false;
244 }
245
246 id3->bitrate = 706;
247 id3->frequency = 44100;
248
249 id3->vbr = false;
250 id3->filesize = filelength;
251 id3->genre_string = id3_get_num_genre(36);
252
253 return true;
254}