summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2008-10-10 13:12:28 +0000
committerBjörn Stenberg <bjorn@haxx.se>2008-10-10 13:12:28 +0000
commite76c69f3e4b9075db979145a60157d8cd968f537 (patch)
tree84ac8d57c687d1fdd10d8f205aa83a048edfd875 /apps
parent98fa3913f9618a09269e9ab39abb9a53274f5676 (diff)
downloadrockbox-e76c69f3e4b9075db979145a60157d8cd968f537.tar.gz
rockbox-e76c69f3e4b9075db979145a60157d8cd968f537.zip
Moved id3.c, mpeg.c and replaygain.c from firmware/ to apps/. This is the first step in separating the generic metadata code and the id3-specific code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@18760 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/SOURCES4
-rw-r--r--apps/id3.c1353
-rw-r--r--apps/mpeg.c2873
-rw-r--r--apps/replaygain.c457
4 files changed, 4687 insertions, 0 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index eb09797719..7622b416f7 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -7,6 +7,7 @@ abrepeat.c
7bookmark.c 7bookmark.c
8debug_menu.c 8debug_menu.c
9filetypes.c 9filetypes.c
10id3.c
10language.c 11language.c
11main.c 12main.c
12menu.c 13menu.c
@@ -17,6 +18,9 @@ menus/theme_menu.c
17menus/eq_menu.c 18menus/eq_menu.c
18buffering.c 19buffering.c
19voice_thread.c 20voice_thread.c
21replaygain.c
22#else /* !SWCODEC */
23mpeg.c
20#endif 24#endif
21menus/main_menu.c 25menus/main_menu.c
22menus/playback_menu.c 26menus/playback_menu.c
diff --git a/apps/id3.c b/apps/id3.c
new file mode 100644
index 0000000000..c1541e30df
--- /dev/null
+++ b/apps/id3.c
@@ -0,0 +1,1353 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Daniel Stenberg
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/*
22 * Parts of this code has been stolen from the Ample project and was written
23 * by David H�deman. It has since been extended and enhanced pretty much by
24 * all sorts of friendly Rockbox people.
25 *
26 */
27
28 /* tagResolver and associated code copyright 2003 Thomas Paul Diffenbach
29 */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <errno.h>
35#include <stdbool.h>
36#include <stddef.h>
37#include <ctype.h>
38#include "config.h"
39#include "file.h"
40#include "logf.h"
41
42#include "id3.h"
43#include "mp3data.h"
44#include "system.h"
45#include "replaygain.h"
46#include "rbunicode.h"
47
48/** Database of audio formats **/
49const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
50{
51 /* Unknown file format */
52 [AFMT_UNKNOWN] =
53 AFMT_ENTRY("???", NULL, NULL, NULL ),
54
55 /* MPEG Audio layer 1 */
56 [AFMT_MPA_L1] =
57 AFMT_ENTRY("MP1", "mpa", NULL, "mp1\0" ),
58 /* MPEG Audio layer 2 */
59 [AFMT_MPA_L2] =
60 AFMT_ENTRY("MP2", "mpa", NULL, "mpa\0mp2\0" ),
61 /* MPEG Audio layer 3 */
62 [AFMT_MPA_L3] =
63 AFMT_ENTRY("MP3", "mpa", "mp3_enc", "mp3\0" ),
64
65#if CONFIG_CODEC == SWCODEC
66 /* Audio Interchange File Format */
67 [AFMT_AIFF] =
68 AFMT_ENTRY("AIFF", "aiff", "aiff_enc", "aiff\0aif\0"),
69 /* Uncompressed PCM in a WAV file */
70 [AFMT_PCM_WAV] =
71 AFMT_ENTRY("WAV", "wav", "wav_enc", "wav\0" ),
72 /* Ogg Vorbis */
73 [AFMT_OGG_VORBIS] =
74 AFMT_ENTRY("Ogg", "vorbis", NULL, "ogg\0" ),
75 /* FLAC */
76 [AFMT_FLAC] =
77 AFMT_ENTRY("FLAC", "flac", NULL, "flac\0" ),
78 /* Musepack */
79 [AFMT_MPC] =
80 AFMT_ENTRY("MPC", "mpc", NULL, "mpc\0" ),
81 /* A/52 (aka AC3) audio */
82 [AFMT_A52] =
83 AFMT_ENTRY("AC3", "a52", NULL, "a52\0ac3\0" ),
84 /* WavPack */
85 [AFMT_WAVPACK] =
86 AFMT_ENTRY("WV", "wavpack", "wavpack_enc", "wv\0" ),
87 /* Apple Lossless Audio Codec */
88 [AFMT_ALAC] =
89 AFMT_ENTRY("ALAC", "alac", NULL, "m4a\0m4b\0" ),
90 /* Advanced Audio Coding in M4A container */
91 [AFMT_AAC] =
92 AFMT_ENTRY("AAC", "aac", NULL, "mp4\0" ),
93 /* Shorten */
94 [AFMT_SHN] =
95 AFMT_ENTRY("SHN", "shorten", NULL, "shn\0" ),
96 /* SID File Format */
97 [AFMT_SID] =
98 AFMT_ENTRY("SID", "sid", NULL, "sid\0" ),
99 /* ADX File Format */
100 [AFMT_ADX] =
101 AFMT_ENTRY("ADX", "adx", NULL, "adx\0" ),
102 /* NESM (NES Sound Format) */
103 [AFMT_NSF] =
104 AFMT_ENTRY("NSF", "nsf", NULL, "nsf\0nsfe\0" ),
105 /* Speex File Format */
106 [AFMT_SPEEX] =
107 AFMT_ENTRY("Speex","speex", NULL, "spx\0" ),
108 /* SPC700 Save State */
109 [AFMT_SPC] =
110 AFMT_ENTRY("SPC", "spc", NULL, "spc\0" ),
111 /* APE (Monkey's Audio) */
112 [AFMT_APE] =
113 AFMT_ENTRY("APE", "ape", NULL, "ape\0mac\0" ),
114 /* WMA (WMAV1/V2 in ASF) */
115 [AFMT_WMA] =
116 AFMT_ENTRY("WMA", "wma", NULL, "wma\0wmv\0asf\0" ),
117 /* Amiga MOD File */
118 [AFMT_MOD] =
119 AFMT_ENTRY("MOD", "mod", NULL, "mod\0" ),
120 /* Amiga SAP File */
121 [AFMT_SAP] =
122 AFMT_ENTRY("SAP", "asap", NULL, "sap\0" ),
123#endif
124};
125
126#if CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING)
127/* get REC_FORMAT_* corresponding AFMT_* */
128const int rec_format_afmt[REC_NUM_FORMATS] =
129{
130 /* give AFMT_UNKNOWN by default */
131 [0 ... REC_NUM_FORMATS-1] = AFMT_UNKNOWN,
132 /* add new entries below this line */
133 [REC_FORMAT_AIFF] = AFMT_AIFF,
134 [REC_FORMAT_MPA_L3] = AFMT_MPA_L3,
135 [REC_FORMAT_WAVPACK] = AFMT_WAVPACK,
136 [REC_FORMAT_PCM_WAV] = AFMT_PCM_WAV,
137};
138
139/* get AFMT_* corresponding REC_FORMAT_* */
140const int afmt_rec_format[AFMT_NUM_CODECS] =
141{
142 /* give -1 by default */
143 [0 ... AFMT_NUM_CODECS-1] = -1,
144 /* add new entries below this line */
145 [AFMT_AIFF] = REC_FORMAT_AIFF,
146 [AFMT_MPA_L3] = REC_FORMAT_MPA_L3,
147 [AFMT_WAVPACK] = REC_FORMAT_WAVPACK,
148 [AFMT_PCM_WAV] = REC_FORMAT_PCM_WAV,
149};
150#endif /* CONFIG_CODEC == SWCODEC && defined (HAVE_RECORDING) */
151/****/
152
153static unsigned long unsync(unsigned long b0,
154 unsigned long b1,
155 unsigned long b2,
156 unsigned long b3)
157{
158 return (((long)(b0 & 0x7F) << (3*7)) |
159 ((long)(b1 & 0x7F) << (2*7)) |
160 ((long)(b2 & 0x7F) << (1*7)) |
161 ((long)(b3 & 0x7F) << (0*7)));
162}
163
164static const char* const genres[] = {
165 "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
166 "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
167 "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
168 "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
169 "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
170 "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock",
171 "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
172 "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
173 "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
174 "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
175 "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave",
176 "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
177 "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock",
178
179 /* winamp extensions */
180 "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob",
181 "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
182 "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
183 "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
184 "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
185 "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
186 "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
187 "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
188 "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
189 "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
190 "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
191 "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "Jpop",
192 "Synthpop"
193};
194
195char* id3_get_num_genre(unsigned int genre_num)
196{
197 if (genre_num < sizeof(genres)/sizeof(char*))
198 return (char*)genres[genre_num];
199 return NULL;
200}
201
202/* True if the string is from the "genres" array */
203static bool id3_is_genre_string(const char *string)
204{
205 return ( string >= genres[0] &&
206 string <= genres[sizeof(genres)/sizeof(char*) - 1] );
207}
208
209/*
210 HOW TO ADD ADDITIONAL ID3 VERSION 2 TAGS
211 Code and comments by Thomas Paul Diffenbach
212
213 To add another ID3v2 Tag, do the following:
214 1. add a char* named for the tag to struct mp3entry in id3.h,
215 (I (tpd) prefer to use char* rather than ints, even for what seems like
216 numerical values, for cases where a number won't do, e.g.,
217 YEAR: "circa 1765", "1790/1977" (composed/performed), "28 Feb 1969"
218 TRACK: "1/12", "1 of 12", GENRE: "Freeform genre name"
219 Text is more flexible, and as the main use of id3 data is to
220 display it, converting it to an int just means reconverting to
221 display it, at a runtime cost.)
222
223 2. If any special processing beyond copying the tag value from the Id3
224 block to the struct mp3entry is rrequired (such as converting to an
225 int), write a function to perform this special processing.
226
227 This function's prototype must match that of
228 typedef tagPostProcessFunc, that is it must be:
229 int func( struct mp3entry*, char* tag, int bufferpos )
230 the first argument is a pointer to the current mp3entry structure the
231 second argument is a pointer to the null terminated string value of the
232 tag found the third argument is the offset of the next free byte in the
233 mp3entry's buffer your function should return the corrected offset; if
234 you don't lengthen or shorten the tag string, you can return the third
235 argument unchanged.
236
237 Unless you have a good reason no to, make the function static.
238 TO JUST COPY THE TAG NO SPECIAL PROCESSING FUNCTION IS NEEDED.
239
240 3. add one or more entries to the tagList array, using the format:
241 char* ID3 Tag symbolic name -- see the ID3 specification for these,
242 sizeof() that name minus 1,
243 offsetof( struct mp3entry, variable_name_in_struct_mp3entry ),
244 pointer to your special processing function or NULL
245 if you need no special processing
246 flag indicating if this tag is binary or textual
247 Many ID3 symbolic names come in more than one form. You can add both
248 forms, each referencing the same variable in struct mp3entry.
249 If both forms are present, the last found will be used.
250 Note that the offset can be zero, in which case no entry will be set
251 in the mp3entry struct; the frame is still read into the buffer and
252 the special processing function is called (several times, if there
253 are several frames with the same name).
254
255 4. Alternately, use the TAG_LIST_ENTRY macro with
256 ID3 tag symbolic name,
257 variable in struct mp3entry,
258 special processing function address
259
260 5. Add code to wps-display.c function get_tag to assign a printf-like
261 format specifier for the tag */
262
263/* Structure for ID3 Tag extraction information */
264struct tag_resolver {
265 const char* tag;
266 int tag_length;
267 size_t offset;
268 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
269 bool binary;
270};
271
272static bool global_ff_found;
273
274static int unsynchronize(char* tag, int len, bool *ff_found)
275{
276 int i;
277 unsigned char c;
278 unsigned char *rp, *wp;
279
280 wp = rp = (unsigned char *)tag;
281
282 rp = (unsigned char *)tag;
283 for(i = 0;i < len;i++) {
284 /* Read the next byte and write it back, but don't increment the
285 write pointer */
286 c = *rp++;
287 *wp = c;
288 if(*ff_found) {
289 /* Increment the write pointer if it isn't an unsynch pattern */
290 if(c != 0)
291 wp++;
292 *ff_found = false;
293 } else {
294 if(c == 0xff)
295 *ff_found = true;
296 wp++;
297 }
298 }
299 return (long)wp - (long)tag;
300}
301
302static int unsynchronize_frame(char* tag, int len)
303{
304 bool ff_found = false;
305
306 return unsynchronize(tag, len, &ff_found);
307}
308
309static int read_unsynched(int fd, void *buf, int len)
310{
311 int i;
312 int rc;
313 int remaining = len;
314 char *wp;
315 char *rp;
316
317 wp = buf;
318
319 while(remaining) {
320 rp = wp;
321 rc = read(fd, rp, remaining);
322 if(rc <= 0)
323 return rc;
324
325 i = unsynchronize(wp, remaining, &global_ff_found);
326 remaining -= i;
327 wp += i;
328 }
329
330 return len;
331}
332
333static int skip_unsynched(int fd, int len)
334{
335 int rc;
336 int remaining = len;
337 int rlen;
338 char buf[32];
339
340 while(remaining) {
341 rlen = MIN(sizeof(buf), (unsigned int)remaining);
342 rc = read(fd, buf, rlen);
343 if(rc <= 0)
344 return rc;
345
346 remaining -= unsynchronize(buf, rlen, &global_ff_found);
347 }
348
349 return len;
350}
351
352/* parse numeric value from string */
353static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
354{
355 entry->tracknum = atoi( tag );
356 return bufferpos;
357}
358
359/* parse numeric value from string */
360static int parsediscnum( struct mp3entry* entry, char* tag, int bufferpos )
361{
362 entry->discnum = atoi( tag );
363 return bufferpos;
364}
365
366/* parse numeric value from string */
367static int parseyearnum( struct mp3entry* entry, char* tag, int bufferpos )
368{
369 entry->year = atoi( tag );
370 return bufferpos;
371}
372
373/* parse numeric genre from string, version 2.2 and 2.3 */
374static int parsegenre( struct mp3entry* entry, char* tag, int bufferpos )
375{
376 if(entry->id3version >= ID3_VER_2_4) {
377 /* In version 2.4 and up, there are no parentheses, and the genre frame
378 is a list of strings, either numbers or text. */
379
380 /* Is it a number? */
381 if(isdigit(tag[0])) {
382 entry->genre_string = id3_get_num_genre(atoi( tag ));
383 return tag - entry->id3v2buf;
384 } else {
385 entry->genre_string = tag;
386 return bufferpos;
387 }
388 } else {
389 if( tag[0] == '(' && tag[1] != '(' ) {
390 entry->genre_string = id3_get_num_genre(atoi( tag + 1 ));
391 return tag - entry->id3v2buf;
392 }
393 else {
394 entry->genre_string = tag;
395 return bufferpos;
396 }
397 }
398}
399
400#if CONFIG_CODEC == SWCODEC
401/* parse user defined text, looking for replaygain information. */
402static int parseuser( struct mp3entry* entry, char* tag, int bufferpos )
403{
404 char* value = NULL;
405 int desc_len = strlen(tag);
406 int value_len = 0;
407
408 if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos) {
409 /* At least part of the value was read, so we can safely try to
410 * parse it
411 */
412 value = tag + desc_len + 1;
413 value_len = parse_replaygain(tag, value, entry, tag,
414 bufferpos - (tag - entry->id3v2buf));
415 }
416
417 return tag - entry->id3v2buf + value_len;
418}
419
420/* parse RVA2 binary data and convert to replaygain information. */
421static int parserva2( struct mp3entry* entry, char* tag, int bufferpos )
422{
423 int desc_len = strlen(tag);
424 int start_pos = tag - entry->id3v2buf;
425 int end_pos = start_pos + desc_len + 5;
426 int value_len = 0;
427 unsigned char* value = tag + desc_len + 1;
428
429 /* Only parse RVA2 replaygain tags if tag version == 2.4 and channel
430 * type is master volume.
431 */
432 if (entry->id3version == ID3_VER_2_4 && end_pos < bufferpos
433 && *value++ == 1) {
434 long gain = 0;
435 long peak = 0;
436 long peakbits;
437 long peakbytes;
438 bool album = false;
439
440 /* The RVA2 specification is unclear on some things (id string and
441 * peak volume), but this matches how Quod Libet use them.
442 */
443
444 gain = (int16_t) ((value[0] << 8) | value[1]);
445 value += 2;
446 peakbits = *value++;
447 peakbytes = (peakbits + 7) / 8;
448
449 /* Only use the topmost 24 bits for peak volume */
450 if (peakbytes > 3) {
451 peakbytes = 3;
452 }
453
454 /* Make sure the peak bits were read */
455 if (end_pos + peakbytes < bufferpos) {
456 long shift = ((8 - (peakbits & 7)) & 7) + (3 - peakbytes) * 8;
457
458 for ( ; peakbytes; peakbytes--) {
459 peak <<= 8;
460 peak += *value++;
461 }
462
463 peak <<= shift;
464
465 if (peakbits > 24) {
466 peak += *value >> (8 - shift);
467 }
468 }
469
470 if (strcasecmp(tag, "album") == 0) {
471 album = true;
472 } else if (strcasecmp(tag, "track") != 0) {
473 /* Only accept non-track values if we don't have any previous
474 * value.
475 */
476 if (entry->track_gain != 0) {
477 return start_pos;
478 }
479 }
480
481 value_len = parse_replaygain_int(album, gain, peak * 2, entry,
482 tag, sizeof(entry->id3v2buf) - start_pos);
483 }
484
485 return start_pos + value_len;
486}
487#endif
488
489static int parsembtid( struct mp3entry* entry, char* tag, int bufferpos )
490{
491 char* value = NULL;
492 int desc_len = strlen(tag);
493 /*DEBUGF("MBID len: %d\n", desc_len);*/
494 int value_len = 0;
495
496 if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos)
497 {
498 value = tag + desc_len + 1;
499
500 if (strcasecmp(tag, "http://musicbrainz.org") == 0)
501 {
502 /* Musicbrainz track IDs are always 36 chars long plus null */
503 value_len = 37;
504
505 entry->mb_track_id = value;
506
507 /*DEBUGF("ENTRY: %s LEN: %d\n", entry->mb_track_id, strlen(entry->mb_track_id));*/
508 }
509 }
510
511 return tag - entry->id3v2buf + value_len;
512}
513
514static const struct tag_resolver taglist[] = {
515 { "TPE1", 4, offsetof(struct mp3entry, artist), NULL, false },
516 { "TP1", 3, offsetof(struct mp3entry, artist), NULL, false },
517 { "TIT2", 4, offsetof(struct mp3entry, title), NULL, false },
518 { "TT2", 3, offsetof(struct mp3entry, title), NULL, false },
519 { "TALB", 4, offsetof(struct mp3entry, album), NULL, false },
520 { "TAL", 3, offsetof(struct mp3entry, album), NULL, false },
521 { "TRK", 3, offsetof(struct mp3entry, track_string), &parsetracknum, false },
522 { "TPOS", 4, offsetof(struct mp3entry, disc_string), &parsediscnum, false },
523 { "TRCK", 4, offsetof(struct mp3entry, track_string), &parsetracknum, false },
524 { "TDRC", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
525 { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
526 { "TYE", 3, offsetof(struct mp3entry, year_string), &parseyearnum, false },
527 { "TCOM", 4, offsetof(struct mp3entry, composer), NULL, false },
528 { "TPE2", 4, offsetof(struct mp3entry, albumartist), NULL, false },
529 { "TP2", 3, offsetof(struct mp3entry, albumartist), NULL, false },
530 { "TIT1", 4, offsetof(struct mp3entry, grouping), NULL, false },
531 { "TT1", 3, offsetof(struct mp3entry, grouping), NULL, false },
532 { "COMM", 4, offsetof(struct mp3entry, comment), NULL, false },
533 { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre, false },
534 { "TCO", 3, offsetof(struct mp3entry, genre_string), &parsegenre, false },
535#if CONFIG_CODEC == SWCODEC
536 { "TXXX", 4, 0, &parseuser, false },
537 { "RVA2", 4, 0, &parserva2, true },
538#endif
539 { "UFID", 4, 0, &parsembtid, false },
540};
541
542#define TAGLIST_SIZE ((int)(sizeof(taglist) / sizeof(taglist[0])))
543
544/* Get the length of an ID3 string in the given encoding. Returns the length
545 * in bytes, including end nil, or -1 if the encoding is unknown.
546 */
547static int unicode_len(char encoding, const void* string)
548{
549 int len = 0;
550
551 if (encoding == 0x01 || encoding == 0x02) {
552 char first;
553 const char *s = string;
554 /* string might be unaligned, so using short* can crash on ARM and SH1 */
555 do {
556 first = *s++;
557 } while ((first | *s++) != 0);
558
559 len = s - (const char*) string;
560 } else {
561 len = strlen((char*) string) + 1;
562 }
563
564 return len;
565}
566
567/* Checks to see if the passed in string is a 16-bit wide Unicode v2
568 string. If it is, we convert it to a UTF-8 string. If it's not unicode,
569 we convert from the default codepage */
570static int unicode_munge(char* string, char* utf8buf, int *len) {
571 long tmp;
572 bool le = false;
573 int i = 0;
574 unsigned char *str = (unsigned char *)string;
575 int templen = 0;
576 unsigned char* utf8 = (unsigned char *)utf8buf;
577
578 switch (str[0]) {
579 case 0x00: /* Type 0x00 is ordinary ISO 8859-1 */
580 str++;
581 (*len)--;
582 utf8 = iso_decode(str, utf8, -1, *len);
583 *utf8 = 0;
584 *len = (unsigned long)utf8 - (unsigned long)utf8buf;
585 break;
586
587 case 0x01: /* Unicode with or without BOM */
588 case 0x02:
589 (*len)--;
590 str++;
591
592 /* Handle frames with more than one string
593 (needed for TXXX frames).*/
594 do {
595 tmp = bytes2int(0, 0, str[0], str[1]);
596
597 /* Now check if there is a BOM
598 (zero-width non-breaking space, 0xfeff)
599 and if it is in little or big endian format */
600 if(tmp == 0xfffe) { /* Little endian? */
601 le = true;
602 str += 2;
603 (*len)-=2;
604 } else if(tmp == 0xfeff) { /* Big endian? */
605 str += 2;
606 (*len)-=2;
607 } else
608 /* If there is no BOM (which is a specification violation),
609 let's try to guess it. If one of the bytes is 0x00, it is
610 probably the most significant one. */
611 if(str[1] == 0)
612 le = true;
613
614 do {
615 if(le)
616 utf8 = utf16LEdecode(str, utf8, 1);
617 else
618 utf8 = utf16BEdecode(str, utf8, 1);
619
620 str+=2;
621 i += 2;
622 } while((str[0] || str[1]) && (i < *len));
623
624 *utf8++ = 0; /* Terminate the string */
625 templen += (strlen(&utf8buf[templen]) + 1);
626 str += 2;
627 i+=2;
628 } while(i < *len);
629 *len = templen - 1;
630 break;
631
632 case 0x03: /* UTF-8 encoded string */
633 for(i=0; i < *len; i++)
634 utf8[i] = str[i+1];
635 (*len)--;
636 break;
637
638 default: /* Plain old string */
639 utf8 = iso_decode(str, utf8, -1, *len);
640 *utf8 = 0;
641 *len = (unsigned long)utf8 - (unsigned long)utf8buf;
642 break;
643 }
644 return 0;
645}
646
647/*
648 * Sets the title of an MP3 entry based on its ID3v1 tag.
649 *
650 * Arguments: file - the MP3 file to scen for a ID3v1 tag
651 * entry - the entry to set the title in
652 *
653 * Returns: true if a title was found and created, else false
654 */
655static bool setid3v1title(int fd, struct mp3entry *entry)
656{
657 unsigned char buffer[128];
658 static const char offsets[] = {3, 33, 63, 97, 93, 125, 127};
659 int i, j;
660 unsigned char* utf8;
661
662 if (-1 == lseek(fd, -128, SEEK_END))
663 return false;
664
665 if (read(fd, buffer, sizeof buffer) != sizeof buffer)
666 return false;
667
668 if (strncmp((char *)buffer, "TAG", 3))
669 return false;
670
671 entry->id3v1len = 128;
672 entry->id3version = ID3_VER_1_0;
673
674 for (i=0; i < (int)sizeof offsets; i++) {
675 unsigned char* ptr = (unsigned char *)buffer + offsets[i];
676
677 switch(i) {
678 case 0:
679 case 1:
680 case 2:
681 /* kill trailing space in strings */
682 for (j=29; j && (ptr[j]==0 || ptr[j]==' '); j--)
683 ptr[j] = 0;
684 /* convert string to utf8 */
685 utf8 = (unsigned char *)entry->id3v1buf[i];
686 utf8 = iso_decode(ptr, utf8, -1, 30);
687 /* make sure string is terminated */
688 *utf8 = 0;
689 break;
690
691 case 3:
692 /* kill trailing space in strings */
693 for (j=27; j && (ptr[j]==0 || ptr[j]==' '); j--)
694 ptr[j] = 0;
695 /* convert string to utf8 */
696 utf8 = (unsigned char *)entry->id3v1buf[3];
697 utf8 = iso_decode(ptr, utf8, -1, 28);
698 /* make sure string is terminated */
699 *utf8 = 0;
700 break;
701
702 case 4:
703 ptr[4] = 0;
704 entry->year = atoi((char *)ptr);
705 break;
706
707 case 5:
708 /* id3v1.1 uses last two bytes of comment field for track
709 number: first must be 0 and second is track num */
710 if (!ptr[0] && ptr[1]) {
711 entry->tracknum = ptr[1];
712 entry->id3version = ID3_VER_1_1;
713 }
714 break;
715
716 case 6:
717 /* genre */
718 entry->genre_string = id3_get_num_genre(ptr[0]);
719 break;
720 }
721 }
722
723 entry->title = entry->id3v1buf[0];
724 entry->artist = entry->id3v1buf[1];
725 entry->album = entry->id3v1buf[2];
726 entry->comment = entry->id3v1buf[3];
727
728 return true;
729}
730
731
732/*
733 * Sets the title of an MP3 entry based on its ID3v2 tag.
734 *
735 * Arguments: file - the MP3 file to scan for a ID3v2 tag
736 * entry - the entry to set the title in
737 *
738 * Returns: true if a title was found and created, else false
739 */
740static void setid3v2title(int fd, struct mp3entry *entry)
741{
742 int minframesize;
743 int size;
744 long bufferpos = 0, totframelen, framelen;
745 char header[10];
746 char tmp[4];
747 unsigned char version;
748 char *buffer = entry->id3v2buf;
749 int bytesread = 0;
750 int buffersize = sizeof(entry->id3v2buf);
751 unsigned char global_flags;
752 int flags;
753 int skip;
754 bool global_unsynch = false;
755 bool unsynch = false;
756 int i, j;
757 int rc;
758
759 global_ff_found = false;
760
761 /* Bail out if the tag is shorter than 10 bytes */
762 if(entry->id3v2len < 10)
763 return;
764
765 /* Read the ID3 tag version from the header */
766 lseek(fd, 0, SEEK_SET);
767 if(10 != read(fd, header, 10))
768 return;
769
770 /* Get the total ID3 tag size */
771 size = entry->id3v2len - 10;
772
773 version = header[3];
774 switch ( version ) {
775 case 2:
776 version = ID3_VER_2_2;
777 minframesize = 8;
778 break;
779
780 case 3:
781 version = ID3_VER_2_3;
782 minframesize = 12;
783 break;
784
785 case 4:
786 version = ID3_VER_2_4;
787 minframesize = 12;
788 break;
789
790 default:
791 /* unsupported id3 version */
792 return;
793 }
794 entry->id3version = version;
795 entry->tracknum = entry->year = entry->discnum = 0;
796 entry->title = entry->artist = entry->album = NULL; /* FIXME incomplete */
797
798 global_flags = header[5];
799
800 /* Skip the extended header if it is present */
801 if(global_flags & 0x40) {
802 if(version == ID3_VER_2_3) {
803 if(10 != read(fd, header, 10))
804 return;
805 /* The 2.3 extended header size doesn't include the header size
806 field itself. Also, it is not unsynched. */
807 framelen =
808 bytes2int(header[0], header[1], header[2], header[3]) + 4;
809
810 /* Skip the rest of the header */
811 lseek(fd, framelen - 10, SEEK_CUR);
812 }
813
814 if(version >= ID3_VER_2_4) {
815 if(4 != read(fd, header, 4))
816 return;
817
818 /* The 2.4 extended header size does include the entire header,
819 so here we can just skip it. This header is unsynched. */
820 framelen = unsync(header[0], header[1],
821 header[2], header[3]);
822
823 lseek(fd, framelen - 4, SEEK_CUR);
824 }
825 }
826
827 /* Is unsynchronization applied? */
828 if(global_flags & 0x80) {
829 global_unsynch = true;
830 }
831
832 /*
833 * We must have at least minframesize bytes left for the
834 * remaining frames to be interesting
835 */
836 while (size >= minframesize && bufferpos < buffersize - 1) {
837 flags = 0;
838
839 /* Read frame header and check length */
840 if(version >= ID3_VER_2_3) {
841 if(global_unsynch && version <= ID3_VER_2_3)
842 rc = read_unsynched(fd, header, 10);
843 else
844 rc = read(fd, header, 10);
845 if(rc != 10)
846 return;
847 /* Adjust for the 10 bytes we read */
848 size -= 10;
849
850 flags = bytes2int(0, 0, header[8], header[9]);
851
852 if (version >= ID3_VER_2_4) {
853 framelen = unsync(header[4], header[5],
854 header[6], header[7]);
855 } else {
856 /* version .3 files don't use synchsafe ints for
857 * size */
858 framelen = bytes2int(header[4], header[5],
859 header[6], header[7]);
860 }
861 } else {
862 if(6 != read(fd, header, 6))
863 return;
864 /* Adjust for the 6 bytes we read */
865 size -= 6;
866
867 framelen = bytes2int(0, header[3], header[4], header[5]);
868 }
869
870 logf("framelen = %ld", framelen);
871 if(framelen == 0){
872 if (header[0] == 0 && header[1] == 0 && header[2] == 0)
873 return;
874 else
875 continue;
876 }
877
878 unsynch = false;
879
880 if(flags)
881 {
882 skip = 0;
883
884 if (version >= ID3_VER_2_4) {
885 if(flags & 0x0040) { /* Grouping identity */
886 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
887 framelen--;
888 }
889 } else {
890 if(flags & 0x0020) { /* Grouping identity */
891 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
892 framelen--;
893 }
894 }
895
896 if(flags & 0x000c) /* Compression or encryption */
897 {
898 /* Skip it */
899 size -= framelen;
900 lseek(fd, framelen, SEEK_CUR);
901 continue;
902 }
903
904 if(flags & 0x0002) /* Unsynchronization */
905 unsynch = true;
906
907 if (version >= ID3_VER_2_4) {
908 if(flags & 0x0001) { /* Data length indicator */
909 if(4 != read(fd, tmp, 4))
910 return;
911
912 /* We don't need the data length */
913 framelen -= 4;
914 }
915 }
916 }
917
918 /* Keep track of the remaining frame size */
919 totframelen = framelen;
920
921 /* If the frame is larger than the remaining buffer space we try
922 to read as much as would fit in the buffer */
923 if(framelen >= buffersize - bufferpos)
924 framelen = buffersize - bufferpos - 1;
925
926 logf("id3v2 frame: %.4s", header);
927
928 /* Check for certain frame headers
929
930 'size' is the amount of frame bytes remaining. We decrement it by
931 the amount of bytes we read. If we fail to read as many bytes as
932 we expect, we assume that we can't read from this file, and bail
933 out.
934
935 For each frame. we will iterate over the list of supported tags,
936 and read the tag into entry's buffer. All tags will be kept as
937 strings, for cases where a number won't do, e.g., YEAR: "circa
938 1765", "1790/1977" (composed/performed), "28 Feb 1969" TRACK:
939 "1/12", "1 of 12", GENRE: "Freeform genre name" Text is more
940 flexible, and as the main use of id3 data is to display it,
941 converting it to an int just means reconverting to display it, at a
942 runtime cost.
943
944 For tags that the current code does convert to ints, a post
945 processing function will be called via a pointer to function. */
946
947 for (i=0; i<TAGLIST_SIZE; i++) {
948 const struct tag_resolver* tr = &taglist[i];
949 char** ptag = tr->offset ? (char**) (((char*)entry) + tr->offset)
950 : NULL;
951 char* tag;
952
953 /* Only ID3_VER_2_2 uses frames with three-character names. */
954 if (((version == ID3_VER_2_2) && (tr->tag_length != 3))
955 || ((version > ID3_VER_2_2) && (tr->tag_length != 4))) {
956 continue;
957 }
958
959 /* Note that parser functions sometimes set *ptag to NULL, so
960 * the "!*ptag" check here doesn't always have the desired
961 * effect. Should the parser functions (parsegenre in
962 * particular) be updated to handle the case of being called
963 * multiple times, or should the "*ptag" check be removed?
964 */
965 if( (!ptag || !*ptag) && !memcmp( header, tr->tag, tr->tag_length ) ) {
966
967 /* found a tag matching one in tagList, and not yet filled */
968 tag = buffer + bufferpos;
969
970 if(global_unsynch && version <= ID3_VER_2_3)
971 bytesread = read_unsynched(fd, tag, framelen);
972 else
973 bytesread = read(fd, tag, framelen);
974
975 if( bytesread != framelen )
976 return;
977
978 size -= bytesread;
979
980 if(unsynch || (global_unsynch && version >= ID3_VER_2_4))
981 bytesread = unsynchronize_frame(tag, bytesread);
982
983 /* the COMM frame has a 3 char field to hold an ISO-639-1
984 * language string and an optional short description;
985 * remove them so unicode_munge can work correctly
986 */
987
988 if(!memcmp( header, "COMM", 4 )) {
989 int offset;
990 /* ignore comments with iTunes 7 soundcheck/gapless data */
991 if(!strncmp(tag+4, "iTun", 4))
992 break;
993 offset = 3 + unicode_len(*tag, tag + 4);
994 if(bytesread > offset) {
995 bytesread -= offset;
996 memmove(tag + 1, tag + 1 + offset, bytesread - 1);
997 }
998 }
999
1000 /* Attempt to parse Unicode string only if the tag contents
1001 aren't binary */
1002 if(!tr->binary) {
1003 /* UTF-8 could potentially be 3 times larger */
1004 /* so we need to create a new buffer */
1005 char utf8buf[(3 * bytesread) + 1];
1006
1007 unicode_munge( tag, utf8buf, &bytesread );
1008
1009 if(bytesread >= buffersize - bufferpos)
1010 bytesread = buffersize - bufferpos - 1;
1011
1012 for (j = 0; j < bytesread; j++)
1013 tag[j] = utf8buf[j];
1014
1015 /* remove trailing spaces */
1016 while ( bytesread > 0 && isspace(tag[bytesread-1]))
1017 bytesread--;
1018 }
1019
1020 tag[bytesread] = 0;
1021 bufferpos += bytesread + 1;
1022
1023 if (ptag)
1024 *ptag = tag;
1025
1026 if( tr->ppFunc )
1027 bufferpos = tr->ppFunc(entry, tag, bufferpos);
1028
1029 /* Seek to the next frame */
1030 if(framelen < totframelen)
1031 lseek(fd, totframelen - framelen, SEEK_CUR);
1032 break;
1033 }
1034 }
1035
1036 if( i == TAGLIST_SIZE ) {
1037 /* no tag in tagList was found, or it was a repeat.
1038 skip it using the total size */
1039
1040 if(global_unsynch && version <= ID3_VER_2_3) {
1041 size -= skip_unsynched(fd, totframelen);
1042 } else {
1043 size -= totframelen;
1044 if( lseek(fd, totframelen, SEEK_CUR) == -1 )
1045 return;
1046 }
1047 }
1048 }
1049}
1050
1051/*
1052 * Calculates the size of the ID3v2 tag.
1053 *
1054 * Arguments: file - the file to search for a tag.
1055 *
1056 * Returns: the size of the tag or 0 if none was found
1057 */
1058int getid3v2len(int fd)
1059{
1060 char buf[6];
1061 int offset;
1062
1063 /* Make sure file has a ID3 tag */
1064 if((-1 == lseek(fd, 0, SEEK_SET)) ||
1065 (read(fd, buf, 6) != 6) ||
1066 (strncmp(buf, "ID3", strlen("ID3")) != 0))
1067 offset = 0;
1068
1069 /* Now check what the ID3v2 size field says */
1070 else
1071 if(read(fd, buf, 4) != 4)
1072 offset = 0;
1073 else
1074 offset = unsync(buf[0], buf[1], buf[2], buf[3]) + 10;
1075
1076 logf("ID3V2 Length: 0x%x", offset);
1077 return offset;
1078}
1079
1080/*
1081 * Calculates the length (in milliseconds) of an MP3 file.
1082 *
1083 * Modified to only use integers.
1084 *
1085 * Arguments: file - the file to calculate the length upon
1086 * entry - the entry to update with the length
1087 *
1088 * Returns: the song length in milliseconds,
1089 * 0 means that it couldn't be calculated
1090 */
1091static int getsonglength(int fd, struct mp3entry *entry)
1092{
1093 unsigned long filetime = 0;
1094 struct mp3info info;
1095 long bytecount;
1096
1097 /* Start searching after ID3v2 header */
1098 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET))
1099 return 0;
1100
1101 bytecount = get_mp3file_info(fd, &info);
1102
1103 logf("Space between ID3V2 tag and first audio frame: 0x%lx bytes",
1104 bytecount);
1105
1106 if(bytecount < 0)
1107 return -1;
1108
1109 bytecount += entry->id3v2len;
1110
1111 /* Validate byte count, in case the file has been edited without
1112 * updating the header.
1113 */
1114 if (info.byte_count)
1115 {
1116 const unsigned long expected = entry->filesize - entry->id3v1len
1117 - entry->id3v2len;
1118 const unsigned long diff = MAX(10240, info.byte_count / 20);
1119
1120 if ((info.byte_count > expected + diff)
1121 || (info.byte_count < expected - diff))
1122 {
1123 logf("Note: info.byte_count differs from expected value by "
1124 "%ld bytes", labs((long) (expected - info.byte_count)));
1125 info.byte_count = 0;
1126 info.frame_count = 0;
1127 info.file_time = 0;
1128 info.enc_padding = 0;
1129
1130 /* Even if the bitrate was based on "known bad" values, it
1131 * should still be better for VBR files than using the bitrate
1132 * of the first audio frame.
1133 */
1134 }
1135 }
1136
1137 entry->bitrate = info.bitrate;
1138 entry->frequency = info.frequency;
1139 entry->version = info.version;
1140 entry->layer = info.layer;
1141 switch(entry->layer) {
1142#if CONFIG_CODEC==SWCODEC
1143 case 0:
1144 entry->codectype=AFMT_MPA_L1;
1145 break;
1146#endif
1147 case 1:
1148 entry->codectype=AFMT_MPA_L2;
1149 break;
1150 case 2:
1151 entry->codectype=AFMT_MPA_L3;
1152 break;
1153 }
1154
1155 /* If the file time hasn't been established, this may be a fixed
1156 rate MP3, so just use the default formula */
1157
1158 filetime = info.file_time;
1159
1160 if(filetime == 0)
1161 {
1162 /* Prevent a division by zero */
1163 if (info.bitrate < 8)
1164 filetime = 0;
1165 else
1166 filetime = (entry->filesize - bytecount) / (info.bitrate / 8);
1167 /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8
1168 * instead of filesize * 8 is exact, because mpeg audio bitrates are
1169 * always multiples of 8, and it avoids overflows. */
1170 }
1171
1172 entry->frame_count = info.frame_count;
1173
1174 entry->vbr = info.is_vbr;
1175 entry->has_toc = info.has_toc;
1176
1177#if CONFIG_CODEC==SWCODEC
1178 entry->lead_trim = info.enc_delay;
1179 entry->tail_trim = info.enc_padding;
1180#endif
1181
1182 memcpy(entry->toc, info.toc, sizeof(info.toc));
1183
1184 entry->vbr_header_pos = info.vbr_header_pos;
1185
1186 /* Update the seek point for the first playable frame */
1187 entry->first_frame_offset = bytecount;
1188 logf("First frame is at %lx", entry->first_frame_offset);
1189
1190 return filetime;
1191}
1192
1193/*
1194 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc)
1195 * about an MP3 file and updates it's entry accordingly.
1196 *
1197 Note, that this returns true for successful, false for error! */
1198bool get_mp3_metadata(int fd, struct mp3entry *entry, const char *filename)
1199{
1200#if CONFIG_CODEC != SWCODEC
1201 memset(entry, 0, sizeof(struct mp3entry));
1202#endif
1203
1204 strncpy(entry->path, filename, sizeof(entry->path));
1205
1206 entry->title = NULL;
1207 entry->filesize = filesize(fd);
1208 entry->id3v2len = getid3v2len(fd);
1209 entry->tracknum = 0;
1210 entry->discnum = 0;
1211
1212 if (entry->id3v2len)
1213 setid3v2title(fd, entry);
1214 int len = getsonglength(fd, entry);
1215 if (len < 0)
1216 return false;
1217 entry->length = len;
1218
1219 /* Subtract the meta information from the file size to get
1220 the true size of the MP3 stream */
1221 entry->filesize -= entry->first_frame_offset;
1222
1223 /* only seek to end of file if no id3v2 tags were found */
1224 if (!entry->id3v2len) {
1225 setid3v1title(fd, entry);
1226 }
1227
1228 if(!entry->length || (entry->filesize < 8 ))
1229 /* no song length or less than 8 bytes is hereby considered to be an
1230 invalid mp3 and won't be played by us! */
1231 return false;
1232
1233 return true;
1234}
1235
1236/* Note, that this returns false for successful, true for error! */
1237bool mp3info(struct mp3entry *entry, const char *filename)
1238{
1239 int fd;
1240 bool result;
1241
1242 fd = open(filename, O_RDONLY);
1243 if (fd < 0)
1244 return true;
1245
1246 result = !get_mp3_metadata(fd, entry, filename);
1247
1248 close(fd);
1249
1250 return result;
1251}
1252
1253void adjust_mp3entry(struct mp3entry *entry, void *dest, const void *orig)
1254{
1255 long offset;
1256 if (orig > dest)
1257 offset = - ((size_t)orig - (size_t)dest);
1258 else
1259 offset = (size_t)dest - (size_t)orig;
1260
1261 if (entry->title)
1262 entry->title += offset;
1263 if (entry->artist)
1264 entry->artist += offset;
1265 if (entry->album)
1266 entry->album += offset;
1267 if (entry->genre_string && !id3_is_genre_string(entry->genre_string))
1268 /* Don't adjust that if it points to an entry of the "genres" array */
1269 entry->genre_string += offset;
1270 if (entry->track_string)
1271 entry->track_string += offset;
1272 if (entry->disc_string)
1273 entry->disc_string += offset;
1274 if (entry->year_string)
1275 entry->year_string += offset;
1276 if (entry->composer)
1277 entry->composer += offset;
1278 if (entry->comment)
1279 entry->comment += offset;
1280 if (entry->albumartist)
1281 entry->albumartist += offset;
1282 if (entry->grouping)
1283 entry->grouping += offset;
1284#if CONFIG_CODEC == SWCODEC
1285 if (entry->track_gain_string)
1286 entry->track_gain_string += offset;
1287 if (entry->album_gain_string)
1288 entry->album_gain_string += offset;
1289#endif
1290 if (entry->mb_track_id)
1291 entry->mb_track_id += offset;
1292}
1293
1294void copy_mp3entry(struct mp3entry *dest, const struct mp3entry *orig)
1295{
1296 memcpy(dest, orig, sizeof(struct mp3entry));
1297 adjust_mp3entry(dest, dest, orig);
1298}
1299
1300#ifdef DEBUG_STANDALONE
1301
1302char *secs2str(int ms)
1303{
1304 static char buffer[32];
1305 int secs = ms/1000;
1306 ms %= 1000;
1307 snprintf(buffer, sizeof(buffer), "%d:%02d.%d", secs/60, secs%60, ms/100);
1308 return buffer;
1309}
1310
1311int main(int argc, char **argv)
1312{
1313 int i;
1314 for(i=1; i<argc; i++) {
1315 struct mp3entry mp3;
1316 mp3.album = "Bogus";
1317 if(mp3info(&mp3, argv[i], false)) {
1318 printf("Failed to get %s\n", argv[i]);
1319 return 0;
1320 }
1321
1322 printf("****** File: %s\n"
1323 " Title: %s\n"
1324 " Artist: %s\n"
1325 " Album: %s\n"
1326 " Genre: %s (%d) \n"
1327 " Composer: %s\n"
1328 " Year: %s (%d)\n"
1329 " Track: %s (%d)\n"
1330 " Length: %s / %d s\n"
1331 " Bitrate: %d\n"
1332 " Frequency: %d\n",
1333 argv[i],
1334 mp3.title?mp3.title:"<blank>",
1335 mp3.artist?mp3.artist:"<blank>",
1336 mp3.album?mp3.album:"<blank>",
1337 mp3.genre_string?mp3.genre_string:"<blank>",
1338 mp3.genre,
1339 mp3.composer?mp3.composer:"<blank>",
1340 mp3.year_string?mp3.year_string:"<blank>",
1341 mp3.year,
1342 mp3.track_string?mp3.track_string:"<blank>",
1343 mp3.tracknum,
1344 secs2str(mp3.length),
1345 mp3.length/1000,
1346 mp3.bitrate,
1347 mp3.frequency);
1348 }
1349
1350 return 0;
1351}
1352
1353#endif
diff --git a/apps/mpeg.c b/apps/mpeg.c
new file mode 100644
index 0000000000..2c65e46060
--- /dev/null
+++ b/apps/mpeg.c
@@ -0,0 +1,2873 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
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 <stdbool.h>
22#include <stdlib.h>
23#include "config.h"
24
25#if CONFIG_CODEC != SWCODEC
26
27#include "debug.h"
28#include "panic.h"
29#include "id3.h"
30#include "mpeg.h"
31#include "audio.h"
32#include "ata.h"
33#include "string.h"
34#include <kernel.h>
35#include "thread.h"
36#include "errno.h"
37#include "mp3data.h"
38#include "buffer.h"
39#include "mp3_playback.h"
40#include "sound.h"
41#include "bitswap.h"
42#include "events.h"
43#ifndef SIMULATOR
44#include "i2c.h"
45#include "mas.h"
46#include "system.h"
47#include "usb.h"
48#include "file.h"
49#include "hwcompat.h"
50#endif /* !SIMULATOR */
51#ifdef HAVE_LCD_BITMAP
52#include "lcd.h"
53#endif
54
55#ifndef SIMULATOR
56extern unsigned long mas_version_code;
57#endif
58
59#if CONFIG_CODEC == MAS3587F
60extern enum /* from mp3_playback.c */
61{
62 MPEG_DECODER,
63 MPEG_ENCODER
64} mpeg_mode;
65#endif /* CONFIG_CODEC == MAS3587F */
66
67extern char* playlist_peek(int steps);
68extern bool playlist_check(int steps);
69extern int playlist_next(int steps);
70extern int playlist_amount(void);
71extern int playlist_update_resume_info(const struct mp3entry* id3);
72
73#define MPEG_PLAY 1
74#define MPEG_STOP 2
75#define MPEG_PAUSE 3
76#define MPEG_RESUME 4
77#define MPEG_NEXT 5
78#define MPEG_PREV 6
79#define MPEG_FF_REWIND 7
80#define MPEG_FLUSH_RELOAD 8
81#define MPEG_RECORD 9
82#define MPEG_INIT_RECORDING 10
83#define MPEG_INIT_PLAYBACK 11
84#define MPEG_NEW_FILE 12
85#define MPEG_PAUSE_RECORDING 13
86#define MPEG_RESUME_RECORDING 14
87#define MPEG_NEED_DATA 100
88#define MPEG_TRACK_CHANGE 101
89#define MPEG_SAVE_DATA 102
90#define MPEG_STOP_DONE 103
91#define MPEG_PRERECORDING_TICK 104
92
93/* indicator for MPEG_NEED_DATA */
94#define GENERATE_UNBUFFER_EVENTS 1
95
96/* list of tracks in memory */
97#define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */
98#define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1)
99
100struct trackdata
101{
102 struct mp3entry id3;
103 int mempos;
104 int load_ahead_index;
105};
106
107static struct trackdata trackdata[MAX_TRACK_ENTRIES];
108
109static unsigned int current_track_counter = 0;
110static unsigned int last_track_counter = 0;
111
112/* Play time of the previous track */
113unsigned long prev_track_elapsed;
114
115#ifndef SIMULATOR
116static int track_read_idx = 0;
117static int track_write_idx = 0;
118#endif /* !SIMULATOR */
119
120/* Cuesheet callback */
121static bool (*cuesheet_callback)(const char *filename) = NULL;
122
123static const char mpeg_thread_name[] = "mpeg";
124static unsigned int mpeg_errno;
125
126static bool playing = false; /* We are playing an MP3 stream */
127static bool is_playing = false; /* We are (attempting to) playing MP3 files */
128static bool paused; /* playback is paused */
129
130#ifdef SIMULATOR
131static char mpeg_stack[DEFAULT_STACK_SIZE];
132static struct mp3entry taginfo;
133
134#else /* !SIMULATOR */
135static struct event_queue mpeg_queue;
136static long mpeg_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
137
138static int audiobuflen;
139static int audiobuf_write;
140static int audiobuf_swapwrite;
141static int audiobuf_read;
142
143static int mpeg_file;
144
145static bool play_pending; /* We are about to start playing */
146static bool play_pending_track_change; /* When starting play we're starting a new file */
147static bool filling; /* We are filling the buffer with data from disk */
148static bool dma_underrun; /* True when the DMA has stopped because of
149 slow disk reading (read error, shaking) */
150static bool mpeg_stop_done;
151
152static int last_dma_tick = 0;
153static int last_dma_chunk_size;
154
155static long low_watermark; /* Dynamic low watermark level */
156static long low_watermark_margin = 0; /* Extra time in seconds for watermark */
157static long lowest_watermark_level; /* Debug value to observe the buffer
158 usage */
159#if CONFIG_CODEC == MAS3587F
160static char recording_filename[MAX_PATH]; /* argument to thread */
161static char delayed_filename[MAX_PATH]; /* internal copy of above */
162
163static char xing_buffer[MAX_XING_HEADER_SIZE];
164
165static bool init_recording_done;
166static bool init_playback_done;
167static bool prerecording; /* True if prerecording is enabled */
168static bool is_prerecording; /* True if we are prerecording */
169static bool is_recording; /* We are recording */
170
171static enum {
172 NOT_SAVING = 0, /* reasons to save data, sorted by importance */
173 BUFFER_FULL,
174 NEW_FILE,
175 STOP_RECORDING
176} saving_status;
177
178static int rec_frequency_index; /* For create_xing_header() calls */
179static int rec_version_index; /* For create_xing_header() calls */
180
181struct prerecord_info {
182 int mempos;
183 unsigned long framecount;
184};
185
186static struct prerecord_info prerecord_buffer[MPEG_MAX_PRERECORD_SECONDS];
187static int prerecord_index; /* Current index in the prerecord buffer */
188static int prerecording_max_seconds; /* Max number of seconds to store */
189static int prerecord_count; /* Number of seconds in the prerecord buffer */
190static int prerecord_timeout; /* The tick count of the next prerecord data
191 store */
192
193unsigned long record_start_time; /* Value of current_tick when recording
194 was started */
195unsigned long pause_start_time; /* Value of current_tick when pause was
196 started */
197static unsigned long last_rec_time;
198static unsigned long num_rec_bytes;
199static unsigned long last_rec_bytes;
200static unsigned long frame_count_start;
201static unsigned long frame_count_end;
202static unsigned long saved_header = 0;
203
204/* Shadow MAS registers */
205unsigned long shadow_encoder_control = 0;
206#endif /* CONFIG_CODEC == MAS3587F */
207
208#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
209unsigned long shadow_io_control_main = 0;
210unsigned long shadow_soft_mute = 0;
211unsigned shadow_codec_reg0;
212#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
213
214#ifdef HAVE_RECORDING
215static const unsigned char empty_id3_header[] =
216{
217 'I', 'D', '3', 0x03, 0x00, 0x00,
218 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
219};
220#endif /* HAVE_RECORDING */
221
222
223static int get_unplayed_space(void);
224static int get_playable_space(void);
225static int get_unswapped_space(void);
226#endif /* !SIMULATOR */
227
228#if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
229static void init_recording(void);
230static void prepend_header(void);
231static void update_header(void);
232static void start_prerecording(void);
233static void start_recording(void);
234static void stop_recording(void);
235static int get_unsaved_space(void);
236static void pause_recording(void);
237static void resume_recording(void);
238#endif /* (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR) */
239
240
241#ifndef SIMULATOR
242static int num_tracks_in_memory(void)
243{
244 return (track_write_idx - track_read_idx) & MAX_TRACK_ENTRIES_MASK;
245}
246
247#ifdef DEBUG_TAGS
248static void debug_tags(void)
249{
250 int i;
251
252 for(i = 0;i < MAX_TRACK_ENTRIES;i++)
253 {
254 DEBUGF("%d - %s\n", i, trackdata[i].id3.path);
255 }
256 DEBUGF("read: %d, write :%d\n", track_read_idx, track_write_idx);
257 DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory());
258}
259#else /* !DEBUG_TAGS */
260#define debug_tags()
261#endif /* !DEBUG_TAGS */
262
263static void remove_current_tag(void)
264{
265 if(num_tracks_in_memory() > 0)
266 {
267 /* First move the index, so nobody tries to access the tag */
268 track_read_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK;
269 debug_tags();
270 }
271 else
272 {
273 DEBUGF("remove_current_tag: no tracks to remove\n");
274 }
275}
276
277static void remove_all_non_current_tags(void)
278{
279 track_write_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK;
280 debug_tags();
281}
282
283static void remove_all_tags(void)
284{
285 track_write_idx = track_read_idx;
286
287 debug_tags();
288}
289
290static struct trackdata *get_trackdata(int offset)
291{
292 if(offset >= num_tracks_in_memory())
293 return NULL;
294 else
295 return &trackdata[(track_read_idx + offset) & MAX_TRACK_ENTRIES_MASK];
296}
297#endif /* !SIMULATOR */
298
299/***********************************************************************/
300/* audio event handling */
301
302#define MAX_EVENT_HANDLERS 10
303struct event_handlers_table
304{
305 AUDIO_EVENT_HANDLER handler;
306 unsigned short mask;
307};
308static struct event_handlers_table event_handlers[MAX_EVENT_HANDLERS];
309static int event_handlers_count = 0;
310
311void audio_register_event_handler(AUDIO_EVENT_HANDLER handler, unsigned short mask)
312{
313 if (event_handlers_count < MAX_EVENT_HANDLERS)
314 {
315 event_handlers[event_handlers_count].handler = handler;
316 event_handlers[event_handlers_count].mask = mask;
317 event_handlers_count++;
318 }
319}
320
321/* dispatch calls each handler in the order registered and returns after some
322 handler actually handles the event (the event is assumed to no longer be valid
323 after this, due to the handler changing some condition); returns true if someone
324 handled the event, which is expected to cause the caller to skip its own handling
325 of the event */
326#ifndef SIMULATOR
327static bool audio_dispatch_event(unsigned short event, unsigned long data)
328{
329 int i = 0;
330 for(i=0; i < event_handlers_count; i++)
331 {
332 if ( event_handlers[i].mask & event )
333 {
334 int rc = event_handlers[i].handler(event, data);
335 if ( rc == AUDIO_EVENT_RC_HANDLED )
336 return true;
337 }
338 }
339 return false;
340}
341#endif
342
343/***********************************************************************/
344
345static void set_elapsed(struct mp3entry* id3)
346{
347 if ( id3->vbr ) {
348 if ( id3->has_toc ) {
349 /* calculate elapsed time using TOC */
350 int i;
351 unsigned int remainder, plen, relpos, nextpos;
352
353 /* find wich percent we're at */
354 for (i=0; i<100; i++ )
355 {
356 if ( id3->offset < id3->toc[i] * (id3->filesize / 256) )
357 {
358 break;
359 }
360 }
361
362 i--;
363 if (i < 0)
364 i = 0;
365
366 relpos = id3->toc[i];
367
368 if (i < 99)
369 {
370 nextpos = id3->toc[i+1];
371 }
372 else
373 {
374 nextpos = 256;
375 }
376
377 remainder = id3->offset - (relpos * (id3->filesize / 256));
378
379 /* set time for this percent (divide before multiply to prevent
380 overflow on long files. loss of precision is negligible on
381 short files) */
382 id3->elapsed = i * (id3->length / 100);
383
384 /* calculate remainder time */
385 plen = (nextpos - relpos) * (id3->filesize / 256);
386 id3->elapsed += (((remainder * 100) / plen) *
387 (id3->length / 10000));
388 }
389 else {
390 /* no TOC exists. set a rough estimate using average bitrate */
391 int tpk = id3->length / (id3->filesize / 1024);
392 id3->elapsed = id3->offset / 1024 * tpk;
393 }
394 }
395 else
396 /* constant bitrate, use exact calculation */
397 id3->elapsed = id3->offset / (id3->bitrate / 8);
398}
399
400int audio_get_file_pos(void)
401{
402 int pos = -1;
403 struct mp3entry *id3 = audio_current_track();
404
405 if (id3->vbr)
406 {
407 if (id3->has_toc)
408 {
409 /* Use the TOC to find the new position */
410 unsigned int percent, remainder;
411 int curtoc, nexttoc, plen;
412
413 percent = (id3->elapsed*100)/id3->length;
414 if (percent > 99)
415 percent = 99;
416
417 curtoc = id3->toc[percent];
418
419 if (percent < 99)
420 nexttoc = id3->toc[percent+1];
421 else
422 nexttoc = 256;
423
424 pos = (id3->filesize/256)*curtoc;
425
426 /* Use the remainder to get a more accurate position */
427 remainder = (id3->elapsed*100)%id3->length;
428 remainder = (remainder*100)/id3->length;
429 plen = (nexttoc - curtoc)*(id3->filesize/256);
430 pos += (plen/100)*remainder;
431 }
432 else
433 {
434 /* No TOC exists, estimate the new position */
435 pos = (id3->filesize / (id3->length / 1000)) *
436 (id3->elapsed / 1000);
437 }
438 }
439 else if (id3->bitrate)
440 pos = id3->elapsed * (id3->bitrate / 8);
441 else
442 {
443 return -1;
444 }
445
446 if (pos >= (int)(id3->filesize - id3->id3v1len))
447 {
448 /* Don't seek right to the end of the file so that we can
449 transition properly to the next song */
450 pos = id3->filesize - id3->id3v1len - 1;
451 }
452 else if (pos < (int)id3->first_frame_offset)
453 {
454 /* skip past id3v2 tag and other leading garbage */
455 pos = id3->first_frame_offset;
456 }
457 return pos;
458}
459
460unsigned long mpeg_get_last_header(void)
461{
462#ifdef SIMULATOR
463 return 0;
464#else /* !SIMULATOR */
465 unsigned long tmp[2];
466
467 /* Read the frame data from the MAS and reconstruct it with the
468 frame sync and all */
469 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_STATUS_1, tmp, 2);
470 return 0xffe00000 | ((tmp[0] & 0x7c00) << 6) | (tmp[1] & 0xffff);
471#endif /* !SIMULATOR */
472}
473
474void audio_set_cuesheet_callback(bool (*handler)(const char *filename))
475{
476 cuesheet_callback = handler;
477}
478
479#ifndef SIMULATOR
480/* Send callback events to notify about removing old tracks. */
481static void generate_unbuffer_events(void)
482{
483 int i;
484 int numentries = MAX_TRACK_ENTRIES - num_tracks_in_memory();
485 int cur_idx = track_write_idx;
486
487 for (i = 0; i < numentries; i++)
488 {
489 /* Send an event to notify that track has finished. */
490 send_event(PLAYBACK_EVENT_TRACK_FINISH, &trackdata[cur_idx].id3);
491 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
492 }
493}
494
495/* Send callback events to notify about new tracks. */
496static void generate_postbuffer_events(void)
497{
498 int i;
499 int numentries = num_tracks_in_memory();
500 int cur_idx = track_read_idx;
501
502 for (i = 0; i < numentries; i++)
503 {
504 send_event(PLAYBACK_EVENT_TRACK_BUFFER, &trackdata[cur_idx].id3);
505 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
506 }
507}
508
509static void recalculate_watermark(int bitrate)
510{
511 int bytes_per_sec;
512 int time = ata_spinup_time;
513
514 /* A bitrate of 0 probably means empty VBR header. We play safe
515 and set a high threshold */
516 if(bitrate == 0)
517 bitrate = 320;
518
519 bytes_per_sec = bitrate * 1000 / 8;
520
521 if(time)
522 {
523 /* No drive spins up faster than 3.5s */
524 if(time < 350)
525 time = 350;
526
527 time = time * 3;
528 low_watermark = ((low_watermark_margin * HZ + time) *
529 bytes_per_sec) / HZ;
530 }
531 else
532 {
533 low_watermark = MPEG_LOW_WATER;
534 }
535}
536
537#ifdef HAVE_DISK_STORAGE
538void audio_set_buffer_margin(int seconds)
539{
540 low_watermark_margin = seconds;
541}
542#endif
543
544void audio_get_debugdata(struct audio_debug *dbgdata)
545{
546 dbgdata->audiobuflen = audiobuflen;
547 dbgdata->audiobuf_write = audiobuf_write;
548 dbgdata->audiobuf_swapwrite = audiobuf_swapwrite;
549 dbgdata->audiobuf_read = audiobuf_read;
550
551 dbgdata->last_dma_chunk_size = last_dma_chunk_size;
552
553#if CONFIG_CPU == SH7034
554 dbgdata->dma_on = (SCR0 & 0x80) != 0;
555#endif
556 dbgdata->playing = playing;
557 dbgdata->play_pending = play_pending;
558 dbgdata->is_playing = is_playing;
559 dbgdata->filling = filling;
560 dbgdata->dma_underrun = dma_underrun;
561
562 dbgdata->unplayed_space = get_unplayed_space();
563 dbgdata->playable_space = get_playable_space();
564 dbgdata->unswapped_space = get_unswapped_space();
565
566 dbgdata->low_watermark_level = low_watermark;
567 dbgdata->lowest_watermark_level = lowest_watermark_level;
568}
569
570#ifdef DEBUG
571static void dbg_timer_start(void)
572{
573 /* We are using timer 2 */
574
575 TSTR &= ~0x04; /* Stop the timer */
576 TSNC &= ~0x04; /* No synchronization */
577 TMDR &= ~0x44; /* Operate normally */
578
579 TCNT2 = 0; /* Start counting at 0 */
580 TCR2 = 0x03; /* Sysclock/8 */
581
582 TSTR |= 0x04; /* Start timer 2 */
583}
584
585static int dbg_cnt2us(unsigned int cnt)
586{
587 return (cnt * 10000) / (FREQ/800);
588}
589#endif /* DEBUG */
590
591static int get_unplayed_space(void)
592{
593 int space = audiobuf_write - audiobuf_read;
594 if (space < 0)
595 space += audiobuflen;
596 return space;
597}
598
599static int get_playable_space(void)
600{
601 int space = audiobuf_swapwrite - audiobuf_read;
602 if (space < 0)
603 space += audiobuflen;
604 return space;
605}
606
607static int get_unplayed_space_current_song(void)
608{
609 int space;
610
611 if (num_tracks_in_memory() > 1)
612 {
613 space = get_trackdata(1)->mempos - audiobuf_read;
614 }
615 else
616 {
617 space = audiobuf_write - audiobuf_read;
618 }
619
620 if (space < 0)
621 space += audiobuflen;
622
623 return space;
624}
625
626static int get_unswapped_space(void)
627{
628 int space = audiobuf_write - audiobuf_swapwrite;
629 if (space < 0)
630 space += audiobuflen;
631 return space;
632}
633
634#if CONFIG_CODEC == MAS3587F
635static int get_unsaved_space(void)
636{
637 int space = audiobuf_write - audiobuf_read;
638 if (space < 0)
639 space += audiobuflen;
640 return space;
641}
642
643static void drain_dma_buffer(void)
644{
645 while (PBDRH & 0x40)
646 {
647 xor_b(0x08, &PADRH);
648
649 while (PBDRH & 0x80);
650
651 xor_b(0x08, &PADRH);
652
653 while (!(PBDRH & 0x80));
654 }
655}
656
657#ifdef DEBUG
658static long timing_info_index = 0;
659static long timing_info[1024];
660#endif /* DEBUG */
661
662void rec_tick (void) __attribute__ ((section (".icode")));
663void rec_tick(void)
664{
665 int i;
666 int delay;
667 char data;
668
669 if(is_recording && (PBDRH & 0x40))
670 {
671#ifdef DEBUG
672 timing_info[timing_info_index++] = current_tick;
673 TCNT2 = 0;
674#endif /* DEBUG */
675 /* Note: Although this loop is run in interrupt context, further
676 * optimisation will do no good. The MAS would then deliver bad
677 * frames occasionally, as observed in extended experiments. */
678 i = 0;
679 while (PBDRH & 0x40) /* We try to read as long as EOD is high */
680 {
681 xor_b(0x08, &PADRH); /* Set PR active, independent of polarity */
682
683 delay = 100;
684 while (PBDRH & 0x80) /* Wait until /RTW becomes active */
685 {
686 if (--delay <= 0) /* Bail out if we have to wait too long */
687 { /* i.e. the MAS doesn't want to talk to us */
688 xor_b(0x08, &PADRH); /* Set PR inactive */
689 goto transfer_end; /* and get out of here */
690 }
691 }
692
693 data = *(unsigned char *)0x04000000; /* read data byte */
694
695 xor_b(0x08, &PADRH); /* Set PR inactive */
696
697 audiobuf[audiobuf_write++] = data;
698
699 if (audiobuf_write >= audiobuflen)
700 audiobuf_write = 0;
701
702 i++;
703 }
704 transfer_end:
705
706#ifdef DEBUG
707 timing_info[timing_info_index++] = TCNT2 + (i << 16);
708 timing_info_index &= 0x3ff;
709#endif /* DEBUG */
710
711 num_rec_bytes += i;
712
713 if(is_prerecording)
714 {
715 if(TIME_AFTER(current_tick, prerecord_timeout))
716 {
717 prerecord_timeout = current_tick + HZ;
718 queue_post(&mpeg_queue, MPEG_PRERECORDING_TICK, 0);
719 }
720 }
721 else
722 {
723 /* Signal to save the data if we are running out of buffer
724 space */
725 if (audiobuflen - get_unsaved_space() < MPEG_RECORDING_LOW_WATER
726 && saving_status == NOT_SAVING)
727 {
728 saving_status = BUFFER_FULL;
729 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
730 }
731 }
732 }
733}
734#endif /* CONFIG_CODEC == MAS3587F */
735
736void playback_tick(void)
737{
738 struct trackdata *ptd = get_trackdata(0);
739 if(ptd)
740 {
741 ptd->id3.elapsed += (current_tick - last_dma_tick) * 1000 / HZ;
742 last_dma_tick = current_tick;
743 audio_dispatch_event(AUDIO_EVENT_POS_REPORT,
744 (unsigned long)ptd->id3.elapsed);
745 }
746}
747
748static void reset_mp3_buffer(void)
749{
750 audiobuf_read = 0;
751 audiobuf_write = 0;
752 audiobuf_swapwrite = 0;
753 lowest_watermark_level = audiobuflen;
754}
755
756 /* DMA transfer end interrupt callback */
757static void transfer_end(unsigned char** ppbuf, size_t* psize)
758{
759 if(playing && !paused)
760 {
761 int unplayed_space_left;
762 int space_until_end_of_buffer;
763 int track_offset = 1;
764 struct trackdata *track;
765
766 audiobuf_read += last_dma_chunk_size;
767 if(audiobuf_read >= audiobuflen)
768 audiobuf_read = 0;
769
770 /* First, check if we are on a track boundary */
771 if (num_tracks_in_memory() > 1)
772 {
773 if (audiobuf_read == get_trackdata(track_offset)->mempos)
774 {
775 if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK, 0) )
776 {
777 queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0);
778 track_offset++;
779 }
780 }
781 }
782
783 unplayed_space_left = get_unplayed_space();
784
785 space_until_end_of_buffer = audiobuflen - audiobuf_read;
786
787 if(!filling && unplayed_space_left < low_watermark)
788 {
789 filling = true;
790 queue_post(&mpeg_queue, MPEG_NEED_DATA, GENERATE_UNBUFFER_EVENTS);
791 }
792
793 if(unplayed_space_left)
794 {
795 last_dma_chunk_size = MIN(0x2000, unplayed_space_left);
796 last_dma_chunk_size = MIN(last_dma_chunk_size,
797 space_until_end_of_buffer);
798
799 /* several tracks loaded? */
800 track = get_trackdata(track_offset);
801 if(track)
802 {
803 /* will we move across the track boundary? */
804 if (( audiobuf_read < track->mempos ) &&
805 ((audiobuf_read+last_dma_chunk_size) >
806 track->mempos ))
807 {
808 /* Make sure that we end exactly on the boundary */
809 last_dma_chunk_size = track->mempos - audiobuf_read;
810 }
811 }
812
813 *psize = last_dma_chunk_size & 0xffff;
814 *ppbuf = audiobuf + audiobuf_read;
815 track = get_trackdata(0);
816 if(track)
817 track->id3.offset += last_dma_chunk_size;
818
819 /* Update the watermark debug level */
820 if(unplayed_space_left < lowest_watermark_level)
821 lowest_watermark_level = unplayed_space_left;
822 }
823 else
824 {
825 /* Check if the end of data is because of a hard disk error.
826 If there is an open file handle, we are still playing music.
827 If not, the last file has been loaded, and the file handle is
828 closed. */
829 if(mpeg_file >= 0)
830 {
831 /* Update the watermark debug level */
832 if(unplayed_space_left < lowest_watermark_level)
833 lowest_watermark_level = unplayed_space_left;
834
835 DEBUGF("DMA underrun.\n");
836 dma_underrun = true;
837 }
838 else
839 {
840 if ( ! audio_dispatch_event(AUDIO_EVENT_END_OF_TRACK, 0) )
841 {
842 DEBUGF("No more MP3 data. Stopping.\n");
843 queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0);
844 playing = false;
845 }
846 }
847 *psize = 0; /* no more transfer */
848 }
849 }
850}
851
852static struct trackdata *add_track_to_tag_list(const char *filename)
853{
854 struct trackdata *track;
855
856 if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES)
857 {
858 DEBUGF("Tag memory is full\n");
859 return NULL;
860 }
861
862 track = &trackdata[track_write_idx];
863
864 /* grab id3 tag of new file and
865 remember where in memory it starts */
866 if(mp3info(&track->id3, filename))
867 {
868 DEBUGF("Bad mp3\n");
869 return NULL;
870 }
871 track->mempos = audiobuf_write;
872 track->id3.elapsed = 0;
873#ifdef HAVE_LCD_BITMAP
874 if (track->id3.title)
875 lcd_getstringsize(track->id3.title, NULL, NULL);
876 if (track->id3.artist)
877 lcd_getstringsize(track->id3.artist, NULL, NULL);
878 if (track->id3.album)
879 lcd_getstringsize(track->id3.album, NULL, NULL);
880#endif
881 if (cuesheet_callback)
882 if (cuesheet_callback(filename))
883 track->id3.cuesheet_type = 1;
884
885 track_write_idx = (track_write_idx+1) & MAX_TRACK_ENTRIES_MASK;
886 debug_tags();
887 return track;
888}
889
890static int new_file(int steps)
891{
892 int max_steps = playlist_amount();
893 int start = 0;
894 int i;
895 struct trackdata *track;
896
897 /* Find out how many steps to advance. The load_ahead_index field tells
898 us how many playlist entries it had to skip to get to a valid one.
899 We add those together to find out where to start. */
900 if(steps > 0 && num_tracks_in_memory() > 1)
901 {
902 /* Begin with the song after the currently playing one */
903 i = 1;
904 while((track = get_trackdata(i++)))
905 {
906 start += track->load_ahead_index;
907 }
908 }
909
910 do {
911 char *trackname;
912
913 trackname = playlist_peek( start + steps );
914 if ( !trackname )
915 return -1;
916
917 DEBUGF("Loading %s\n", trackname);
918
919 mpeg_file = open(trackname, O_RDONLY);
920 if(mpeg_file < 0) {
921 DEBUGF("Couldn't open file: %s\n",trackname);
922 if(steps < 0)
923 steps--;
924 else
925 steps++;
926 }
927 else
928 {
929 struct trackdata *track = add_track_to_tag_list(trackname);
930
931 if(!track)
932 {
933 /* Bad mp3 file */
934 if(steps < 0)
935 steps--;
936 else
937 steps++;
938 close(mpeg_file);
939 mpeg_file = -1;
940 }
941 else
942 {
943 /* skip past id3v2 tag */
944 lseek(mpeg_file,
945 track->id3.first_frame_offset,
946 SEEK_SET);
947 track->id3.index = steps;
948 track->load_ahead_index = steps;
949 track->id3.offset = 0;
950
951 if(track->id3.vbr)
952 /* Average bitrate * 1.5 */
953 recalculate_watermark(
954 (track->id3.bitrate * 3) / 2);
955 else
956 recalculate_watermark(
957 track->id3.bitrate);
958
959 }
960 }
961
962 /* Bail out if no file could be opened */
963 if(abs(steps) > max_steps)
964 return -1;
965 } while ( mpeg_file < 0 );
966
967 return 0;
968}
969
970static void stop_playing(void)
971{
972 struct trackdata *track;
973
974 /* Stop the current stream */
975 mp3_play_stop();
976 playing = false;
977 filling = false;
978
979 track = get_trackdata(0);
980 if (track != NULL)
981 prev_track_elapsed = track->id3.elapsed;
982
983 if(mpeg_file >= 0)
984 close(mpeg_file);
985 mpeg_file = -1;
986 remove_all_tags();
987 generate_unbuffer_events();
988 reset_mp3_buffer();
989}
990
991static void end_current_track(void) {
992 struct trackdata *track;
993
994 play_pending = false;
995 playing = false;
996 mp3_play_pause(false);
997
998 track = get_trackdata(0);
999 if (track != NULL)
1000 prev_track_elapsed = track->id3.elapsed;
1001
1002 reset_mp3_buffer();
1003 remove_all_tags();
1004 generate_unbuffer_events();
1005
1006 if(mpeg_file >= 0)
1007 close(mpeg_file);
1008}
1009
1010/* Is this a really the end of playback or is a new playlist starting */
1011static void check_playlist_end(int direction)
1012{
1013 /* Use the largest possible step size to account for skipped tracks */
1014 int steps = playlist_amount();
1015
1016 if (direction < 0)
1017 steps = -steps;
1018
1019 if (playlist_next(steps) < 0)
1020 is_playing = false;
1021}
1022
1023static void update_playlist(void)
1024{
1025 if (num_tracks_in_memory() > 0)
1026 {
1027 struct trackdata *track = get_trackdata(0);
1028 track->id3.index = playlist_next(track->id3.index);
1029 }
1030 else
1031 {
1032 /* End of playlist? */
1033 check_playlist_end(1);
1034 }
1035
1036 playlist_update_resume_info(audio_current_track());
1037}
1038
1039static void track_change(void)
1040{
1041 DEBUGF("Track change\n");
1042
1043 struct trackdata *track = get_trackdata(0);
1044 prev_track_elapsed = track->id3.elapsed;
1045
1046#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1047 /* Reset the AVC */
1048 sound_set_avc(-1);
1049#endif /* (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) */
1050
1051 if (num_tracks_in_memory() > 0)
1052 {
1053 remove_current_tag();
1054 send_event(PLAYBACK_EVENT_TRACK_CHANGE, audio_current_track());
1055 update_playlist();
1056 }
1057
1058 current_track_counter++;
1059}
1060
1061unsigned long audio_prev_elapsed(void)
1062{
1063 return prev_track_elapsed;
1064}
1065
1066#ifdef DEBUG
1067void hexdump(const unsigned char *buf, int len)
1068{
1069 int i;
1070
1071 for(i = 0;i < len;i++)
1072 {
1073 if(i && (i & 15) == 0)
1074 {
1075 DEBUGF("\n");
1076 }
1077 DEBUGF("%02x ", buf[i]);
1078 }
1079 DEBUGF("\n");
1080}
1081#endif /* DEBUG */
1082
1083static void start_playback_if_ready(void)
1084{
1085 int playable_space;
1086
1087 playable_space = audiobuf_swapwrite - audiobuf_read;
1088 if(playable_space < 0)
1089 playable_space += audiobuflen;
1090
1091 /* See if we have started playing yet. If not, do it. */
1092 if(play_pending || dma_underrun)
1093 {
1094 /* If the filling has stopped, and we still haven't reached
1095 the watermark, the file must be smaller than the
1096 watermark. We must still play it. */
1097 if((playable_space >= MPEG_PLAY_PENDING_THRESHOLD) ||
1098 !filling || dma_underrun)
1099 {
1100 DEBUGF("P\n");
1101 if (play_pending) /* don't do this when recovering from DMA underrun */
1102 {
1103 generate_postbuffer_events(); /* signal first track as buffered */
1104 if (play_pending_track_change)
1105 {
1106 play_pending_track_change = false;
1107 send_event(PLAYBACK_EVENT_TRACK_CHANGE, audio_current_track());
1108 }
1109 play_pending = false;
1110 }
1111 playing = true;
1112
1113 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1114 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
1115 dma_underrun = false;
1116
1117 if (!paused)
1118 {
1119 last_dma_tick = current_tick;
1120 mp3_play_pause(true);
1121 }
1122
1123 /* Tell ourselves that we need more data */
1124 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1125 }
1126 }
1127}
1128
1129static bool swap_one_chunk(void)
1130{
1131 int free_space_left;
1132 int amount_to_swap;
1133
1134 free_space_left = get_unswapped_space();
1135
1136 if(free_space_left == 0 && !play_pending)
1137 return false;
1138
1139 /* Swap in larger chunks when the user is waiting for the playback
1140 to start, or when there is dangerously little playable data left */
1141 if(play_pending)
1142 amount_to_swap = MIN(MPEG_PLAY_PENDING_SWAPSIZE, free_space_left);
1143 else
1144 {
1145 if(get_playable_space() < low_watermark)
1146 amount_to_swap = MIN(MPEG_LOW_WATER_SWAP_CHUNKSIZE,
1147 free_space_left);
1148 else
1149 amount_to_swap = MIN(MPEG_SWAP_CHUNKSIZE, free_space_left);
1150 }
1151
1152 if(audiobuf_write < audiobuf_swapwrite)
1153 amount_to_swap = MIN(audiobuflen - audiobuf_swapwrite,
1154 amount_to_swap);
1155 else
1156 amount_to_swap = MIN(audiobuf_write - audiobuf_swapwrite,
1157 amount_to_swap);
1158
1159 bitswap(audiobuf + audiobuf_swapwrite, amount_to_swap);
1160
1161 audiobuf_swapwrite += amount_to_swap;
1162 if(audiobuf_swapwrite >= audiobuflen)
1163 {
1164 audiobuf_swapwrite = 0;
1165 }
1166
1167 return true;
1168}
1169
1170static void mpeg_thread(void)
1171{
1172 static int pause_tick = 0;
1173 static unsigned int pause_track = 0;
1174 struct queue_event ev;
1175 int len;
1176 int free_space_left;
1177 int unplayed_space_left;
1178 int amount_to_read;
1179 int t1, t2;
1180 int start_offset;
1181#if CONFIG_CODEC == MAS3587F
1182 int amount_to_save;
1183 int save_endpos = 0;
1184 int rc;
1185 int level;
1186 long offset;
1187#endif /* CONFIG_CODEC == MAS3587F */
1188
1189 is_playing = false;
1190 play_pending = false;
1191 playing = false;
1192 mpeg_file = -1;
1193
1194 while(1)
1195 {
1196#if CONFIG_CODEC == MAS3587F
1197 if(mpeg_mode == MPEG_DECODER)
1198 {
1199#endif /* CONFIG_CODEC == MAS3587F */
1200 yield();
1201
1202 /* Swap if necessary, and don't block on the queue_wait() */
1203 if(swap_one_chunk())
1204 {
1205 queue_wait_w_tmo(&mpeg_queue, &ev, 0);
1206 }
1207 else if (playing)
1208 {
1209 /* periodically update resume info */
1210 queue_wait_w_tmo(&mpeg_queue, &ev, HZ/2);
1211 }
1212 else
1213 {
1214 DEBUGF("S R:%x W:%x SW:%x\n",
1215 audiobuf_read, audiobuf_write, audiobuf_swapwrite);
1216 queue_wait(&mpeg_queue, &ev);
1217 }
1218
1219 start_playback_if_ready();
1220
1221 switch(ev.id)
1222 {
1223 case MPEG_PLAY:
1224 DEBUGF("MPEG_PLAY\n");
1225
1226#if CONFIG_TUNER
1227 /* Silence the A/D input, it may be on because the radio
1228 may be playing */
1229 mas_codec_writereg(6, 0x0000);
1230#endif /* CONFIG_TUNER */
1231
1232 /* Stop the current stream */
1233 paused = false;
1234 end_current_track();
1235
1236 if ( new_file(0) == -1 )
1237 {
1238 is_playing = false;
1239 track_change();
1240 break;
1241 }
1242
1243 start_offset = (int)ev.data;
1244
1245 /* mid-song resume? */
1246 if (start_offset) {
1247 struct mp3entry* id3 = &get_trackdata(0)->id3;
1248 lseek(mpeg_file, start_offset, SEEK_SET);
1249 id3->offset = start_offset;
1250 set_elapsed(id3);
1251 }
1252 else {
1253 /* skip past id3v2 tag */
1254 lseek(mpeg_file,
1255 get_trackdata(0)->id3.first_frame_offset,
1256 SEEK_SET);
1257
1258 }
1259
1260 /* Make it read more data */
1261 filling = true;
1262 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1263
1264 /* Tell the file loading code that we want to start playing
1265 as soon as we have some data */
1266 play_pending = true;
1267 play_pending_track_change = true;
1268
1269 update_playlist();
1270 current_track_counter++;
1271 break;
1272
1273 case MPEG_STOP:
1274 DEBUGF("MPEG_STOP\n");
1275 is_playing = false;
1276 paused = false;
1277
1278 if (playing)
1279 playlist_update_resume_info(audio_current_track());
1280
1281 stop_playing();
1282 mpeg_stop_done = true;
1283 break;
1284
1285 case MPEG_PAUSE:
1286 DEBUGF("MPEG_PAUSE\n");
1287 /* Stop the current stream */
1288 if (playing)
1289 playlist_update_resume_info(audio_current_track());
1290 paused = true;
1291 playing = false;
1292 pause_tick = current_tick;
1293 pause_track = current_track_counter;
1294 mp3_play_pause(false);
1295 break;
1296
1297 case MPEG_RESUME:
1298 DEBUGF("MPEG_RESUME\n");
1299 /* Continue the current stream */
1300 paused = false;
1301 if (!play_pending)
1302 {
1303 playing = true;
1304 if ( current_track_counter == pause_track )
1305 last_dma_tick += current_tick - pause_tick;
1306 else
1307 last_dma_tick = current_tick;
1308 pause_tick = 0;
1309 mp3_play_pause(true);
1310 }
1311 break;
1312
1313 case MPEG_NEXT:
1314 DEBUGF("MPEG_NEXT\n");
1315 /* is next track in ram? */
1316 if ( num_tracks_in_memory() > 1 ) {
1317 int unplayed_space_left, unswapped_space_left;
1318
1319 /* stop the current stream */
1320 play_pending = false;
1321 playing = false;
1322 mp3_play_pause(false);
1323
1324 track_change();
1325 audiobuf_read = get_trackdata(0)->mempos;
1326 last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song());
1327 mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end);
1328 dma_underrun = false;
1329 last_dma_tick = current_tick;
1330
1331 unplayed_space_left = get_unplayed_space();
1332 unswapped_space_left = get_unswapped_space();
1333
1334 /* should we start reading more data? */
1335 if(!filling && (unplayed_space_left < low_watermark)) {
1336 filling = true;
1337 queue_post(&mpeg_queue, MPEG_NEED_DATA, GENERATE_UNBUFFER_EVENTS);
1338 play_pending = true;
1339 } else if(unswapped_space_left &&
1340 unswapped_space_left > unplayed_space_left) {
1341 /* Stop swapping the data from the previous file */
1342 audiobuf_swapwrite = audiobuf_read;
1343 play_pending = true;
1344 } else {
1345 playing = true;
1346 if (!paused)
1347 mp3_play_pause(true);
1348 }
1349 }
1350 else {
1351 if (!playlist_check(1))
1352 break;
1353
1354 /* stop the current stream */
1355 end_current_track();
1356
1357 if (new_file(1) < 0) {
1358 DEBUGF("No more files to play\n");
1359 filling = false;
1360
1361 check_playlist_end(1);
1362 current_track_counter++;
1363 } else {
1364 /* Make it read more data */
1365 filling = true;
1366 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1367
1368 /* Tell the file loading code that we want
1369 to start playing as soon as we have some data */
1370 play_pending = true;
1371 play_pending_track_change = true;
1372
1373 update_playlist();
1374 current_track_counter++;
1375 }
1376 }
1377 break;
1378
1379 case MPEG_PREV: {
1380 DEBUGF("MPEG_PREV\n");
1381
1382 if (!playlist_check(-1))
1383 break;
1384
1385 /* stop the current stream */
1386 end_current_track();
1387
1388 /* Open the next file */
1389 if (new_file(-1) < 0) {
1390 DEBUGF("No more files to play\n");
1391 filling = false;
1392
1393 check_playlist_end(-1);
1394 current_track_counter++;
1395 } else {
1396 /* Make it read more data */
1397 filling = true;
1398 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1399
1400 /* Tell the file loading code that we want to
1401 start playing as soon as we have some data */
1402 play_pending = true;
1403 play_pending_track_change = true;
1404
1405 update_playlist();
1406 current_track_counter++;
1407 }
1408 break;
1409 }
1410
1411 case MPEG_FF_REWIND: {
1412 struct mp3entry *id3 = audio_current_track();
1413 unsigned int oldtime = id3->elapsed;
1414 unsigned int newtime = (unsigned int)ev.data;
1415 int curpos, newpos, diffpos;
1416 DEBUGF("MPEG_FF_REWIND\n");
1417
1418 id3->elapsed = newtime;
1419
1420 newpos = audio_get_file_pos();
1421 if(newpos < 0)
1422 {
1423 id3->elapsed = oldtime;
1424 break;
1425 }
1426
1427 if (mpeg_file >= 0)
1428 curpos = lseek(mpeg_file, 0, SEEK_CUR);
1429 else
1430 curpos = id3->filesize;
1431
1432 if (num_tracks_in_memory() > 1)
1433 {
1434 /* We have started loading other tracks that need to be
1435 accounted for */
1436 struct trackdata *track;
1437 int i = 0;
1438
1439 while((track = get_trackdata(i++)))
1440 {
1441 curpos += track->id3.filesize;
1442 }
1443 }
1444
1445 diffpos = curpos - newpos;
1446
1447 if(!filling && diffpos >= 0 && diffpos < audiobuflen)
1448 {
1449 int unplayed_space_left, unswapped_space_left;
1450
1451 /* We are changing to a position that's already in
1452 memory, so we just move the DMA read pointer. */
1453 audiobuf_read = audiobuf_write - diffpos;
1454 if (audiobuf_read < 0)
1455 {
1456 audiobuf_read += audiobuflen;
1457 }
1458
1459 unplayed_space_left = get_unplayed_space();
1460 unswapped_space_left = get_unswapped_space();
1461
1462 /* If unswapped_space_left is larger than
1463 unplayed_space_left, it means that the swapwrite pointer
1464 hasn't yet advanced up to the new location of the read
1465 pointer. We just move it, there is no need to swap
1466 data that won't be played anyway. */
1467
1468 if (unswapped_space_left > unplayed_space_left)
1469 {
1470 DEBUGF("Moved swapwrite\n");
1471 audiobuf_swapwrite = audiobuf_read;
1472 play_pending = true;
1473 }
1474
1475 if (mpeg_file>=0 && unplayed_space_left < low_watermark)
1476 {
1477 /* We need to load more data before starting */
1478 filling = true;
1479 queue_post(&mpeg_queue, MPEG_NEED_DATA, GENERATE_UNBUFFER_EVENTS);
1480 play_pending = true;
1481 }
1482 else
1483 {
1484 /* resume will start at new position */
1485 last_dma_chunk_size =
1486 MIN(0x2000, get_unplayed_space_current_song());
1487 mp3_play_data(audiobuf + audiobuf_read,
1488 last_dma_chunk_size, transfer_end);
1489 dma_underrun = false;
1490 }
1491 }
1492 else
1493 {
1494 /* Move to the new position in the file and start
1495 loading data */
1496 reset_mp3_buffer();
1497
1498 if (num_tracks_in_memory() > 1)
1499 {
1500 /* We have to reload the current track */
1501 close(mpeg_file);
1502 remove_all_non_current_tags();
1503 generate_unbuffer_events();
1504 mpeg_file = -1;
1505 }
1506
1507 if (mpeg_file < 0)
1508 {
1509 mpeg_file = open(id3->path, O_RDONLY);
1510 if (mpeg_file < 0)
1511 {
1512 id3->elapsed = oldtime;
1513 break;
1514 }
1515 }
1516
1517 if(-1 == lseek(mpeg_file, newpos, SEEK_SET))
1518 {
1519 id3->elapsed = oldtime;
1520 break;
1521 }
1522
1523 filling = true;
1524 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1525
1526 /* Tell the file loading code that we want to start playing
1527 as soon as we have some data */
1528 play_pending = true;
1529 }
1530
1531 id3->offset = newpos;
1532
1533 break;
1534 }
1535
1536 case MPEG_FLUSH_RELOAD: {
1537 int numtracks = num_tracks_in_memory();
1538 bool reload_track = false;
1539
1540 if (numtracks > 1)
1541 {
1542 /* Reset the buffer */
1543 audiobuf_write = get_trackdata(1)->mempos;
1544
1545 /* Reset swapwrite unless we're still swapping current
1546 track */
1547 if (get_unplayed_space() <= get_playable_space())
1548 audiobuf_swapwrite = audiobuf_write;
1549
1550 close(mpeg_file);
1551 remove_all_non_current_tags();
1552 generate_unbuffer_events();
1553 mpeg_file = -1;
1554 reload_track = true;
1555 }
1556 else if (numtracks == 1 && mpeg_file < 0)
1557 {
1558 reload_track = true;
1559 }
1560
1561 if(reload_track && new_file(1) >= 0)
1562 {
1563 /* Tell ourselves that we want more data */
1564 filling = true;
1565 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1566 }
1567
1568 break;
1569 }
1570
1571 case MPEG_NEED_DATA:
1572 free_space_left = audiobuf_read - audiobuf_write;
1573
1574 /* We interpret 0 as "empty buffer" */
1575 if(free_space_left <= 0)
1576 free_space_left += audiobuflen;
1577
1578 unplayed_space_left = audiobuflen - free_space_left;
1579
1580 /* Make sure that we don't fill the entire buffer */
1581 free_space_left -= MPEG_HIGH_WATER;
1582
1583 if (ev.data == GENERATE_UNBUFFER_EVENTS)
1584 generate_unbuffer_events();
1585
1586 /* do we have any more buffer space to fill? */
1587 if(free_space_left <= 0)
1588 {
1589 DEBUGF("0\n");
1590 filling = false;
1591 generate_postbuffer_events();
1592 ata_sleep();
1593 break;
1594 }
1595
1596 /* Read small chunks while we are below the low water mark */
1597 if(unplayed_space_left < low_watermark)
1598 amount_to_read = MIN(MPEG_LOW_WATER_CHUNKSIZE,
1599 free_space_left);
1600 else
1601 amount_to_read = free_space_left;
1602
1603 /* Don't read more than until the end of the buffer */
1604 amount_to_read = MIN(audiobuflen - audiobuf_write,
1605 amount_to_read);
1606#ifdef HAVE_MMC /* MMC is slow, so don't read too large chunks */
1607 amount_to_read = MIN(0x40000, amount_to_read);
1608#elif MEM == 8
1609 amount_to_read = MIN(0x100000, amount_to_read);
1610#endif
1611
1612 /* Read as much mpeg data as we can fit in the buffer */
1613 if(mpeg_file >= 0)
1614 {
1615 DEBUGF("R\n");
1616 t1 = current_tick;
1617 len = read(mpeg_file, audiobuf + audiobuf_write,
1618 amount_to_read);
1619 if(len > 0)
1620 {
1621 t2 = current_tick;
1622 DEBUGF("time: %d\n", t2 - t1);
1623 DEBUGF("R: %x\n", len);
1624
1625 /* Now make sure that we don't feed the MAS with ID3V1
1626 data */
1627 if (len < amount_to_read)
1628 {
1629 int i;
1630 static const unsigned char tag[] = "TAG";
1631 int taglen = 128;
1632 int tagptr = audiobuf_write + len - 128;
1633
1634 /* Really rare case: entire potential tag wasn't
1635 read in this call AND audiobuf_write < 128 */
1636 if (tagptr < 0)
1637 tagptr += audiobuflen;
1638
1639 for(i = 0;i < 3;i++)
1640 {
1641 if(tagptr >= audiobuflen)
1642 tagptr -= audiobuflen;
1643
1644 if(audiobuf[tagptr] != tag[i])
1645 {
1646 taglen = 0;
1647 break;
1648 }
1649
1650 tagptr++;
1651 }
1652
1653 if(taglen)
1654 {
1655 /* Skip id3v1 tag */
1656 DEBUGF("Skipping ID3v1 tag\n");
1657 len -= taglen;
1658
1659 /* In the very rare case when the entire tag
1660 wasn't read in this read() len will be < 0.
1661 Take care of this when changing the write
1662 pointer. */
1663 }
1664 }
1665
1666 audiobuf_write += len;
1667
1668 if (audiobuf_write < 0)
1669 audiobuf_write += audiobuflen;
1670
1671 if(audiobuf_write >= audiobuflen)
1672 {
1673 audiobuf_write = 0;
1674 DEBUGF("W\n");
1675 }
1676
1677 /* Tell ourselves that we want more data */
1678 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1679 }
1680 else
1681 {
1682 if(len < 0)
1683 {
1684 DEBUGF("MPEG read error\n");
1685 }
1686
1687 close(mpeg_file);
1688 mpeg_file = -1;
1689
1690 if(new_file(1) < 0)
1691 {
1692 /* No more data to play */
1693 DEBUGF("No more files to play\n");
1694 filling = false;
1695 }
1696 else
1697 {
1698 /* Tell ourselves that we want more data */
1699 queue_post(&mpeg_queue, MPEG_NEED_DATA, 0);
1700 }
1701 }
1702 }
1703 break;
1704
1705 case MPEG_TRACK_CHANGE:
1706 track_change();
1707 break;
1708
1709#ifndef USB_NONE
1710 case SYS_USB_CONNECTED:
1711 is_playing = false;
1712 paused = false;
1713 stop_playing();
1714
1715 /* Tell the USB thread that we are safe */
1716 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
1717 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1718
1719 /* Wait until the USB cable is extracted again */
1720 usb_wait_for_disconnect(&mpeg_queue);
1721 break;
1722#endif /* !USB_NONE */
1723
1724#if CONFIG_CODEC == MAS3587F
1725 case MPEG_INIT_RECORDING:
1726 init_recording();
1727 init_recording_done = true;
1728 break;
1729#endif /* CONFIG_CODEC == MAS3587F */
1730
1731 case SYS_TIMEOUT:
1732 if (playing)
1733 playlist_update_resume_info(audio_current_track());
1734 break;
1735 }
1736#if CONFIG_CODEC == MAS3587F
1737 }
1738 else
1739 {
1740 queue_wait(&mpeg_queue, &ev);
1741 switch(ev.id)
1742 {
1743 case MPEG_RECORD:
1744 if (is_prerecording)
1745 {
1746 int startpos;
1747
1748 /* Go back prerecord_count seconds in the buffer */
1749 startpos = prerecord_index - prerecord_count;
1750 if(startpos < 0)
1751 startpos += prerecording_max_seconds;
1752
1753 /* Read the position data from the prerecord buffer */
1754 frame_count_start = prerecord_buffer[startpos].framecount;
1755 startpos = prerecord_buffer[startpos].mempos;
1756
1757 DEBUGF("Start looking at address %x (%x)\n",
1758 audiobuf+startpos, startpos);
1759
1760 saved_header = mpeg_get_last_header();
1761
1762 mem_find_next_frame(startpos, &offset, 1800,
1763 saved_header);
1764
1765 audiobuf_read = startpos + offset;
1766 if(audiobuf_read >= audiobuflen)
1767 audiobuf_read -= audiobuflen;
1768
1769 DEBUGF("New audiobuf_read address: %x (%x)\n",
1770 audiobuf+audiobuf_read, audiobuf_read);
1771
1772 level = disable_irq_save();
1773 num_rec_bytes = get_unsaved_space();
1774 restore_irq(level);
1775 }
1776 else
1777 {
1778 frame_count_start = 0;
1779 num_rec_bytes = 0;
1780 audiobuf_read = MPEG_RESERVED_HEADER_SPACE;
1781 audiobuf_write = MPEG_RESERVED_HEADER_SPACE;
1782 }
1783
1784 prepend_header();
1785 DEBUGF("Recording...\n");
1786 start_recording();
1787
1788 /* Wait until at least one frame is encoded and get the
1789 frame header, for later use by the Xing header
1790 generation */
1791 sleep(HZ/5);
1792 saved_header = mpeg_get_last_header();
1793
1794 /* delayed until buffer is saved, don't open yet */
1795 strcpy(delayed_filename, recording_filename);
1796 mpeg_file = -1;
1797
1798 break;
1799
1800 case MPEG_STOP:
1801 DEBUGF("MPEG_STOP\n");
1802
1803 stop_recording();
1804
1805 /* Save the remaining data in the buffer */
1806 save_endpos = audiobuf_write;
1807 saving_status = STOP_RECORDING;
1808 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1809 break;
1810
1811 case MPEG_STOP_DONE:
1812 DEBUGF("MPEG_STOP_DONE\n");
1813
1814 if (mpeg_file >= 0)
1815 close(mpeg_file);
1816 mpeg_file = -1;
1817
1818 update_header();
1819#ifdef DEBUG1
1820 {
1821 int i;
1822 for(i = 0;i < 512;i++)
1823 {
1824 DEBUGF("%d - %d us (%d bytes)\n",
1825 timing_info[i*2],
1826 (timing_info[i*2+1] & 0xffff) *
1827 10000 / 13824,
1828 timing_info[i*2+1] >> 16);
1829 }
1830 }
1831#endif /* DEBUG1 */
1832
1833 if (prerecording)
1834 {
1835 start_prerecording();
1836 }
1837 mpeg_stop_done = true;
1838 break;
1839
1840 case MPEG_NEW_FILE:
1841 /* Bail out when a more important save is happening */
1842 if (saving_status > NEW_FILE)
1843 break;
1844
1845 /* Make sure we have at least one complete frame
1846 in the buffer. If we haven't recorded a single
1847 frame within 200ms, the MAS is probably not recording
1848 anything, and we bail out. */
1849 amount_to_save = get_unsaved_space();
1850 if (amount_to_save < 1800)
1851 {
1852 sleep(HZ/5);
1853 amount_to_save = get_unsaved_space();
1854 }
1855
1856 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT,
1857 &frame_count_end, 1);
1858
1859 last_rec_time = current_tick - record_start_time;
1860 record_start_time = current_tick;
1861 if (paused)
1862 pause_start_time = record_start_time;
1863
1864 /* capture all values at one point */
1865 level = disable_irq_save();
1866 save_endpos = audiobuf_write;
1867 last_rec_bytes = num_rec_bytes;
1868 num_rec_bytes = 0;
1869 restore_irq(level);
1870
1871 if (amount_to_save >= 1800)
1872 {
1873 /* Now find a frame boundary to split at */
1874 save_endpos -= 1800;
1875 if (save_endpos < 0)
1876 save_endpos += audiobuflen;
1877
1878 rc = mem_find_next_frame(save_endpos, &offset, 1800,
1879 saved_header);
1880 if (!rc) /* No header found, save whole buffer */
1881 offset = 1800;
1882
1883 save_endpos += offset;
1884 if (save_endpos >= audiobuflen)
1885 save_endpos -= audiobuflen;
1886
1887 last_rec_bytes += offset - 1800;
1888 level = disable_irq_save();
1889 num_rec_bytes += 1800 - offset;
1890 restore_irq(level);
1891 }
1892
1893 saving_status = NEW_FILE;
1894 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1895 break;
1896
1897 case MPEG_SAVE_DATA:
1898 if (saving_status == BUFFER_FULL)
1899 save_endpos = audiobuf_write;
1900
1901 if (mpeg_file < 0) /* delayed file open */
1902 {
1903 mpeg_file = open(delayed_filename, O_WRONLY|O_CREAT);
1904
1905 if (mpeg_file < 0)
1906 panicf("recfile: %d", mpeg_file);
1907 }
1908
1909 amount_to_save = save_endpos - audiobuf_read;
1910 if (amount_to_save < 0)
1911 amount_to_save += audiobuflen;
1912
1913 amount_to_save = MIN(amount_to_save,
1914 audiobuflen - audiobuf_read);
1915#ifdef HAVE_MMC /* MMC is slow, so don't save too large chunks at once */
1916 amount_to_save = MIN(0x40000, amount_to_save);
1917#elif MEM == 8
1918 amount_to_save = MIN(0x100000, amount_to_save);
1919#endif
1920 rc = write(mpeg_file, audiobuf + audiobuf_read,
1921 amount_to_save);
1922 if (rc < 0)
1923 {
1924 if (errno == ENOSPC)
1925 {
1926 mpeg_errno = AUDIOERR_DISK_FULL;
1927 stop_recording();
1928 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1929 /* will close the file */
1930 break;
1931 }
1932 else
1933 panicf("rec wrt: %d", rc);
1934 }
1935
1936 audiobuf_read += amount_to_save;
1937 if (audiobuf_read >= audiobuflen)
1938 audiobuf_read = 0;
1939
1940 if (audiobuf_read == save_endpos) /* all saved */
1941 {
1942 switch (saving_status)
1943 {
1944 case BUFFER_FULL:
1945 rc = fsync(mpeg_file);
1946 if (rc < 0)
1947 panicf("rec fls: %d", rc);
1948 ata_sleep();
1949 break;
1950
1951 case NEW_FILE:
1952 /* Close the current file */
1953 rc = close(mpeg_file);
1954 if (rc < 0)
1955 panicf("rec cls: %d", rc);
1956 mpeg_file = -1;
1957 update_header();
1958 ata_sleep();
1959
1960 /* copy new filename */
1961 strcpy(delayed_filename, recording_filename);
1962 prepend_header();
1963 frame_count_start = frame_count_end;
1964 break;
1965
1966 case STOP_RECORDING:
1967 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1968 /* will close the file */
1969 break;
1970
1971 default:
1972 break;
1973 }
1974 saving_status = NOT_SAVING;
1975 }
1976 else /* tell ourselves to save the next chunk */
1977 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1978
1979 break;
1980
1981 case MPEG_PRERECORDING_TICK:
1982 if(!is_prerecording)
1983 break;
1984
1985 /* Store the write pointer every second */
1986 prerecord_buffer[prerecord_index].mempos = audiobuf_write;
1987 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT,
1988 &prerecord_buffer[prerecord_index].framecount, 1);
1989
1990 /* Wrap if necessary */
1991 if(++prerecord_index == prerecording_max_seconds)
1992 prerecord_index = 0;
1993
1994 /* Update the number of seconds recorded */
1995 if(prerecord_count < prerecording_max_seconds)
1996 prerecord_count++;
1997 break;
1998
1999 case MPEG_INIT_PLAYBACK:
2000 /* Stop the prerecording */
2001 stop_recording();
2002 reset_mp3_buffer();
2003 mp3_play_init();
2004 init_playback_done = true;
2005 break;
2006
2007 case MPEG_PAUSE_RECORDING:
2008 pause_recording();
2009 break;
2010
2011 case MPEG_RESUME_RECORDING:
2012 resume_recording();
2013 break;
2014
2015 case SYS_USB_CONNECTED:
2016 /* We can safely go to USB mode if no recording
2017 is taking place */
2018 if((!is_recording || is_prerecording) && mpeg_stop_done)
2019 {
2020 /* Even if we aren't recording, we still call this
2021 function, to put the MAS in monitoring mode,
2022 to save power. */
2023 stop_recording();
2024
2025 /* Tell the USB thread that we are safe */
2026 DEBUGF("mpeg_thread got SYS_USB_CONNECTED\n");
2027 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2028
2029 /* Wait until the USB cable is extracted again */
2030 usb_wait_for_disconnect(&mpeg_queue);
2031 }
2032 break;
2033 }
2034 }
2035#endif /* CONFIG_CODEC == MAS3587F */
2036 }
2037}
2038#endif /* !SIMULATOR */
2039
2040struct mp3entry* audio_current_track()
2041{
2042#ifdef SIMULATOR
2043 return &taginfo;
2044#else /* !SIMULATOR */
2045 if(num_tracks_in_memory())
2046 return &get_trackdata(0)->id3;
2047 else
2048 return NULL;
2049#endif /* !SIMULATOR */
2050}
2051
2052struct mp3entry* audio_next_track()
2053{
2054#ifdef SIMULATOR
2055 return &taginfo;
2056#else /* !SIMULATOR */
2057 if(num_tracks_in_memory() > 1)
2058 return &get_trackdata(1)->id3;
2059 else
2060 return NULL;
2061#endif /* !SIMULATOR */
2062}
2063
2064bool audio_has_changed_track(void)
2065{
2066 if(last_track_counter != current_track_counter)
2067 {
2068 last_track_counter = current_track_counter;
2069 return true;
2070 }
2071 return false;
2072}
2073
2074#if CONFIG_CODEC == MAS3587F
2075#ifndef SIMULATOR
2076void audio_init_playback(void)
2077{
2078 init_playback_done = false;
2079 queue_post(&mpeg_queue, MPEG_INIT_PLAYBACK, 0);
2080
2081 while(!init_playback_done)
2082 sleep(1);
2083}
2084
2085
2086/****************************************************************************
2087 * Recording functions
2088 ***************************************************************************/
2089void audio_init_recording(unsigned int buffer_offset)
2090{
2091 buffer_offset = buffer_offset;
2092 init_recording_done = false;
2093 queue_post(&mpeg_queue, MPEG_INIT_RECORDING, 0);
2094
2095 while(!init_recording_done)
2096 sleep(1);
2097}
2098
2099static void init_recording(void)
2100{
2101 unsigned long val;
2102 int rc;
2103
2104 /* Disable IRQ6 */
2105 IPRB &= 0xff0f;
2106
2107 stop_playing();
2108 is_playing = false;
2109 paused = false;
2110
2111 /* Init the recording variables */
2112 is_recording = false;
2113 is_prerecording = false;
2114
2115 mpeg_stop_done = true;
2116
2117 mas_reset();
2118
2119 /* Enable the audio CODEC and the DSP core, max analog voltage range */
2120 rc = mas_direct_config_write(MAS_CONTROL, 0x8c00);
2121 if(rc < 0)
2122 panicf("mas_ctrl_w: %d", rc);
2123
2124 /* Stop the current application */
2125 val = 0;
2126 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
2127 do
2128 {
2129 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
2130 } while(val);
2131
2132 /* Perform black magic as described by the data sheet */
2133 if((mas_version_code & 0x0fff) == 0x0102)
2134 {
2135 DEBUGF("Performing MAS black magic for B2 version\n");
2136 mas_writereg(0xa3, 0x98);
2137 mas_writereg(0x94, 0xfffff);
2138 val = 0;
2139 mas_writemem(MAS_BANK_D1, 0, &val, 1);
2140 mas_writereg(0xa3, 0x90);
2141 }
2142
2143 /* Enable A/D Converters */
2144 shadow_codec_reg0 = 0xcccd;
2145 mas_codec_writereg(0x0, shadow_codec_reg0);
2146
2147 /* Copy left channel to right (mono mode) */
2148 mas_codec_writereg(8, 0x8000);
2149
2150 /* ADC scale 0%, DSP scale 100%
2151 We use the DSP output for monitoring, because it works with all
2152 sources including S/PDIF */
2153 mas_codec_writereg(6, 0x0000);
2154 mas_codec_writereg(7, 0x4000);
2155
2156 /* No mute */
2157 shadow_soft_mute = 0;
2158 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute, 1);
2159
2160#ifdef HAVE_SPDIF_OUT
2161 val = 0x09; /* Disable SDO and SDI, low impedance S/PDIF outputs */
2162#else
2163 val = 0x2d; /* Disable SDO and SDI, disable S/PDIF output */
2164#endif
2165 mas_writemem(MAS_BANK_D0, MAS_D0_INTERFACE_CONTROL, &val, 1);
2166
2167 /* Set Demand mode, monitoring OFF and validate all settings */
2168 shadow_io_control_main = 0x125;
2169 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
2170
2171 /* Start the encoder application */
2172 val = 0x40;
2173 mas_writemem(MAS_BANK_D0, MAS_D0_APP_SELECT, &val, 1);
2174 do
2175 {
2176 mas_readmem(MAS_BANK_D0, MAS_D0_APP_RUNNING, &val, 1);
2177 } while(!(val & 0x40));
2178
2179 /* We have started the recording application with monitoring OFF.
2180 This is because we want to record at least one frame to fill the DMA
2181 buffer, because the silly MAS will not negate EOD until at least one
2182 DMA transfer has taken place.
2183 Now let's wait for some data to be encoded. */
2184 sleep(HZ/5);
2185
2186 /* Now set it to Monitoring mode as default, saves power */
2187 shadow_io_control_main = 0x525;
2188 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
2189
2190 /* Wait until the DSP has accepted the settings */
2191 do
2192 {
2193 mas_readmem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &val,1);
2194 } while(val & 1);
2195
2196 drain_dma_buffer();
2197 mpeg_mode = MPEG_ENCODER;
2198
2199 DEBUGF("MAS Recording application started\n");
2200
2201 /* At this point, all settings are the reset MAS defaults, next thing is to
2202 call mpeg_set_recording_options(). */
2203}
2204
2205void audio_record(const char *filename)
2206{
2207 mpeg_errno = 0;
2208
2209 strncpy(recording_filename, filename, MAX_PATH - 1);
2210 recording_filename[MAX_PATH - 1] = 0;
2211
2212 queue_post(&mpeg_queue, MPEG_RECORD, 0);
2213}
2214
2215void audio_pause_recording(void)
2216{
2217 queue_post(&mpeg_queue, MPEG_PAUSE_RECORDING, 0);
2218}
2219
2220void audio_resume_recording(void)
2221{
2222 queue_post(&mpeg_queue, MPEG_RESUME_RECORDING, 0);
2223}
2224
2225static void prepend_header(void)
2226{
2227 int startpos;
2228 unsigned i;
2229
2230 /* Make room for header */
2231 audiobuf_read -= MPEG_RESERVED_HEADER_SPACE;
2232 if(audiobuf_read < 0)
2233 {
2234 /* Clear the bottom half */
2235 memset(audiobuf, 0, audiobuf_read + MPEG_RESERVED_HEADER_SPACE);
2236
2237 /* And the top half */
2238 audiobuf_read += audiobuflen;
2239 memset(audiobuf + audiobuf_read, 0, audiobuflen - audiobuf_read);
2240 }
2241 else
2242 {
2243 memset(audiobuf + audiobuf_read, 0, MPEG_RESERVED_HEADER_SPACE);
2244 }
2245 /* Copy the empty ID3 header */
2246 startpos = audiobuf_read;
2247 for(i = 0; i < sizeof(empty_id3_header); i++)
2248 {
2249 audiobuf[startpos++] = empty_id3_header[i];
2250 if(startpos == audiobuflen)
2251 startpos = 0;
2252 }
2253}
2254
2255static void update_header(void)
2256{
2257 int fd, framelen;
2258 unsigned long frames;
2259
2260 if (last_rec_bytes > 0)
2261 {
2262 /* Create the Xing header */
2263 fd = open(delayed_filename, O_RDWR);
2264 if (fd < 0)
2265 panicf("rec upd: %d (%s)", fd, recording_filename);
2266
2267 frames = frame_count_end - frame_count_start;
2268 /* If the number of recorded frames has reached 0x7ffff,
2269 we can no longer trust it */
2270 if (frame_count_end == 0x7ffff)
2271 frames = 0;
2272
2273 /* saved_header is saved right before stopping the MAS */
2274 framelen = create_xing_header(fd, 0, last_rec_bytes, xing_buffer,
2275 frames, last_rec_time * (1000/HZ),
2276 saved_header, NULL, false);
2277
2278 lseek(fd, MPEG_RESERVED_HEADER_SPACE - framelen, SEEK_SET);
2279 write(fd, xing_buffer, framelen);
2280 close(fd);
2281 }
2282}
2283
2284static void start_prerecording(void)
2285{
2286 unsigned long val;
2287
2288 DEBUGF("Starting prerecording\n");
2289
2290 prerecord_index = 0;
2291 prerecord_count = 0;
2292 prerecord_timeout = current_tick + HZ;
2293 memset(prerecord_buffer, 0, sizeof(prerecord_buffer));
2294 reset_mp3_buffer();
2295
2296 is_prerecording = true;
2297
2298 /* Stop monitoring and start the encoder */
2299 shadow_io_control_main &= ~(1 << 10);
2300 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
2301 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
2302
2303 /* Wait until the DSP has accepted the settings */
2304 do
2305 {
2306 mas_readmem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &val,1);
2307 } while(val & 1);
2308
2309 is_recording = true;
2310 saving_status = NOT_SAVING;
2311
2312 demand_irq_enable(true);
2313}
2314
2315static void start_recording(void)
2316{
2317 unsigned long val;
2318
2319 if(is_prerecording)
2320 {
2321 /* This will make the IRQ handler start recording
2322 for real, i.e send MPEG_SAVE_DATA messages when
2323 the buffer is full */
2324 is_prerecording = false;
2325 }
2326 else
2327 {
2328 /* If prerecording is off, we need to stop the monitoring
2329 and start the encoder */
2330 shadow_io_control_main &= ~(1 << 10);
2331 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
2332 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
2333
2334 /* Wait until the DSP has accepted the settings */
2335 do
2336 {
2337 mas_readmem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &val,1);
2338 } while(val & 1);
2339 }
2340
2341 is_recording = true;
2342 saving_status = NOT_SAVING;
2343 paused = false;
2344
2345 /* Store the current time */
2346 if(prerecording)
2347 record_start_time = current_tick - prerecord_count * HZ;
2348 else
2349 record_start_time = current_tick;
2350
2351 pause_start_time = 0;
2352
2353 demand_irq_enable(true);
2354}
2355
2356static void pause_recording(void)
2357{
2358 pause_start_time = current_tick;
2359
2360 /* Set the pause bit */
2361 shadow_soft_mute |= 2;
2362 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute, 1);
2363
2364 paused = true;
2365}
2366
2367static void resume_recording(void)
2368{
2369 paused = false;
2370
2371 /* Clear the pause bit */
2372 shadow_soft_mute &= ~2;
2373 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute, 1);
2374
2375 /* Compensate for the time we have been paused */
2376 if(pause_start_time)
2377 {
2378 record_start_time =
2379 current_tick - (pause_start_time - record_start_time);
2380 pause_start_time = 0;
2381 }
2382}
2383
2384static void stop_recording(void)
2385{
2386 unsigned long val;
2387
2388 /* Let it finish the last frame */
2389 if(!paused)
2390 pause_recording();
2391 sleep(HZ/5);
2392
2393 demand_irq_enable(false);
2394
2395 is_recording = false;
2396 is_prerecording = false;
2397
2398 last_rec_bytes = num_rec_bytes;
2399 mas_readmem(MAS_BANK_D0, MAS_D0_MPEG_FRAME_COUNT, &frame_count_end, 1);
2400 last_rec_time = current_tick - record_start_time;
2401
2402 /* Start monitoring */
2403 shadow_io_control_main |= (1 << 10);
2404 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main, 1);
2405 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
2406
2407 /* Wait until the DSP has accepted the settings */
2408 do
2409 {
2410 mas_readmem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &val,1);
2411 } while(val & 1);
2412
2413 resume_recording();
2414}
2415
2416void audio_set_recording_options(struct audio_recording_options *options)
2417{
2418 bool is_mpeg1;
2419
2420 is_mpeg1 = (options->rec_frequency < 3)?true:false;
2421
2422 rec_version_index = is_mpeg1?3:2;
2423 rec_frequency_index = options->rec_frequency % 3;
2424
2425 shadow_encoder_control = (options->rec_quality << 17) |
2426 (rec_frequency_index << 10) |
2427 ((is_mpeg1?1:0) << 9) |
2428 (((options->rec_channels * 2 + 1) & 3) << 6) |
2429 (1 << 5) /* MS-stereo */ |
2430 (1 << 2) /* Is an original */;
2431 mas_writemem(MAS_BANK_D0, MAS_D0_ENCODER_CONTROL, &shadow_encoder_control,1);
2432
2433 DEBUGF("mas_writemem(MAS_BANK_D0, ENCODER_CONTROL, %x)\n", shadow_encoder_control);
2434
2435 shadow_soft_mute = options->rec_editable?4:0;
2436 mas_writemem(MAS_BANK_D0, MAS_D0_SOFT_MUTE, &shadow_soft_mute,1);
2437
2438 DEBUGF("mas_writemem(MAS_BANK_D0, SOFT_MUTE, %x)\n", shadow_soft_mute);
2439
2440 shadow_io_control_main = ((1 << 10) | /* Monitoring ON */
2441 ((options->rec_source < 2)?1:2) << 8) | /* Input select */
2442 (1 << 5) | /* SDO strobe invert */
2443 ((is_mpeg1?0:1) << 3) |
2444 (1 << 2) | /* Inverted SIBC clock signal */
2445 1; /* Validate */
2446 mas_writemem(MAS_BANK_D0, MAS_D0_IO_CONTROL_MAIN, &shadow_io_control_main,1);
2447
2448 DEBUGF("mas_writemem(MAS_BANK_D0, IO_CONTROL_MAIN, %x)\n", shadow_io_control_main);
2449
2450 if(options->rec_source == AUDIO_SRC_MIC)
2451 {
2452 /* Copy left channel to right (mono mode) */
2453 mas_codec_writereg(8, 0x8000);
2454 }
2455 else
2456 {
2457 /* Stereo input mode */
2458 mas_codec_writereg(8, 0);
2459 }
2460
2461 prerecording_max_seconds = options->rec_prerecord_time;
2462 if(prerecording_max_seconds)
2463 {
2464 prerecording = true;
2465 start_prerecording();
2466 }
2467 else
2468 {
2469 prerecording = false;
2470 is_prerecording = false;
2471 is_recording = false;
2472 }
2473}
2474
2475/* If use_mic is true, the left gain is used */
2476void audio_set_recording_gain(int left, int right, int type)
2477{
2478 /* Enable both left and right A/D */
2479 shadow_codec_reg0 = (left << 12) |
2480 (right << 8) |
2481 (left << 4) |
2482 (type==AUDIO_GAIN_MIC?0x0008:0) | /* Connect left A/D to mic */
2483 0x0007;
2484 mas_codec_writereg(0x0, shadow_codec_reg0);
2485}
2486
2487#if CONFIG_TUNER & S1A0903X01
2488/* Get the (unpitched) MAS PLL frequency, for avoiding FM interference with the
2489 * Samsung tuner. Zero means unknown. Currently handles recording from analog
2490 * input only. */
2491int mpeg_get_mas_pllfreq(void)
2492{
2493 if (mpeg_mode != MPEG_ENCODER)
2494 return 0;
2495
2496 if (rec_frequency_index == 0) /* 44.1 kHz / 22.05 kHz */
2497 return 22579000;
2498 else
2499 return 24576000;
2500}
2501#endif /* CONFIG_TUNER & S1A0903X01 */
2502
2503/* try to make some kind of beep, also in recording mode */
2504void audio_beep(int duration)
2505{
2506 long starttick = current_tick;
2507 do
2508 { /* toggle bit 0 of codec register 0, toggling the DAC off & on.
2509 * While this is still audible even without an external signal,
2510 * it doesn't affect the (pre-)recording. */
2511 mas_codec_writereg(0, shadow_codec_reg0 ^ 1);
2512 mas_codec_writereg(0, shadow_codec_reg0);
2513 yield();
2514 }
2515 while (current_tick - starttick < duration);
2516}
2517
2518void audio_new_file(const char *filename)
2519{
2520 mpeg_errno = 0;
2521
2522 strncpy(recording_filename, filename, MAX_PATH - 1);
2523 recording_filename[MAX_PATH - 1] = 0;
2524
2525 queue_post(&mpeg_queue, MPEG_NEW_FILE, 0);
2526}
2527
2528unsigned long audio_recorded_time(void)
2529{
2530 if(is_prerecording)
2531 return prerecord_count * HZ;
2532
2533 if(is_recording)
2534 {
2535 if(paused)
2536 return pause_start_time - record_start_time;
2537 else
2538 return current_tick - record_start_time;
2539 }
2540
2541 return 0;
2542}
2543
2544unsigned long audio_num_recorded_bytes(void)
2545{
2546 int num_bytes;
2547 int index;
2548
2549 if(is_recording)
2550 {
2551 if(is_prerecording)
2552 {
2553 index = prerecord_index - prerecord_count;
2554 if(index < 0)
2555 index += prerecording_max_seconds;
2556
2557 num_bytes = audiobuf_write - prerecord_buffer[index].mempos;
2558 if(num_bytes < 0)
2559 num_bytes += audiobuflen;
2560
2561 return num_bytes;;
2562 }
2563 else
2564 return num_rec_bytes;
2565 }
2566 else
2567 return 0;
2568}
2569
2570#else /* SIMULATOR */
2571
2572/* dummies coming up */
2573
2574void audio_init_playback(void)
2575{
2576 /* a dummy */
2577}
2578unsigned long audio_recorded_time(void)
2579{
2580 /* a dummy */
2581 return 0;
2582}
2583void audio_beep(int duration)
2584{
2585 /* a dummy */
2586 (void)duration;
2587}
2588void audio_pause_recording(void)
2589{
2590 /* a dummy */
2591}
2592void audio_resume_recording(void)
2593{
2594 /* a dummy */
2595}
2596unsigned long audio_num_recorded_bytes(void)
2597{
2598 /* a dummy */
2599 return 0;
2600}
2601void audio_record(const char *filename)
2602{
2603 /* a dummy */
2604 (void)filename;
2605}
2606void audio_new_file(const char *filename)
2607{
2608 /* a dummy */
2609 (void)filename;
2610}
2611
2612void audio_set_recording_gain(int left, int right, int type)
2613{
2614 /* a dummy */
2615 (void)left;
2616 (void)right;
2617 (void)type;
2618}
2619void audio_init_recording(unsigned int buffer_offset)
2620{
2621 /* a dummy */
2622 (void)buffer_offset;
2623}
2624void audio_set_recording_options(struct audio_recording_options *options)
2625{
2626 /* a dummy */
2627 (void)options;
2628}
2629#endif /* SIMULATOR */
2630#endif /* CONFIG_CODEC == MAS3587F */
2631
2632void audio_play(long offset)
2633{
2634#ifdef SIMULATOR
2635 char* trackname;
2636 int steps=0;
2637
2638 is_playing = true;
2639
2640 do {
2641 trackname = playlist_peek( steps );
2642 if (!trackname)
2643 break;
2644 if(mp3info(&taginfo, trackname)) {
2645 /* bad mp3, move on */
2646 if(++steps > playlist_amount())
2647 break;
2648 continue;
2649 }
2650#ifdef HAVE_MPEG_PLAY
2651 real_mpeg_play(trackname);
2652#endif
2653 playlist_next(steps);
2654 taginfo.offset = offset;
2655 set_elapsed(&taginfo);
2656 is_playing = true;
2657 playing = true;
2658 break;
2659 } while(1);
2660#else /* !SIMULATOR */
2661 is_playing = true;
2662
2663 queue_post(&mpeg_queue, MPEG_PLAY, offset);
2664#endif /* !SIMULATOR */
2665
2666 mpeg_errno = 0;
2667}
2668
2669void audio_stop(void)
2670{
2671#ifndef SIMULATOR
2672 if (playing)
2673 {
2674 struct trackdata *track = get_trackdata(0);
2675 prev_track_elapsed = track->id3.elapsed;
2676 }
2677 mpeg_stop_done = false;
2678 queue_post(&mpeg_queue, MPEG_STOP, 0);
2679 while(!mpeg_stop_done)
2680 yield();
2681#else /* SIMULATOR */
2682 paused = false;
2683 is_playing = false;
2684 playing = false;
2685#endif /* SIMULATOR */
2686}
2687
2688/* dummy */
2689void audio_stop_recording(void)
2690{
2691 audio_stop();
2692}
2693
2694void audio_pause(void)
2695{
2696#ifndef SIMULATOR
2697 queue_post(&mpeg_queue, MPEG_PAUSE, 0);
2698#else /* SIMULATOR */
2699 is_playing = true;
2700 playing = false;
2701 paused = true;
2702#endif /* SIMULATOR */
2703}
2704
2705void audio_resume(void)
2706{
2707#ifndef SIMULATOR
2708 queue_post(&mpeg_queue, MPEG_RESUME, 0);
2709#else /* SIMULATOR */
2710 is_playing = true;
2711 playing = true;
2712 paused = false;
2713#endif /* SIMULATOR */
2714}
2715
2716void audio_next(void)
2717{
2718#ifndef SIMULATOR
2719 queue_remove_from_head(&mpeg_queue, MPEG_NEED_DATA);
2720 queue_post(&mpeg_queue, MPEG_NEXT, 0);
2721#else /* SIMULATOR */
2722 char* file;
2723 int steps = 1;
2724 int index;
2725
2726 do {
2727 file = playlist_peek(steps);
2728 if(!file)
2729 break;
2730 if(mp3info(&taginfo, file)) {
2731 if(++steps > playlist_amount())
2732 break;
2733 continue;
2734 }
2735 index = playlist_next(steps);
2736 taginfo.index = index;
2737 current_track_counter++;
2738 is_playing = true;
2739 playing = true;
2740 break;
2741 } while(1);
2742#endif /* SIMULATOR */
2743}
2744
2745void audio_prev(void)
2746{
2747#ifndef SIMULATOR
2748 queue_remove_from_head(&mpeg_queue, MPEG_NEED_DATA);
2749 queue_post(&mpeg_queue, MPEG_PREV, 0);
2750#else /* SIMULATOR */
2751 char* file;
2752 int steps = -1;
2753 int index;
2754
2755 do {
2756 file = playlist_peek(steps);
2757 if(!file)
2758 break;
2759 if(mp3info(&taginfo, file)) {
2760 steps--;
2761 continue;
2762 }
2763 index = playlist_next(steps);
2764 taginfo.index = index;
2765 current_track_counter++;
2766 is_playing = true;
2767 playing = true;
2768 break;
2769 } while(1);
2770#endif /* SIMULATOR */
2771}
2772
2773void audio_ff_rewind(long newtime)
2774{
2775#ifndef SIMULATOR
2776 queue_post(&mpeg_queue, MPEG_FF_REWIND, newtime);
2777#else /* SIMULATOR */
2778 (void)newtime;
2779#endif /* SIMULATOR */
2780}
2781
2782void audio_flush_and_reload_tracks(void)
2783{
2784#ifndef SIMULATOR
2785 queue_post(&mpeg_queue, MPEG_FLUSH_RELOAD, 0);
2786#endif /* !SIMULATOR*/
2787}
2788
2789int audio_status(void)
2790{
2791 int ret = 0;
2792
2793 if(is_playing)
2794 ret |= AUDIO_STATUS_PLAY;
2795
2796 if(paused)
2797 ret |= AUDIO_STATUS_PAUSE;
2798
2799#if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
2800 if(is_recording && !is_prerecording)
2801 ret |= AUDIO_STATUS_RECORD;
2802
2803 if(is_prerecording)
2804 ret |= AUDIO_STATUS_PRERECORD;
2805#endif /* CONFIG_CODEC == MAS3587F */
2806
2807 if(mpeg_errno)
2808 ret |= AUDIO_STATUS_ERROR;
2809
2810 return ret;
2811}
2812
2813unsigned int audio_error(void)
2814{
2815 return mpeg_errno;
2816}
2817
2818void audio_error_clear(void)
2819{
2820 mpeg_errno = 0;
2821}
2822
2823#ifdef SIMULATOR
2824static void mpeg_thread(void)
2825{
2826 struct mp3entry* id3;
2827 while ( 1 ) {
2828 if (is_playing) {
2829 id3 = audio_current_track();
2830 if (!paused)
2831 {
2832 id3->elapsed+=1000;
2833 id3->offset+=1000;
2834 }
2835 if (id3->elapsed>=id3->length)
2836 audio_next();
2837 }
2838 sleep(HZ);
2839 }
2840}
2841#endif /* SIMULATOR */
2842
2843void audio_init(void)
2844{
2845 mpeg_errno = 0;
2846
2847#ifndef SIMULATOR
2848 audiobuflen = audiobufend - audiobuf;
2849 queue_init(&mpeg_queue, true);
2850#endif /* !SIMULATOR */
2851 create_thread(mpeg_thread, mpeg_stack,
2852 sizeof(mpeg_stack), 0, mpeg_thread_name
2853 IF_PRIO(, PRIORITY_SYSTEM)
2854 IF_COP(, CPU));
2855
2856 memset(trackdata, sizeof(trackdata), 0);
2857
2858#if (CONFIG_CODEC == MAS3587F) && !defined(SIMULATOR)
2859 if (HW_MASK & PR_ACTIVE_HIGH)
2860 and_b(~0x08, &PADRH);
2861 else
2862 or_b(0x08, &PADRH);
2863#endif /* CONFIG_CODEC == MAS3587F */
2864
2865#ifdef DEBUG
2866#ifndef SIMULATOR
2867 dbg_timer_start();
2868 dbg_cnt2us(0);
2869#endif /* !SIMULATOR */
2870#endif /* DEBUG */
2871}
2872
2873#endif /* CONFIG_CODEC != SWCODEC */
diff --git a/apps/replaygain.c b/apps/replaygain.c
new file mode 100644
index 0000000000..e160a1b23d
--- /dev/null
+++ b/apps/replaygain.c
@@ -0,0 +1,457 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Magnus Holmgren
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
22#include <ctype.h>
23#include <inttypes.h>
24#include <math.h>
25#include <stdbool.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <system.h>
30#include "id3.h"
31#include "debug.h"
32#include "replaygain.h"
33
34/* The fixed point math routines (with the exception of fp_atof) are based
35 * on oMathFP by Dan Carter (http://orbisstudios.com).
36 */
37
38/* 12 bits of precision gives fairly accurate result, but still allows a
39 * compact implementation. The math code supports up to 13...
40 */
41
42#define FP_BITS (12)
43#define FP_MASK ((1 << FP_BITS) - 1)
44#define FP_ONE (1 << FP_BITS)
45#define FP_TWO (2 << FP_BITS)
46#define FP_HALF (1 << (FP_BITS - 1))
47#define FP_LN2 ( 45426 >> (16 - FP_BITS))
48#define FP_LN2_INV ( 94548 >> (16 - FP_BITS))
49#define FP_EXP_ZERO ( 10922 >> (16 - FP_BITS))
50#define FP_EXP_ONE ( -182 >> (16 - FP_BITS))
51#define FP_EXP_TWO ( 4 >> (16 - FP_BITS))
52#define FP_INF (0x7fffffff)
53#define FP_LN10 (150902 >> (16 - FP_BITS))
54
55#define FP_MAX_DIGITS (4)
56#define FP_MAX_DIGITS_INT (10000)
57
58#define FP_FAST_MUL_DIV
59
60#ifdef FP_FAST_MUL_DIV
61
62/* These macros can easily overflow, but they are good enough for our uses,
63 * and saves some code.
64 */
65#define fp_mul(x, y) (((x) * (y)) >> FP_BITS)
66#define fp_div(x, y) (((x) << FP_BITS) / (y))
67
68#else
69
70static long fp_mul(long x, long y)
71{
72 long x_neg = 0;
73 long y_neg = 0;
74 long rc;
75
76 if ((x == 0) || (y == 0))
77 {
78 return 0;
79 }
80
81 if (x < 0)
82 {
83 x_neg = 1;
84 x = -x;
85 }
86
87 if (y < 0)
88 {
89 y_neg = 1;
90 y = -y;
91 }
92
93 rc = (((x >> FP_BITS) * (y >> FP_BITS)) << FP_BITS)
94 + (((x & FP_MASK) * (y & FP_MASK)) >> FP_BITS)
95 + ((x & FP_MASK) * (y >> FP_BITS))
96 + ((x >> FP_BITS) * (y & FP_MASK));
97
98 if ((x_neg ^ y_neg) == 1)
99 {
100 rc = -rc;
101 }
102
103 return rc;
104}
105
106static long fp_div(long x, long y)
107{
108 long x_neg = 0;
109 long y_neg = 0;
110 long shifty;
111 long rc;
112 int msb = 0;
113 int lsb = 0;
114
115 if (x == 0)
116 {
117 return 0;
118 }
119
120 if (y == 0)
121 {
122 return (x < 0) ? -FP_INF : FP_INF;
123 }
124
125 if (x < 0)
126 {
127 x_neg = 1;
128 x = -x;
129 }
130
131 if (y < 0)
132 {
133 y_neg = 1;
134 y = -y;
135 }
136
137 while ((x & (1 << (30 - msb))) == 0)
138 {
139 msb++;
140 }
141
142 while ((y & (1 << lsb)) == 0)
143 {
144 lsb++;
145 }
146
147 shifty = FP_BITS - (msb + lsb);
148 rc = ((x << msb) / (y >> lsb));
149
150 if (shifty > 0)
151 {
152 rc <<= shifty;
153 }
154 else
155 {
156 rc >>= -shifty;
157 }
158
159 if ((x_neg ^ y_neg) == 1)
160 {
161 rc = -rc;
162 }
163
164 return rc;
165}
166
167#endif /* FP_FAST_MUL_DIV */
168
169static long fp_exp(long x)
170{
171 long k;
172 long z;
173 long R;
174 long xp;
175
176 if (x == 0)
177 {
178 return FP_ONE;
179 }
180
181 k = (fp_mul(abs(x), FP_LN2_INV) + FP_HALF) & ~FP_MASK;
182
183 if (x < 0)
184 {
185 k = -k;
186 }
187
188 x -= fp_mul(k, FP_LN2);
189 z = fp_mul(x, x);
190 R = FP_TWO + fp_mul(z, FP_EXP_ZERO + fp_mul(z, FP_EXP_ONE
191 + fp_mul(z, FP_EXP_TWO)));
192 xp = FP_ONE + fp_div(fp_mul(FP_TWO, x), R - x);
193
194 if (k < 0)
195 {
196 k = FP_ONE >> (-k >> FP_BITS);
197 }
198 else
199 {
200 k = FP_ONE << (k >> FP_BITS);
201 }
202
203 return fp_mul(k, xp);
204}
205
206static long fp_exp10(long x)
207{
208 if (x == 0)
209 {
210 return FP_ONE;
211 }
212
213 return fp_exp(fp_mul(FP_LN10, x));
214}
215
216static long fp_atof(const char* s, int precision)
217{
218 long int_part = 0;
219 long int_one = 1 << precision;
220 long frac_part = 0;
221 long frac_count = 0;
222 long frac_max = ((precision * 4) + 12) / 13;
223 long frac_max_int = 1;
224 long sign = 1;
225 bool point = false;
226
227 while ((*s != '\0') && isspace(*s))
228 {
229 s++;
230 }
231
232 if (*s == '-')
233 {
234 sign = -1;
235 s++;
236 }
237 else if (*s == '+')
238 {
239 s++;
240 }
241
242 while (*s != '\0')
243 {
244 if (*s == '.')
245 {
246 if (point)
247 {
248 break;
249 }
250
251 point = true;
252 }
253 else if (isdigit(*s))
254 {
255 if (point)
256 {
257 if (frac_count < frac_max)
258 {
259 frac_part = frac_part * 10 + (*s - '0');
260 frac_count++;
261 frac_max_int *= 10;
262 }
263 }
264 else
265 {
266 int_part = int_part * 10 + (*s - '0');
267 }
268 }
269 else
270 {
271 break;
272 }
273
274 s++;
275 }
276
277 while (frac_count < frac_max)
278 {
279 frac_part *= 10;
280 frac_count++;
281 frac_max_int *= 10;
282 }
283
284 return sign * ((int_part * int_one)
285 + (((int64_t) frac_part * int_one) / frac_max_int));
286}
287
288static long convert_gain(long gain)
289{
290 /* Don't allow unreasonably low or high gain changes.
291 * Our math code can't handle it properly anyway. :)
292 */
293 if (gain < (-48 * FP_ONE))
294 {
295 gain = -48 * FP_ONE;
296 }
297
298 if (gain > (17 * FP_ONE))
299 {
300 gain = 17 * FP_ONE;
301 }
302
303 gain = fp_exp10(gain / 20) << (24 - FP_BITS);
304
305 return gain;
306}
307
308/* Get the sample scale factor in Q7.24 format from a gain value. Returns 0
309 * for no gain.
310 *
311 * str Gain in dB as a string. E.g., "-3.45 dB"; the "dB" part is ignored.
312 */
313static long get_replaygain(const char* str)
314{
315 long gain = 0;
316
317 if (str)
318 {
319 gain = fp_atof(str, FP_BITS);
320 gain = convert_gain(gain);
321 }
322
323 return gain;
324}
325
326/* Get the peak volume in Q7.24 format.
327 *
328 * str Peak volume. Full scale is specified as "1.0". Returns 0 for no peak.
329 */
330static long get_replaypeak(const char* str)
331{
332 long peak = 0;
333
334 if (str)
335 {
336 peak = fp_atof(str, 24);
337 }
338
339 return peak;
340}
341
342/* Get a sample scale factor in Q7.24 format from a gain value.
343 *
344 * int_gain Gain in dB, multiplied by 100.
345 */
346long get_replaygain_int(long int_gain)
347{
348 return convert_gain(int_gain * FP_ONE / 100);
349}
350
351/* Parse a ReplayGain tag conforming to the "VorbisGain standard". If a
352 * valid tag is found, update mp3entry struct accordingly. Existing values
353 * are not overwritten. Returns number of bytes written to buffer.
354 *
355 * key Name of the tag.
356 * value Value of the tag.
357 * entry mp3entry struct to update.
358 * buffer Where to store the text for gain values (for later display).
359 * length Bytes left in buffer.
360 */
361long parse_replaygain(const char* key, const char* value,
362 struct mp3entry* entry, char* buffer, int length)
363{
364 char **p = NULL;
365
366 if (((strcasecmp(key, "replaygain_track_gain") == 0)
367 || (strcasecmp(key, "rg_radio") == 0)) && !entry->track_gain)
368 {
369 entry->track_gain = get_replaygain(value);
370 p = &(entry->track_gain_string);
371 }
372 else if (((strcasecmp(key, "replaygain_album_gain") == 0)
373 || (strcasecmp(key, "rg_audiophile") == 0)) && !entry->album_gain)
374 {
375 entry->album_gain = get_replaygain(value);
376 p = &(entry->album_gain_string);
377 }
378 else if (((strcasecmp(key, "replaygain_track_peak") == 0)
379 || (strcasecmp(key, "rg_peak") == 0)) && !entry->track_peak)
380 {
381 entry->track_peak = get_replaypeak(value);
382 }
383 else if ((strcasecmp(key, "replaygain_album_peak") == 0)
384 && !entry->album_peak)
385 {
386 entry->album_peak = get_replaypeak(value);
387 }
388
389 if (p)
390 {
391 int len = strlen(value);
392
393 len = MIN(len, length - 1);
394
395 /* A few characters just isn't interesting... */
396 if (len > 1)
397 {
398 strncpy(buffer, value, len);
399 buffer[len] = 0;
400 *p = buffer;
401 return len + 1;
402 }
403 }
404
405 return 0;
406}
407
408/* Set ReplayGain values from integers. Existing values are not overwritten.
409 * Returns number of bytes written to buffer.
410 *
411 * album If true, set album values, otherwise set track values.
412 * gain Gain value in dB, multiplied by 512. 0 for no gain.
413 * peak Peak volume in Q7.24 format, where 1.0 is full scale. 0 for no
414 * peak volume.
415 * buffer Where to store the text for gain values (for later display).
416 * length Bytes left in buffer.
417 */
418long parse_replaygain_int(bool album, long gain, long peak,
419 struct mp3entry* entry, char* buffer, int length)
420{
421 long len = 0;
422
423 if (buffer != NULL)
424 {
425 len = snprintf(buffer, length, "%d.%02d dB", gain / 512,
426 ((abs(gain) & 0x01ff) * 100 + 256) / 512);
427 len++;
428 }
429
430 if (gain != 0)
431 {
432 gain = convert_gain(gain * FP_ONE / 512);
433 }
434
435 if (album)
436 {
437 entry->album_gain = gain;
438 entry->album_gain_string = buffer;
439
440 if (peak)
441 {
442 entry->album_peak = peak;
443 }
444 }
445 else
446 {
447 entry->track_gain = gain;
448 entry->track_gain_string = buffer;
449
450 if (peak)
451 {
452 entry->track_peak = peak;
453 }
454 }
455
456 return len;
457}