summaryrefslogtreecommitdiff
path: root/apps/mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mpeg.c')
-rw-r--r--apps/mpeg.c2873
1 files changed, 2873 insertions, 0 deletions
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 */