diff options
author | Dominik Wenger <domonoky@googlemail.com> | 2008-07-26 15:16:10 +0000 |
---|---|---|
committer | Dominik Wenger <domonoky@googlemail.com> | 2008-07-26 15:16:10 +0000 |
commit | 25bb37bb6851c85e21fb0cecfd9617eebe6c7a56 (patch) | |
tree | 14800e46724f8fa90c2ea1cb7100ac89423cde4e /apps/metadata/asap.c | |
parent | 4e4bf82fb756f36dca6af333357a54e09b9f4cca (diff) | |
download | rockbox-25bb37bb6851c85e21fb0cecfd9617eebe6c7a56.tar.gz rockbox-25bb37bb6851c85e21fb0cecfd9617eebe6c7a56.zip |
commit asap codec. plays .sap files. At the moment it only plays the default song. So subSongs are ignored.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18121 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/metadata/asap.c')
-rw-r--r-- | apps/metadata/asap.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/apps/metadata/asap.c b/apps/metadata/asap.c new file mode 100644 index 0000000000..7e635a30e8 --- /dev/null +++ b/apps/metadata/asap.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: asap.c 17847 2008-06-28 18:10:04Z domonoky $ | ||
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 "id3.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 | |||
36 | struct module_info | ||
37 | { | ||
38 | char name[255]; | ||
39 | char author[255]; | ||
40 | char date[255]; | ||
41 | int numSongs; | ||
42 | int defSong; | ||
43 | int numChannels; | ||
44 | int durations[32]; | ||
45 | int loops[32]; | ||
46 | }; | ||
47 | |||
48 | static bool parse_dec(int *retval, const char *p, int minval, int maxval) | ||
49 | { | ||
50 | int r = 0; | ||
51 | do { | ||
52 | char c = *p; | ||
53 | if (c >= '0' && c <= '9') | ||
54 | r = 10 * r + c - '0'; | ||
55 | else | ||
56 | return false; | ||
57 | if (r > maxval) | ||
58 | return false; | ||
59 | } while (*++p != '\0'); | ||
60 | if (r < minval) | ||
61 | return false; | ||
62 | *retval = r; | ||
63 | return true; | ||
64 | } | ||
65 | |||
66 | static bool parse_text(char *retval, const char *p) | ||
67 | { | ||
68 | int i; | ||
69 | if (*p != '"') | ||
70 | return false; | ||
71 | p++; | ||
72 | if (p[0] == '<' && p[1] == '?' && p[2] == '>' && p[3] == '"') | ||
73 | return true; | ||
74 | i = 0; | ||
75 | while (*p != '"') { | ||
76 | if (i >= 127) | ||
77 | return false; | ||
78 | if (*p == '\0') | ||
79 | return false; | ||
80 | retval[i++] = *p++; | ||
81 | } | ||
82 | retval[i] = '\0'; | ||
83 | return true; | ||
84 | } | ||
85 | |||
86 | static int ASAP_ParseDuration(const char *s) | ||
87 | { | ||
88 | int r; | ||
89 | if (*s < '0' || *s > '9') | ||
90 | return -1; | ||
91 | r = *s++ - '0'; | ||
92 | if (*s >= '0' && *s <= '9') | ||
93 | r = 10 * r + *s++ - '0'; | ||
94 | if (*s == ':') { | ||
95 | s++; | ||
96 | if (*s < '0' || *s > '5') | ||
97 | return -1; | ||
98 | r = 60 * r + (*s++ - '0') * 10; | ||
99 | if (*s < '0' || *s > '9') | ||
100 | return -1; | ||
101 | r += *s++ - '0'; | ||
102 | } | ||
103 | r *= 1000; | ||
104 | if (*s != '.') | ||
105 | return r; | ||
106 | s++; | ||
107 | if (*s < '0' || *s > '9') | ||
108 | return r; | ||
109 | r += 100 * (*s++ - '0'); | ||
110 | if (*s < '0' || *s > '9') | ||
111 | return r; | ||
112 | r += 10 * (*s++ - '0'); | ||
113 | if (*s < '0' || *s > '9') | ||
114 | return r; | ||
115 | r += *s - '0'; | ||
116 | return r; | ||
117 | } | ||
118 | |||
119 | static bool parse_sap_header(int fd,struct module_info* info,int file_len) | ||
120 | { | ||
121 | int module_index = 0; | ||
122 | int sap_signature = -1; | ||
123 | int duration_index = 0; | ||
124 | unsigned char cur_char = 0; | ||
125 | int i; | ||
126 | |||
127 | /* set defaults */ | ||
128 | |||
129 | info->numSongs=1; | ||
130 | info->defSong=0; | ||
131 | info->numChannels=1; | ||
132 | for (i = 0; i < MAX_SONGS; i++) { | ||
133 | info->durations[i] = -1; | ||
134 | info->loops[i] = 0; | ||
135 | } | ||
136 | |||
137 | /* parse file */ | ||
138 | while (1) | ||
139 | { | ||
140 | char line[256]; | ||
141 | char *p; | ||
142 | |||
143 | if (module_index + 8 >= file_len) | ||
144 | return false; | ||
145 | /* read a char */ | ||
146 | read(fd,&cur_char,1); | ||
147 | /* end of header */ | ||
148 | if (cur_char == 0xff) | ||
149 | break; | ||
150 | |||
151 | i = 0; | ||
152 | while (cur_char != 0x0d) | ||
153 | { | ||
154 | line[i++] = cur_char; | ||
155 | module_index++; | ||
156 | if (module_index >= file_len || (unsigned)i >= sizeof(line) - 1) | ||
157 | return false; | ||
158 | /* read a char */ | ||
159 | read(fd,&cur_char,1); | ||
160 | } | ||
161 | if (++module_index >= file_len ) | ||
162 | return false; | ||
163 | /* read a char */ | ||
164 | read(fd,&cur_char,1); | ||
165 | if ( cur_char != 0x0a) | ||
166 | return false; | ||
167 | |||
168 | line[i] = '\0'; | ||
169 | for (p = line; *p != '\0'; p++) { | ||
170 | if (*p == ' ') { | ||
171 | *p++ = '\0'; | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | |||
176 | /* parse tags */ | ||
177 | if(strcmp(line, "SAP") == 0) | ||
178 | sap_signature = 1; | ||
179 | if (sap_signature == -1) | ||
180 | return false; | ||
181 | if (strcmp(line,"AUTHOR") == 0) | ||
182 | { | ||
183 | if (parse_text(info->author, p) == false ) | ||
184 | return false; | ||
185 | } | ||
186 | else if(strcmp(line,"NAME")==0) | ||
187 | { | ||
188 | if (parse_text(info->name, p) == false) | ||
189 | return false; | ||
190 | } | ||
191 | else if(strcmp(line,"DATE")==0) | ||
192 | { | ||
193 | if (parse_text(info->date, p) == false) | ||
194 | return false; | ||
195 | } | ||
196 | else if (strcmp(line,"SONGS")==0) | ||
197 | { | ||
198 | if (parse_dec(&info->numSongs, p,1,MAX_SONGS) == false ) | ||
199 | return false; | ||
200 | } | ||
201 | else if (strcmp(line,"DEFSONG")==0) | ||
202 | { | ||
203 | if (parse_dec(&info->defSong, p,0,MAX_SONGS) == false) | ||
204 | return false; | ||
205 | } | ||
206 | else if (strcmp(line,"STEREO")==0) | ||
207 | { | ||
208 | info->numChannels = 2; | ||
209 | } | ||
210 | else if (strcmp(line,"TIME") == 0) | ||
211 | { | ||
212 | int duration = ASAP_ParseDuration(p); | ||
213 | if (duration < 0 || duration_index >= MAX_SONGS) | ||
214 | return false; | ||
215 | info->durations[duration_index] = duration; | ||
216 | if (strstr(p, "LOOP") != NULL) | ||
217 | info->loops[duration_index] = 1; | ||
218 | duration_index++; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | lseek(fd,0,SEEK_SET); | ||
223 | return true; | ||
224 | } | ||
225 | |||
226 | |||
227 | bool get_asap_metadata(int fd, struct mp3entry* id3) | ||
228 | { | ||
229 | char *buf = id3->id3v2buf; | ||
230 | |||
231 | int filelength = filesize(fd); | ||
232 | struct module_info *info; | ||
233 | info = (struct module_info *) buf; | ||
234 | |||
235 | if(parse_sap_header(fd,info,filelength) == false) | ||
236 | { | ||
237 | DEBUGF("parse sap header failed.\n"); | ||
238 | return false; | ||
239 | } | ||
240 | |||
241 | id3->title = info->name; | ||
242 | id3->artist = info->author; | ||
243 | id3->year_string = info->date; | ||
244 | int length = info->durations[info->defSong]; | ||
245 | if (length < 0) | ||
246 | length = 180 * 1000; | ||
247 | id3->length = length; | ||
248 | |||
249 | id3->bitrate = 706; | ||
250 | id3->frequency = 44100; | ||
251 | |||
252 | id3->vbr = false; | ||
253 | id3->filesize = filelength; | ||
254 | |||
255 | return true; | ||
256 | } | ||