Hide the buffering thread and queue inside buffering.c
[Rockbox.git] / apps / playback.c
blob02406141f2dbd710e2a3fa8b3bd5cf8dd0cb555e
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
34 #include "system.h"
35 #include "thread.h"
36 #include "file.h"
37 #include "panic.h"
38 #include "memory.h"
39 #include "lcd.h"
40 #include "font.h"
41 #include "button.h"
42 #include "kernel.h"
43 #include "tree.h"
44 #include "debug.h"
45 #include "sprintf.h"
46 #include "settings.h"
47 #include "codecs.h"
48 #include "audio.h"
49 #include "buffering.h"
50 #include "mp3_playback.h"
51 #include "usb.h"
52 #include "status.h"
53 #include "ata.h"
54 #include "screens.h"
55 #include "playlist.h"
56 #include "playback.h"
57 #include "pcmbuf.h"
58 #include "buffer.h"
59 #include "dsp.h"
60 #include "abrepeat.h"
61 #include "cuesheet.h"
62 #ifdef HAVE_TAGCACHE
63 #include "tagcache.h"
64 #endif
65 #ifdef HAVE_LCD_BITMAP
66 #include "icons.h"
67 #include "peakmeter.h"
68 #include "action.h"
69 #endif
70 #include "lang.h"
71 #include "bookmark.h"
72 #include "misc.h"
73 #include "sound.h"
74 #include "metadata.h"
75 #include "splash.h"
76 #include "talk.h"
77 #include "ata_idle_notify.h"
79 #ifdef HAVE_RECORDING
80 #include "recording.h"
81 #include "talk.h"
82 #endif
84 #ifdef HAVE_WM8758
85 #include "menus/eq_menu.h"
86 #endif
88 #define PLAYBACK_VOICE
91 /* Define LOGF_ENABLE to enable logf output in this file */
92 /*#define LOGF_ENABLE*/
93 #include "logf.h"
95 /* macros to enable logf for queues
96 logging on SYS_TIMEOUT can be disabled */
97 #ifdef SIMULATOR
98 /* Define this for logf output of all queuing except SYS_TIMEOUT */
99 #define PLAYBACK_LOGQUEUES
100 /* Define this to logf SYS_TIMEOUT messages */
101 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
102 #endif
104 #ifdef PLAYBACK_LOGQUEUES
105 #define LOGFQUEUE logf
106 #else
107 #define LOGFQUEUE(...)
108 #endif
110 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
111 #define LOGFQUEUE_SYS_TIMEOUT logf
112 #else
113 #define LOGFQUEUE_SYS_TIMEOUT(...)
114 #endif
117 /* Define one constant that includes recording related functionality */
118 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
119 #define AUDIO_HAVE_RECORDING
120 #endif
122 enum {
123 Q_AUDIO_PLAY = 1,
124 Q_AUDIO_STOP,
125 Q_AUDIO_PAUSE,
126 Q_AUDIO_SKIP,
127 Q_AUDIO_PRE_FF_REWIND,
128 Q_AUDIO_FF_REWIND,
129 /* Q_AUDIO_REBUFFER_SEEK, */
130 Q_AUDIO_CHECK_NEW_TRACK,
131 Q_AUDIO_FLUSH,
132 Q_AUDIO_TRACK_CHANGED,
133 Q_AUDIO_DIR_SKIP,
134 Q_AUDIO_POSTINIT,
135 Q_AUDIO_FILL_BUFFER,
136 #if MEM > 8
137 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
138 #endif
139 Q_CODEC_REQUEST_COMPLETE,
140 Q_CODEC_REQUEST_FAILED,
142 Q_VOICE_PLAY,
143 Q_VOICE_STOP,
145 Q_CODEC_LOAD,
146 Q_CODEC_LOAD_DISK,
148 #ifdef AUDIO_HAVE_RECORDING
149 Q_ENCODER_LOAD_DISK,
150 Q_ENCODER_RECORD,
151 #endif
154 /* As defined in plugins/lib/xxx2wav.h */
155 #if MEM > 1
156 #define MALLOC_BUFSIZE (512*1024)
157 #define GUARD_BUFSIZE (32*1024)
158 #else
159 #define MALLOC_BUFSIZE (100*1024)
160 #define GUARD_BUFSIZE (8*1024)
161 #endif
163 /* As defined in plugin.lds */
164 #if defined(CPU_PP)
165 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
166 #define CODEC_IRAM_SIZE ((size_t)0xc000)
167 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
168 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
169 #define CODEC_IRAM_SIZE ((size_t)0x10000)
170 #else
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #endif
175 #ifndef IBSS_ATTR_VOICE_STACK
176 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
177 #endif
179 bool audio_is_initialized = false;
181 /* Variables are commented with the threads that use them: *
182 * A=audio, C=codec, V=voice. A suffix of - indicates that *
183 * the variable is read but not updated on that thread. */
184 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
186 /* Main state control */
187 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
188 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
189 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
190 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
192 /* Ring buffer where compressed audio and codecs are loaded */
193 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
194 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
195 /* FIXME: make filebuflen static */
196 size_t filebuflen = 0; /* Size of buffer (A/C-) */
197 /* FIXME: make buf_ridx (C/A-) */
199 /* Possible arrangements of the buffer */
200 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
201 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
202 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
203 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
205 static struct mp3entry curtrack_id3;
206 static struct mp3entry nexttrack_id3;
208 /* Track info structure about songs in the file buffer (A/C-) */
209 struct track_info {
210 int audio_hid; /* The ID for the track's buffer handle */
211 int id3_hid; /* The ID for the track's metadata handle */
212 int codec_hid; /* The ID for the track's codec handle */
214 size_t codecsize; /* Codec length in bytes */
215 size_t filesize; /* File total length */
217 bool taginfo_ready; /* Is metadata read */
219 bool event_sent; /* Was this track's buffered event sent */
222 static struct track_info tracks[MAX_TRACK];
223 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
224 static int track_widx = 0; /* Track being buffered (A) */
226 #if 0
227 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
228 #endif
230 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
232 /* Set by the audio thread when the current track information has updated
233 * and the WPS may need to update its cached information */
234 static bool track_changed = false;
236 /* Information used only for filling the buffer */
237 /* Playlist steps from playing track to next track to be buffered (A) */
238 static int last_peek_offset = 0;
240 /* Scrobbler support */
241 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
243 /* Track change controls */
244 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
245 static bool playlist_end = false; /* Has the current playlist ended? (A) */
246 static bool dir_skip = false; /* Is a directory skip pending? (A) */
247 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
248 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
249 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
251 /* Callbacks which applications or plugins may set */
252 /* When the playing track has changed from the user's perspective */
253 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
254 /* When a track has been buffered */
255 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
256 /* When a track's buffer has been overwritten or cleared */
257 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
259 /* Configuration */
260 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
261 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
262 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
263 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
264 #if MEM > 8
265 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
266 #endif
268 /* Multiple threads */
269 static void set_current_codec(int codec_idx);
270 /* Set the watermark to trigger buffer fill (A/C) FIXME */
271 static void set_filebuf_watermark(int seconds);
273 /* Audio thread */
274 static struct event_queue audio_queue NOCACHEBSS_ATTR;
275 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
276 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
277 static const char audio_thread_name[] = "audio";
279 static void audio_thread(void);
280 static void audio_initiate_track_change(long direction);
281 static bool audio_have_tracks(void);
282 static void audio_reset_buffer(void);
284 /* Codec thread */
285 extern struct codec_api ci;
286 static struct event_queue codec_queue NOCACHEBSS_ATTR;
287 static struct queue_sender_list codec_queue_sender_list;
288 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
289 IBSS_ATTR;
290 static const char codec_thread_name[] = "codec";
291 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
293 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
295 /* Voice thread */
296 #ifdef PLAYBACK_VOICE
298 extern struct codec_api ci_voice;
300 static struct thread_entry *voice_thread_p = NULL;
301 static struct event_queue voice_queue NOCACHEBSS_ATTR;
302 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
303 IBSS_ATTR_VOICE_STACK;
304 static const char voice_thread_name[] = "voice codec";
306 /* Voice codec swapping control */
307 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
309 #ifdef SIMULATOR
310 /* IRAM codec swap buffer for sim*/
311 static unsigned char sim_iram[CODEC_IRAM_SIZE];
312 #undef CODEC_IRAM_ORIGIN
313 #define CODEC_IRAM_ORIGIN sim_iram
314 #endif
316 /* iram_buf and dram_buf are either both NULL or both non-NULL */
317 /* Pointer to IRAM buffer for codec swapping */
318 static unsigned char *iram_buf = NULL;
319 /* Pointer to DRAM buffer for codec swapping */
320 static unsigned char *dram_buf = NULL;
321 /* Parity of swap_codec calls - needed because one codec swapping itself in
322 automatically swaps in the other and the swap when unlocking should not
323 happen if the parity is even.
325 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
326 /* Locking to control which codec (normal/voice) is running */
327 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
328 static struct event event_codecthread NOCACHEBSS_ATTR;
330 /* Voice state */
331 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
332 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
333 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
334 static unsigned char *voicebuf = NULL;
335 static size_t voice_remaining = 0;
337 #ifdef IRAM_STEAL
338 /* Voice IRAM has been stolen for other use */
339 static bool voice_iram_stolen = false;
340 #endif
342 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
344 struct voice_info {
345 void (*callback)(unsigned char **start, size_t* size);
346 size_t size;
347 unsigned char *buf;
349 static void voice_thread(void);
350 static void voice_stop(void);
352 #endif /* PLAYBACK_VOICE */
355 /* --- Helper functions --- */
357 struct mp3entry *bufgetid3(int handle_id)
359 if (handle_id < 0)
360 return NULL;
362 struct mp3entry *id3;
363 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
365 if (ret < 0 || ret != sizeof(struct mp3entry))
366 return NULL;
368 return id3;
371 void *bufgetcodec(struct track_info *track)
373 void *ptr;
374 ssize_t ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
376 if (ret == -2) {
377 request_buffer_handle(CUR_TI->audio_hid);
380 while (ret == -2) {
381 sleep(1);
382 ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
385 if (ret < 0)
386 return NULL;
387 else
388 return ptr;
391 void clear_track_info(struct track_info *track)
393 if (!track)
394 return;
396 if (track->codec_hid > 0) {
397 bufclose(track->codec_hid);
400 if (track->id3_hid > 0) {
401 bufclose(track->id3_hid);
404 if (track->audio_hid > 0) {
405 bufclose(track->audio_hid);
408 memset(track, 0, sizeof(struct track_info));
411 /* --- External interfaces --- */
413 void mp3_play_data(const unsigned char* start, int size,
414 void (*get_more)(unsigned char** start, size_t* size))
416 #ifdef PLAYBACK_VOICE
417 static struct voice_info voice_clip;
418 voice_clip.callback = get_more;
419 voice_clip.buf = (unsigned char*)start;
420 voice_clip.size = size;
421 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
422 queue_post(&voice_queue, Q_VOICE_STOP, 0);
423 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
424 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
425 voice_thread_start = true;
426 trigger_cpu_boost();
427 #else
428 (void) start;
429 (void) size;
430 (void) get_more;
431 #endif
434 void mp3_play_stop(void)
436 #ifdef PLAYBACK_VOICE
437 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
438 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
439 queue_post(&voice_queue, Q_VOICE_STOP, 1);
440 #endif
443 void mp3_play_pause(bool play)
445 /* a dummy */
446 (void)play;
449 bool mp3_is_playing(void)
451 #ifdef PLAYBACK_VOICE
452 return voice_is_playing;
453 #else
454 return false;
455 #endif
458 /* If voice could be swapped out - wait for it to return
459 * Used by buffer claming functions.
461 static void wait_for_voice_swap_in(void)
463 #ifdef PLAYBACK_VOICE
464 if (NULL == iram_buf)
465 return;
467 event_wait(&event_codecthread, STATE_NONSIGNALED);
468 #endif /* PLAYBACK_VOICE */
471 /* This sends a stop message and the audio thread will dump all it's
472 subsequenct messages */
473 static void audio_hard_stop(void)
475 /* Stop playback */
476 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
477 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
480 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
482 unsigned char *buf, *end;
484 if (audio_is_initialized)
486 audio_hard_stop();
487 wait_for_voice_swap_in();
488 #ifdef PLAYBACK_VOICE
489 voice_stop();
490 #endif
492 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
494 if (buffer_size == NULL)
496 /* Special case for talk_init to use since it already knows it's
497 trashed */
498 buffer_state = BUFFER_STATE_TRASHED;
499 return NULL;
502 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
503 || !talk_voice_required())
505 logf("get buffer: talk, audio");
506 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
507 the talk buffer is not needed because voice isn't being used, or
508 could be BUFFER_STATE_TRASHED already. If state is
509 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
510 without the caller knowing what's going on. Changing certain settings
511 may move it to a worse condition but the memory in use by something
512 else will remain undisturbed.
514 if (buffer_state != BUFFER_STATE_TRASHED)
516 talk_buffer_steal();
517 buffer_state = BUFFER_STATE_TRASHED;
520 buf = audiobuf;
521 end = audiobufend;
523 else
525 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
526 still BUFFER_STATE_INITIALIZED */
527 /* Skip talk buffer and move pcm buffer to end to maximize available
528 contiguous memory - no audio running means voice will not need the
529 swap space */
530 logf("get buffer: audio");
531 buf = audiobuf + talk_get_bufsize();
532 end = audiobufend - pcmbuf_init(audiobufend);
533 buffer_state = BUFFER_STATE_VOICED_ONLY;
536 *buffer_size = end - buf;
538 return buf;
541 #ifdef IRAM_STEAL
542 void audio_iram_steal(void)
544 /* We need to stop audio playback in order to use codec IRAM */
545 audio_hard_stop();
547 #ifdef PLAYBACK_VOICE
548 if (NULL != iram_buf)
550 /* Can't already be stolen */
551 if (voice_iram_stolen)
552 return;
554 /* Must wait for voice to be current again if it is swapped which
555 would cause the caller's buffer to get clobbered when voice locks
556 and runs - we'll wait for it to lock and yield again then make sure
557 the ride has come to a complete stop */
558 wait_for_voice_swap_in();
559 voice_stop();
561 /* Save voice IRAM but just memcpy - safe to do here since voice
562 is current and no audio codec is loaded */
563 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
564 voice_iram_stolen = true;
566 else
568 /* Nothing much to do if no voice */
569 voice_iram_stolen = false;
571 #endif
573 #endif /* IRAM_STEAL */
575 #ifdef HAVE_RECORDING
576 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
578 /* Don't allow overwrite of voice swap area or we'll trash the
579 swapped-out voice codec but can use whole thing if none */
580 unsigned char *end;
582 /* Stop audio and voice. Wait for voice to swap in and be clear
583 of pending events to ensure trouble-free operation of encoders */
584 audio_hard_stop();
585 wait_for_voice_swap_in();
586 #ifdef PLAYBACK_VOICE
587 voice_stop();
588 #endif
589 talk_buffer_steal();
591 #ifdef PLAYBACK_VOICE
592 /* If no dram_buf, swap space not used and recording gets more
593 memory. Codec swap areas will remain unaffected by the next init
594 since they're allocated at the end of the buffer and their sizes
595 don't change between calls */
596 end = dram_buf;
597 if (NULL == end)
598 #endif /* PLAYBACK_VOICE */
599 end = audiobufend;
601 buffer_state = BUFFER_STATE_TRASHED;
603 *buffer_size = end - audiobuf;
605 return (unsigned char *)audiobuf;
608 bool audio_load_encoder(int afmt)
610 #ifndef SIMULATOR
611 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
612 if (!enc_fn)
613 return false;
615 audio_remove_encoder();
616 ci.enc_codec_loaded = 0; /* clear any previous error condition */
618 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
619 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
621 while (ci.enc_codec_loaded == 0)
622 yield();
624 logf("codec loaded: %d", ci.enc_codec_loaded);
626 return ci.enc_codec_loaded > 0;
627 #else
628 (void)afmt;
629 return true;
630 #endif
631 } /* audio_load_encoder */
633 void audio_remove_encoder(void)
635 #ifndef SIMULATOR
636 /* force encoder codec unload (if currently loaded) */
637 if (ci.enc_codec_loaded <= 0)
638 return;
640 ci.stop_encoder = true;
641 while (ci.enc_codec_loaded > 0)
642 yield();
643 #endif
644 } /* audio_remove_encoder */
646 #endif /* HAVE_RECORDING */
648 struct mp3entry* audio_current_track(void)
650 const char *filename;
651 const char *p;
652 static struct mp3entry temp_id3;
653 int cur_idx;
654 int offset = ci.new_track + wps_offset;
656 cur_idx = track_ridx + offset;
657 cur_idx &= MAX_TRACK_MASK;
659 if (cur_idx == track_ridx && *curtrack_id3.path)
660 return &curtrack_id3;
661 else if (tracks[cur_idx].id3_hid > 0)
662 return bufgetid3(tracks[cur_idx].id3_hid);
664 memset(&temp_id3, 0, sizeof(struct mp3entry));
666 filename = playlist_peek(0);
667 if (!filename)
668 filename = "No file!";
670 #ifdef HAVE_TC_RAMCACHE
671 if (tagcache_fill_tags(&temp_id3, filename))
672 return &temp_id3;
673 #endif
675 p = strrchr(filename, '/');
676 if (!p)
677 p = filename;
678 else
679 p++;
681 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
682 temp_id3.title = &temp_id3.path[0];
684 return &temp_id3;
687 struct mp3entry* audio_next_track(void)
689 int next_idx = track_ridx;
691 if (!audio_have_tracks())
692 return NULL;
694 next_idx++;
695 next_idx &= MAX_TRACK_MASK;
697 if (tracks[next_idx].id3_hid <= 0)
698 return NULL;
700 return &nexttrack_id3;
703 bool audio_has_changed_track(void)
705 if (track_changed)
707 track_changed = false;
708 return true;
711 return false;
714 void audio_play(long offset)
716 logf("audio_play");
718 #ifdef PLAYBACK_VOICE
719 /* Truncate any existing voice output so we don't have spelling
720 * etc. over the first part of the played track */
721 talk_force_shutup();
722 #endif
724 /* Start playback */
725 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
726 /* Don't return until playback has actually started */
727 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
730 void audio_stop(void)
732 /* Stop playback */
733 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
734 /* Don't return until playback has actually stopped */
735 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
738 void audio_pause(void)
740 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
741 /* Don't return until playback has actually paused */
742 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
745 void audio_resume(void)
747 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
748 /* Don't return until playback has actually resumed */
749 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
752 void audio_next(void)
754 if (playlist_check(ci.new_track + wps_offset + 1))
756 if (global_settings.beep)
757 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
759 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
760 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
761 /* Update wps while our message travels inside deep playback queues. */
762 wps_offset++;
763 track_changed = true;
765 else
767 /* No more tracks. */
768 if (global_settings.beep)
769 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
773 void audio_prev(void)
775 if (playlist_check(ci.new_track + wps_offset - 1))
777 if (global_settings.beep)
778 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
780 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
781 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
782 /* Update wps while our message travels inside deep playback queues. */
783 wps_offset--;
784 track_changed = true;
786 else
788 /* No more tracks. */
789 if (global_settings.beep)
790 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
794 void audio_next_dir(void)
796 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
797 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
800 void audio_prev_dir(void)
802 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
803 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
806 void audio_pre_ff_rewind(void)
808 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
809 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
812 void audio_ff_rewind(long newpos)
814 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
815 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
818 void audio_flush_and_reload_tracks(void)
820 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
821 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
824 void audio_error_clear(void)
826 #ifdef AUDIO_HAVE_RECORDING
827 pcm_rec_error_clear();
828 #endif
831 int audio_status(void)
833 int ret = 0;
835 if (playing)
836 ret |= AUDIO_STATUS_PLAY;
838 if (paused)
839 ret |= AUDIO_STATUS_PAUSE;
841 #ifdef HAVE_RECORDING
842 /* Do this here for constitency with mpeg.c version */
843 ret |= pcm_rec_status();
844 #endif
846 return ret;
849 int audio_get_file_pos(void)
851 return 0;
854 #ifndef HAVE_FLASH_STORAGE
855 void audio_set_buffer_margin(int setting)
857 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
858 buffer_margin = lookup[setting];
859 logf("buffer margin: %d", buffer_margin);
860 set_filebuf_watermark(buffer_margin);
862 #endif
864 /* Take nescessary steps to enable or disable the crossfade setting */
865 void audio_set_crossfade(int enable)
867 size_t offset;
868 bool was_playing;
869 size_t size;
871 /* Tell it the next setting to use */
872 pcmbuf_crossfade_enable(enable);
874 /* Return if size hasn't changed or this is too early to determine
875 which in the second case there's no way we could be playing
876 anything at all */
877 if (pcmbuf_is_same_size())
879 /* This function is a copout and just syncs some variables -
880 to be removed at a later date */
881 pcmbuf_crossfade_enable_finished();
882 return;
885 offset = 0;
886 was_playing = playing;
888 /* Playback has to be stopped before changing the buffer size */
889 if (was_playing)
891 /* Store the track resume position */
892 offset = curtrack_id3.offset;
893 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
896 /* Blast it - audio buffer will have to be setup again next time
897 something plays */
898 audio_get_buffer(true, &size);
900 /* Restart playback if audio was running previously */
901 if (was_playing)
902 audio_play(offset);
905 /* --- Routines called from multiple threads --- */
906 static void set_current_codec(int codec_idx)
908 current_codec = codec_idx;
909 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
912 #ifdef PLAYBACK_VOICE
913 static void swap_codec(void)
915 int my_codec;
917 /* Swap nothing if no swap buffers exist */
918 if (dram_buf == NULL)
920 logf("swap: no swap buffers");
921 return;
924 my_codec = current_codec;
926 logf("swapping out codec: %d", my_codec);
928 /* Invert this when a codec thread enters and leaves */
929 swap_codec_parity = !swap_codec_parity;
931 /* If this is true, an odd number of calls has occurred and there's
932 no codec thread waiting to swap us out when it locks and runs. This
933 occurs when playback is stopped or when just starting playback and
934 the audio thread is loading a codec; parities should always be even
935 on entry when a thread calls this during playback */
936 if (swap_codec_parity)
938 /* Save our current IRAM and DRAM */
939 #ifdef IRAM_STEAL
940 if (voice_iram_stolen)
942 logf("swap: iram restore");
943 voice_iram_stolen = false;
944 /* Don't swap trashed data into buffer as the voice IRAM will
945 already be swapped out - should _always_ be the case if
946 voice_iram_stolen is true since the voice has been swapped
947 in beforehand */
948 if (my_codec == CODEC_IDX_VOICE)
950 logf("voice iram already swapped");
951 goto skip_iram_swap;
954 #endif
956 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
958 #ifdef IRAM_STEAL
959 skip_iram_swap:
960 #endif
962 memswap128(dram_buf, codecbuf, CODEC_SIZE);
963 /* No cache invalidation needed; it will be done in codec_load_ram
964 or we won't be here otherwise */
967 /* Release my semaphore */
968 semaphore_release(&sem_codecthread);
969 logf("unlocked: %d", my_codec);
971 /* Wait for other codec */
972 event_wait(&event_codecthread,
973 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
975 /* Wait for other codec to unlock */
976 logf("waiting for lock: %d", my_codec);
977 semaphore_wait(&sem_codecthread);
979 /* Take control */
980 set_current_codec(my_codec);
981 event_set_state(&event_codecthread,
982 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
984 /* Reload our IRAM and DRAM */
985 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
986 memswap128(dram_buf, codecbuf, CODEC_SIZE);
987 invalidate_icache();
989 /* Flip parity again */
990 swap_codec_parity = !swap_codec_parity;
992 logf("resuming codec: %d", my_codec);
995 /* This function is meant to be used by the buffer stealing functions to
996 ensure the codec is no longer active and so voice will be swapped-in
997 before it is called */
998 static void voice_stop(void)
1000 /* Must have a voice codec loaded or we'll hang forever here */
1001 if (!voice_codec_loaded)
1002 return;
1004 talk_force_shutup();
1006 /* Loop until voice empties it's queue, stops and picks up on the new
1007 track; the voice thread must be stopped and waiting for messages
1008 outside the codec */
1009 while (voice_is_playing || !queue_empty(&voice_queue) ||
1010 ci_voice.new_track)
1011 yield();
1013 if (!playing)
1014 pcmbuf_play_stop();
1015 } /* voice_stop */
1017 /* Is voice still speaking */
1018 /* Unfortunately only reliable when music is not also playing. */
1019 static bool is_voice_speaking(void)
1021 return is_voice_queued()
1022 || voice_is_playing
1023 || (!playing && pcm_is_playing());
1026 #endif /* PLAYBACK_VOICE */
1028 /* Wait for voice to finish speaking. */
1029 /* Also only reliable when music is not also playing. */
1030 void voice_wait(void)
1032 #ifdef PLAYBACK_VOICE
1033 while (is_voice_speaking())
1034 sleep(HZ/10);
1035 #endif
1038 static void set_filebuf_watermark(int seconds)
1040 size_t bytes;
1042 if (!filebuf)
1043 return; /* Audio buffers not yet set up */
1045 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), conf_watermark);
1046 bytes = MIN(bytes, filebuflen / 2);
1047 conf_watermark = bytes;
1050 const char * get_codec_filename(int cod_spec)
1052 const char *fname;
1054 #ifdef HAVE_RECORDING
1055 /* Can choose decoder or encoder if one available */
1056 int type = cod_spec & CODEC_TYPE_MASK;
1057 int afmt = cod_spec & CODEC_AFMT_MASK;
1059 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1060 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1062 fname = (type == CODEC_TYPE_ENCODER) ?
1063 audio_formats[afmt].codec_enc_root_fn :
1064 audio_formats[afmt].codec_root_fn;
1066 logf("%s: %d - %s",
1067 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1068 afmt, fname ? fname : "<unknown>");
1069 #else /* !HAVE_RECORDING */
1070 /* Always decoder */
1071 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1072 cod_spec = AFMT_UNKNOWN;
1073 fname = audio_formats[cod_spec].codec_root_fn;
1074 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1075 #endif /* HAVE_RECORDING */
1077 return fname;
1078 } /* get_codec_filename */
1081 /* --- Voice thread --- */
1083 #ifdef PLAYBACK_VOICE
1085 static bool voice_pcmbuf_insert_callback(
1086 const void *ch1, const void *ch2, int count)
1088 const char *src[2] = { ch1, ch2 };
1090 while (count > 0)
1092 int out_count = dsp_output_count(count);
1093 int inp_count;
1094 char *dest;
1096 while ((dest = pcmbuf_request_voice_buffer(
1097 &out_count, playing)) == NULL)
1099 if (playing && audio_codec_loaded)
1100 swap_codec();
1101 else
1102 yield();
1105 /* Get the real input_size for output_size bytes, guarding
1106 * against resampling buffer overflows. */
1107 inp_count = dsp_input_count(out_count);
1109 if (inp_count <= 0)
1110 return true;
1112 /* Input size has grown, no error, just don't write more than length */
1113 if (inp_count > count)
1114 inp_count = count;
1116 out_count = dsp_process(dest, src, inp_count);
1118 if (out_count <= 0)
1119 return true;
1121 if (playing)
1123 pcmbuf_mix_voice(out_count);
1124 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1125 audio_codec_loaded)
1126 swap_codec();
1128 else
1129 pcmbuf_write_complete(out_count);
1131 count -= inp_count;
1134 return true;
1135 } /* voice_pcmbuf_insert_callback */
1137 static void* voice_get_memory_callback(size_t *size)
1139 /* Voice should have no use for this. If it did, we'd have to
1140 swap the malloc buffer as well. */
1141 *size = 0;
1142 return NULL;
1145 static void voice_set_elapsed_callback(unsigned int value)
1147 (void)value;
1150 static void voice_set_offset_callback(size_t value)
1152 (void)value;
1155 static void voice_configure_callback(int setting, intptr_t value)
1157 if (!dsp_configure(setting, value))
1159 logf("Illegal key:%d", setting);
1163 static size_t voice_filebuf_callback(void *ptr, size_t size)
1165 (void)ptr;
1166 (void)size;
1168 return 0;
1171 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1172 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1174 if (aborting && !playing)
1176 /* Aborting: Slight hack - flush PCM buffer if
1177 only being used for voice */
1178 pcmbuf_play_stop();
1181 if (voice_is_playing)
1183 /* Clear the current buffer */
1184 voice_is_playing = false;
1185 voice_getmore = NULL;
1186 voice_remaining = 0;
1187 voicebuf = NULL;
1189 /* Cancel any automatic boost if no more clips requested. */
1190 if (!playing || !voice_thread_start)
1191 sleep(0);
1193 /* Force the codec to think it's changing tracks */
1194 ci_voice.new_track = 1;
1196 *realsize = 0;
1197 return true; /* Yes, change tracks */
1200 return false;
1203 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1205 struct queue_event ev;
1207 if (ci_voice.new_track)
1209 *realsize = 0;
1210 return NULL;
1213 while (1)
1215 if (voice_is_playing || playing)
1217 queue_wait_w_tmo(&voice_queue, &ev, 0);
1218 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1219 ev.id = Q_AUDIO_PLAY;
1221 else
1223 queue_wait(&voice_queue, &ev);
1226 switch (ev.id) {
1227 case Q_AUDIO_PLAY:
1228 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1229 if (playing)
1231 if (audio_codec_loaded)
1232 swap_codec();
1233 yield();
1235 break;
1237 #ifdef AUDIO_HAVE_RECORDING
1238 case Q_ENCODER_RECORD:
1239 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1240 swap_codec();
1241 break;
1242 #endif
1244 case Q_VOICE_STOP:
1245 LOGFQUEUE("voice < Q_VOICE_STOP");
1246 if (voice_on_voice_stop(ev.data, realsize))
1247 return NULL;
1248 break;
1250 case SYS_USB_CONNECTED:
1252 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1253 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1254 /* Voice is obviously current so let us swap ourselves away if
1255 playing so audio may stop itself - audio_codec_loaded can
1256 only be true in this case if we're here even if the codec
1257 is only about to load */
1258 if (audio_codec_loaded)
1259 swap_codec();
1260 /* Playback should be finished by now - ack and wait */
1261 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1262 usb_wait_for_disconnect(&voice_queue);
1263 if (change_tracks)
1264 return NULL;
1265 break;
1268 case Q_VOICE_PLAY:
1269 LOGFQUEUE("voice < Q_VOICE_PLAY");
1270 if (!voice_is_playing)
1272 /* Set up new voice data */
1273 struct voice_info *voice_data;
1274 #ifdef IRAM_STEAL
1275 if (voice_iram_stolen)
1277 /* Voice is the first to run again and is currently
1278 loaded */
1279 logf("voice: iram restore");
1280 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1281 voice_iram_stolen = false;
1283 #endif
1284 /* Must reset the buffer before any playback begins if
1285 needed */
1286 if (buffer_state == BUFFER_STATE_TRASHED)
1287 audio_reset_buffer();
1289 voice_is_playing = true;
1290 trigger_cpu_boost();
1291 voice_data = (struct voice_info *)ev.data;
1292 voice_remaining = voice_data->size;
1293 voicebuf = voice_data->buf;
1294 voice_getmore = voice_data->callback;
1296 goto voice_play_clip; /* To exit both switch and while */
1298 case SYS_TIMEOUT:
1299 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1300 goto voice_play_clip;
1302 default:
1303 LOGFQUEUE("voice < default");
1307 voice_play_clip:
1309 if (voice_remaining == 0 || voicebuf == NULL)
1311 if (voice_getmore)
1312 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1314 /* If this clip is done */
1315 if (voice_remaining == 0)
1317 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1318 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1319 /* Force pcm playback. */
1320 if (!pcm_is_playing())
1321 pcmbuf_play_start();
1325 *realsize = MIN(voice_remaining, reqsize);
1327 if (*realsize == 0)
1328 return NULL;
1330 return voicebuf;
1331 } /* voice_request_buffer_callback */
1333 static void voice_advance_buffer_callback(size_t amount)
1335 amount = MIN(amount, voice_remaining);
1336 voicebuf += amount;
1337 voice_remaining -= amount;
1340 static void voice_advance_buffer_loc_callback(void *ptr)
1342 size_t amount = (size_t)ptr - (size_t)voicebuf;
1344 voice_advance_buffer_callback(amount);
1347 static off_t voice_mp3_get_filepos_callback(int newtime)
1349 (void)newtime;
1351 return 0;
1354 static void voice_do_nothing(void)
1356 return;
1359 static bool voice_seek_buffer_callback(size_t newpos)
1361 (void)newpos;
1363 return false;
1366 static bool voice_request_next_track_callback(void)
1368 ci_voice.new_track = 0;
1369 return true;
1372 static void voice_thread(void)
1374 logf("Loading voice codec");
1375 voice_codec_loaded = true;
1376 semaphore_wait(&sem_codecthread);
1377 event_set_state(&event_codecthread, false);
1378 set_current_codec(CODEC_IDX_VOICE);
1379 dsp_configure(DSP_RESET, 0);
1380 voice_remaining = 0;
1381 voice_getmore = NULL;
1383 /* FIXME: If we being starting the voice thread without reboot, the
1384 voice_queue could be full of old stuff and we must flush it. */
1385 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1387 logf("Voice codec finished");
1388 voice_codec_loaded = false;
1389 voice_thread_p = NULL;
1390 semaphore_release(&sem_codecthread);
1391 } /* voice_thread */
1393 #endif /* PLAYBACK_VOICE */
1395 /* --- Codec thread --- */
1396 static bool codec_pcmbuf_insert_callback(
1397 const void *ch1, const void *ch2, int count)
1399 const char *src[2] = { ch1, ch2 };
1401 while (count > 0)
1403 int out_count = dsp_output_count(count);
1404 int inp_count;
1405 char *dest;
1407 /* Prevent audio from a previous track from playing */
1408 if (ci.new_track || ci.stop_codec)
1409 return true;
1411 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1413 sleep(1);
1414 if (ci.seek_time || ci.new_track || ci.stop_codec)
1415 return true;
1418 /* Get the real input_size for output_size bytes, guarding
1419 * against resampling buffer overflows. */
1420 inp_count = dsp_input_count(out_count);
1422 if (inp_count <= 0)
1423 return true;
1425 /* Input size has grown, no error, just don't write more than length */
1426 if (inp_count > count)
1427 inp_count = count;
1429 out_count = dsp_process(dest, src, inp_count);
1431 if (out_count <= 0)
1432 return true;
1434 pcmbuf_write_complete(out_count);
1436 #ifdef PLAYBACK_VOICE
1437 if ((voice_is_playing || voice_thread_start)
1438 && pcm_is_playing() && voice_codec_loaded &&
1439 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1441 voice_thread_start = false;
1442 swap_codec();
1444 #endif
1446 count -= inp_count;
1449 return true;
1450 } /* codec_pcmbuf_insert_callback */
1452 static void* codec_get_memory_callback(size_t *size)
1454 *size = MALLOC_BUFSIZE;
1455 return malloc_buf;
1458 #if 0
1459 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1460 static void codec_pcmbuf_position_callback(size_t size)
1462 /* This is called from an ISR, so be quick */
1463 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1464 prev_ti->id3.elapsed;
1466 if (time >= prev_ti->id3.length)
1468 pcmbuf_set_position_callback(NULL);
1469 prev_ti->id3.elapsed = prev_ti->id3.length;
1471 else
1472 prev_ti->id3.elapsed = time;
1474 #endif
1476 static void codec_set_elapsed_callback(unsigned int value)
1478 unsigned int latency;
1479 if (ci.seek_time)
1480 return;
1482 #ifdef AB_REPEAT_ENABLE
1483 ab_position_report(value);
1484 #endif
1486 latency = pcmbuf_get_latency();
1487 if (value < latency)
1488 curtrack_id3.elapsed = 0;
1489 else if (value - latency > curtrack_id3.elapsed ||
1490 value - latency < curtrack_id3.elapsed - 2)
1492 curtrack_id3.elapsed = value - latency;
1496 static void codec_set_offset_callback(size_t value)
1498 unsigned int latency;
1500 if (ci.seek_time)
1501 return;
1503 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1504 if (value < latency)
1505 curtrack_id3.offset = 0;
1506 else
1507 curtrack_id3.offset = value - latency;
1510 /* copy up-to size bytes into ptr and return the actual size copied */
1511 static size_t codec_filebuf_callback(void *ptr, size_t size)
1513 ssize_t copy_n;
1515 if (ci.stop_codec || !playing)
1516 return 0;
1518 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1520 /* Nothing requested OR nothing left */
1521 if (copy_n == 0)
1522 return 0;
1525 if (copy_n == -2)
1527 request_buffer_handle(CUR_TI->audio_hid);
1530 /* Let the disk buffer catch fill until enough data is available */
1531 while (copy_n == -2)
1533 sleep(1);
1535 if (ci.stop_codec || ci.new_track)
1536 return 0;
1538 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1541 /* Update read and other position pointers */
1542 bufadvance(CUR_TI->audio_hid, copy_n);
1543 ci.curpos += copy_n;
1545 /* Return the actual amount of data copied to the buffer */
1546 return copy_n;
1547 } /* codec_filebuf_callback */
1549 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1551 size_t copy_n = reqsize;
1552 ssize_t ret;
1553 void *ptr;
1555 if (!playing)
1557 *realsize = 0;
1558 return NULL;
1561 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1562 if (ret >= 0)
1563 copy_n = MIN((size_t)ret, reqsize);
1565 if (copy_n == 0)
1567 *realsize = 0;
1568 return NULL;
1571 if (ret == -2)
1573 request_buffer_handle(CUR_TI->audio_hid);
1576 /* Let the disk buffer catch fill until enough data is available */
1577 while (ret == -2)
1579 sleep(1);
1581 if (ci.stop_codec || ci.new_track)
1583 *realsize = 0;
1584 return NULL;
1586 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1588 copy_n = MIN((size_t)ret, reqsize);
1590 *realsize = copy_n;
1592 return ptr;
1593 } /* codec_request_buffer_callback */
1595 static int get_codec_base_type(int type)
1597 switch (type) {
1598 case AFMT_MPA_L1:
1599 case AFMT_MPA_L2:
1600 case AFMT_MPA_L3:
1601 return AFMT_MPA_L3;
1604 return type;
1607 static void codec_advance_buffer_callback(size_t amount)
1609 bufadvance(CUR_TI->audio_hid, amount);
1610 ci.curpos += amount;
1611 codec_set_offset_callback(ci.curpos);
1614 static void codec_advance_buffer_loc_callback(void *ptr)
1616 size_t amount = get_offset(CUR_TI->audio_hid, ptr);
1618 codec_advance_buffer_callback(amount);
1621 /* Copied from mpeg.c. Should be moved somewhere else. */
1622 static int codec_get_file_pos(void)
1624 int pos = -1;
1625 struct mp3entry *id3 = audio_current_track();
1627 if (id3->vbr)
1629 if (id3->has_toc)
1631 /* Use the TOC to find the new position */
1632 unsigned int percent, remainder;
1633 int curtoc, nexttoc, plen;
1635 percent = (id3->elapsed*100)/id3->length;
1636 if (percent > 99)
1637 percent = 99;
1639 curtoc = id3->toc[percent];
1641 if (percent < 99)
1642 nexttoc = id3->toc[percent+1];
1643 else
1644 nexttoc = 256;
1646 pos = (id3->filesize/256)*curtoc;
1648 /* Use the remainder to get a more accurate position */
1649 remainder = (id3->elapsed*100)%id3->length;
1650 remainder = (remainder*100)/id3->length;
1651 plen = (nexttoc - curtoc)*(id3->filesize/256);
1652 pos += (plen/100)*remainder;
1654 else
1656 /* No TOC exists, estimate the new position */
1657 pos = (id3->filesize / (id3->length / 1000)) *
1658 (id3->elapsed / 1000);
1661 else if (id3->bitrate)
1662 pos = id3->elapsed * (id3->bitrate / 8);
1663 else
1664 return -1;
1666 pos += id3->first_frame_offset;
1668 /* Don't seek right to the end of the file so that we can
1669 transition properly to the next song */
1670 if (pos >= (int)(id3->filesize - id3->id3v1len))
1671 pos = id3->filesize - id3->id3v1len - 1;
1673 return pos;
1676 static off_t codec_mp3_get_filepos_callback(int newtime)
1678 off_t newpos;
1680 curtrack_id3.elapsed = newtime;
1681 newpos = codec_get_file_pos();
1683 return newpos;
1686 static void codec_seek_complete_callback(void)
1688 logf("seek_complete");
1689 if (pcm_is_paused())
1691 /* If this is not a seamless seek, clear the buffer */
1692 pcmbuf_play_stop();
1693 dsp_configure(DSP_FLUSH, 0);
1695 /* If playback was not 'deliberately' paused, unpause now */
1696 if (!paused)
1697 pcmbuf_pause(false);
1699 ci.seek_time = 0;
1702 static bool codec_seek_buffer_callback(size_t newpos)
1704 logf("codec_seek_buffer_callback");
1706 int ret = bufseek(CUR_TI->audio_hid, newpos);
1707 if (ret == 0) {
1708 ci.curpos = newpos;
1709 return true;
1711 else {
1712 return false;
1716 static void codec_configure_callback(int setting, intptr_t value)
1718 switch (setting) {
1719 case CODEC_SET_FILEBUF_WATERMARK:
1720 conf_watermark = value;
1721 set_filebuf_watermark(buffer_margin);
1722 break;
1724 case CODEC_SET_FILEBUF_CHUNKSIZE:
1725 conf_filechunk = value;
1726 break;
1728 case CODEC_SET_FILEBUF_PRESEEK:
1729 conf_preseek = value;
1730 break;
1732 default:
1733 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1737 static void codec_track_changed(void)
1739 automatic_skip = false;
1740 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1741 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1744 static void codec_pcmbuf_track_changed_callback(void)
1746 pcmbuf_set_position_callback(NULL);
1747 codec_track_changed();
1750 static void codec_discard_codec_callback(void)
1752 if (CUR_TI->codec_hid > 0)
1754 bufclose(CUR_TI->codec_hid);
1755 CUR_TI->codec_hid = 0;
1756 CUR_TI->codecsize = 0;
1759 #if 0
1760 /* Check if a buffer desync has happened, log it and stop playback. */
1761 if (buf_ridx != CUR_TI->buf_idx)
1763 int offset = CUR_TI->buf_idx - buf_ridx;
1764 size_t new_used = bufused() - offset;
1766 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1767 logf("Used off:%d",bufused() - new_used);
1769 /* This is a fatal internal error and it's not safe to
1770 * continue playback. */
1771 ci.stop_codec = true;
1772 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1774 #endif
1777 static inline void codec_gapless_track_change(void) {
1778 /* callback keeps the progress bar moving while the pcmbuf empties */
1779 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1780 /* set the pcmbuf callback for when the track really changes */
1781 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1784 static inline void codec_crossfade_track_change(void) {
1785 /* Initiate automatic crossfade mode */
1786 pcmbuf_crossfade_init(false);
1787 /* Notify the wps that the track change starts now */
1788 codec_track_changed();
1791 static void codec_track_skip_done(bool was_manual)
1793 int crossfade_mode = global_settings.crossfade;
1795 /* Manual track change (always crossfade or flush audio). */
1796 if (was_manual)
1798 pcmbuf_crossfade_init(true);
1799 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1800 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1802 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1803 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1804 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1806 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1808 if (global_settings.playlist_shuffle)
1809 /* shuffle mode is on, so crossfade: */
1810 codec_crossfade_track_change();
1811 else
1812 /* shuffle mode is off, so do a gapless track change */
1813 codec_gapless_track_change();
1815 else
1816 /* normal crossfade: */
1817 codec_crossfade_track_change();
1819 else
1820 /* normal gapless playback. */
1821 codec_gapless_track_change();
1824 static bool codec_load_next_track(void)
1826 intptr_t result = Q_CODEC_REQUEST_FAILED;
1828 prev_track_elapsed = curtrack_id3.elapsed;
1830 if (ci.seek_time)
1831 codec_seek_complete_callback();
1833 #ifdef AB_REPEAT_ENABLE
1834 ab_end_of_track_report();
1835 #endif
1837 logf("Request new track");
1839 if (ci.new_track == 0)
1841 ci.new_track++;
1842 automatic_skip = true;
1845 if (!ci.stop_codec)
1847 trigger_cpu_boost();
1848 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1849 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1852 switch (result)
1854 case Q_CODEC_REQUEST_COMPLETE:
1855 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1856 codec_track_skip_done(!automatic_skip);
1857 return true;
1859 case Q_CODEC_REQUEST_FAILED:
1860 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1861 ci.new_track = 0;
1862 ci.stop_codec = true;
1863 return false;
1865 default:
1866 LOGFQUEUE("codec |< default");
1867 ci.stop_codec = true;
1868 return false;
1872 static bool codec_request_next_track_callback(void)
1874 int prev_codectype;
1876 if (ci.stop_codec || !playing)
1877 return false;
1879 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1881 if (!codec_load_next_track())
1882 return false;
1884 /* Check if the next codec is the same file. */
1885 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1887 logf("New track loaded");
1888 codec_discard_codec_callback();
1889 return true;
1891 else
1893 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1894 return false;
1898 static void codec_thread(void)
1900 struct queue_event ev;
1901 int status;
1902 size_t wrap;
1904 while (1) {
1905 status = 0;
1906 queue_wait(&codec_queue, &ev);
1908 switch (ev.id) {
1909 case Q_CODEC_LOAD_DISK:
1910 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1911 queue_reply(&codec_queue, 1);
1912 audio_codec_loaded = true;
1913 #ifdef PLAYBACK_VOICE
1914 /* Don't sent messages to voice codec if it's already swapped
1915 out or it will never get this */
1916 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1918 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1919 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1921 semaphore_wait(&sem_codecthread);
1922 event_set_state(&event_codecthread, true);
1923 #endif
1924 set_current_codec(CODEC_IDX_AUDIO);
1925 ci.stop_codec = false;
1926 status = codec_load_file((const char *)ev.data, &ci);
1927 DEBUGF("codec_load = %d\n", status);
1928 #ifdef PLAYBACK_VOICE
1929 semaphore_release(&sem_codecthread);
1930 #endif
1931 break;
1933 case Q_CODEC_LOAD:
1934 LOGFQUEUE("codec < Q_CODEC_LOAD");
1935 if (CUR_TI->codec_hid <= 0) {
1936 logf("Codec slot is empty!");
1937 /* Wait for the pcm buffer to go empty */
1938 while (pcm_is_playing())
1939 yield();
1940 /* This must be set to prevent an infinite loop */
1941 ci.stop_codec = true;
1942 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1943 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1944 break;
1947 audio_codec_loaded = true;
1948 #ifdef PLAYBACK_VOICE
1949 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1951 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1952 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1954 semaphore_wait(&sem_codecthread);
1955 event_set_state(&event_codecthread, true);
1956 #endif
1957 set_current_codec(CODEC_IDX_AUDIO);
1958 ci.stop_codec = false;
1959 wrap = (size_t)&filebuf[filebuflen] - (size_t)bufgetcodec(CUR_TI);
1960 status = codec_load_ram(bufgetcodec(CUR_TI), CUR_TI->codecsize,
1961 &filebuf[0], wrap, &ci);
1962 #ifdef PLAYBACK_VOICE
1963 semaphore_release(&sem_codecthread);
1964 #endif
1965 break;
1967 #ifdef AUDIO_HAVE_RECORDING
1968 case Q_ENCODER_LOAD_DISK:
1969 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1970 audio_codec_loaded = false; /* Not audio codec! */
1971 #ifdef PLAYBACK_VOICE
1972 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1974 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1975 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
1977 semaphore_wait(&sem_codecthread);
1978 event_set_state(&event_codecthread, true);
1979 #endif
1980 logf("loading encoder");
1981 set_current_codec(CODEC_IDX_AUDIO);
1982 ci.stop_encoder = false;
1983 status = codec_load_file((const char *)ev.data, &ci);
1984 #ifdef PLAYBACK_VOICE
1985 semaphore_release(&sem_codecthread);
1986 #endif
1987 logf("encoder stopped");
1988 break;
1989 #endif /* AUDIO_HAVE_RECORDING */
1991 #ifndef SIMULATOR
1992 case SYS_USB_CONNECTED:
1993 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1994 queue_clear(&codec_queue);
1995 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1996 usb_wait_for_disconnect(&codec_queue);
1997 break;
1998 #endif
2000 default:
2001 LOGFQUEUE("codec < default");
2004 if (audio_codec_loaded)
2006 if (ci.stop_codec)
2008 status = CODEC_OK;
2009 if (!playing)
2010 pcmbuf_play_stop();
2013 audio_codec_loaded = false;
2016 switch (ev.id) {
2017 case Q_CODEC_LOAD_DISK:
2018 case Q_CODEC_LOAD:
2019 LOGFQUEUE("codec < Q_CODEC_LOAD");
2020 if (playing)
2022 if (ci.new_track || status != CODEC_OK)
2024 if (!ci.new_track)
2026 logf("Codec failure");
2027 gui_syncsplash(HZ*2, "Codec failure");
2030 if (!codec_load_next_track())
2032 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2033 /* End of playlist */
2034 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2035 break;
2038 else
2040 logf("Codec finished");
2041 if (ci.stop_codec)
2043 /* Wait for the audio to stop playing before
2044 * triggering the WPS exit */
2045 while(pcm_is_playing())
2047 curtrack_id3.elapsed =
2048 curtrack_id3.length - pcmbuf_get_latency();
2049 sleep(1);
2051 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2052 /* End of playlist */
2053 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2054 break;
2058 if (CUR_TI->codec_hid > 0)
2060 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2061 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2063 else
2065 const char *codec_fn =
2066 get_codec_filename(curtrack_id3.codectype);
2067 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2068 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2069 (intptr_t)codec_fn);
2072 break;
2074 #ifdef AUDIO_HAVE_RECORDING
2075 case Q_ENCODER_LOAD_DISK:
2076 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2078 if (status == CODEC_OK)
2079 break;
2081 logf("Encoder failure");
2082 gui_syncsplash(HZ*2, "Encoder failure");
2084 if (ci.enc_codec_loaded < 0)
2085 break;
2087 logf("Encoder failed to load");
2088 ci.enc_codec_loaded = -1;
2089 break;
2090 #endif /* AUDIO_HAVE_RECORDING */
2092 default:
2093 LOGFQUEUE("codec < default");
2095 } /* end switch */
2100 /* --- Audio thread --- */
2102 #if 0
2103 static bool audio_filebuf_is_lowdata(void)
2105 return bufused() < AUDIO_FILEBUF_CRITICAL;
2107 #endif
2109 static bool audio_have_tracks(void)
2111 return track_ridx != track_widx || CUR_TI->filesize;
2114 static bool audio_have_free_tracks(void)
2116 if (track_widx < track_ridx)
2117 return track_widx + 1 < track_ridx;
2118 else if (track_ridx == 0)
2119 return track_widx < MAX_TRACK - 1;
2121 return true;
2124 int audio_track_count(void)
2126 if (audio_have_tracks())
2128 int relative_track_widx = track_widx;
2130 if (track_ridx > track_widx)
2131 relative_track_widx += MAX_TRACK;
2133 return relative_track_widx - track_ridx + 1;
2136 return 0;
2139 long audio_filebufused(void)
2141 return (long) bufused();
2144 #if 0
2145 /* Count the data BETWEEN the selected tracks */
2146 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2148 size_t amount = 0;
2149 bool need_wrap = to_track < from_track;
2151 while (1)
2153 if (++from_track >= MAX_TRACK)
2155 from_track -= MAX_TRACK;
2156 need_wrap = false;
2159 if (from_track >= to_track && !need_wrap)
2160 break;
2162 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2164 return amount;
2166 #endif
2168 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2170 (void)new_track_ridx;
2171 (void)old_track_ridx;
2172 #if 0
2173 size_t amount;
2175 /* Start with the remainder of the previously playing track */
2176 amount = tracks[old_track_ridx].filesize - ci.curpos;
2177 /* Then collect all data from tracks in between them */
2178 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2179 logf("bwf:%ldB", (long) amount);
2181 if (amount > bufused())
2182 return false;
2184 /* Wind the buffer to the beginning of the target track or its codec */
2185 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2186 #endif
2187 return true;
2190 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2192 (void)new_track_ridx;
2193 (void)old_track_ridx;
2194 #if 0
2195 /* Available buffer data */
2196 size_t buf_back;
2197 /* Start with the previously playing track's data and our data */
2198 size_t amount;
2200 amount = ci.curpos;
2201 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2203 /* If we're not just resetting the current track */
2204 if (new_track_ridx != old_track_ridx)
2206 /* Need to wind to before the old track's codec and our filesize */
2207 amount += tracks[old_track_ridx].codecsize;
2208 amount += tracks[new_track_ridx].filesize;
2210 /* Rewind the old track to its beginning */
2211 tracks[old_track_ridx].available =
2212 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2215 /* If the codec was ever buffered */
2216 if (tracks[new_track_ridx].codecsize)
2218 /* Add the codec to the needed size */
2219 amount += tracks[new_track_ridx].codecsize;
2220 tracks[new_track_ridx].has_codec = true;
2223 /* Then collect all data from tracks between new and old */
2224 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2226 /* Do we have space to make this skip? */
2227 if (amount > buf_back)
2228 return false;
2230 logf("bwb:%ldB",amount);
2232 /* Rewind the buffer to the beginning of the target track or its codec */
2233 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2235 /* Reset to the beginning of the new track */
2236 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2237 #endif
2238 return true;
2241 static void audio_update_trackinfo(void)
2243 if (CUR_TI->id3_hid > 0)
2244 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
2246 CUR_TI->taginfo_ready = (CUR_TI->id3_hid > 0);
2248 int next_idx = track_ridx + 1;
2249 next_idx &= MAX_TRACK_MASK;
2251 if (tracks[next_idx].id3_hid > 0)
2252 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
2254 tracks[next_idx].taginfo_ready = (tracks[next_idx].id3_hid > 0);
2256 ci.filesize = CUR_TI->filesize;
2257 curtrack_id3.elapsed = 0;
2258 curtrack_id3.offset = 0;
2259 ci.id3 = &curtrack_id3;
2260 ci.curpos = 0;
2261 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2264 #if 0
2265 /* Yield to codecs for as long as possible if they are in need of data
2266 * return true if the caller should break to let the audio thread process
2267 * new events */
2268 static bool audio_yield_codecs(void)
2270 yield();
2272 if (!queue_empty(&audio_queue))
2273 return true;
2275 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2276 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2278 if (filling)
2279 yield();
2280 else
2281 sleep(2);
2283 if (!queue_empty(&audio_queue))
2284 return true;
2287 return false;
2289 #endif
2291 static void audio_clear_track_entries(bool clear_unbuffered)
2293 int cur_idx = track_widx;
2294 int last_idx = -1;
2296 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2298 /* Loop over all tracks from write-to-read */
2299 while (1)
2301 cur_idx++;
2302 cur_idx &= MAX_TRACK_MASK;
2304 if (cur_idx == track_ridx)
2305 break;
2307 /* If the track is buffered, conditionally clear/notify,
2308 * otherwise clear the track if that option is selected */
2309 if (tracks[cur_idx].event_sent)
2311 if (last_idx >= 0)
2313 /* If there is an unbuffer callback, call it, otherwise,
2314 * just clear the track */
2315 if (track_unbuffer_callback && tracks[last_idx].id3_hid > 0)
2316 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2318 clear_track_info(&tracks[last_idx]);
2320 last_idx = cur_idx;
2322 else if (clear_unbuffered)
2323 clear_track_info(&tracks[cur_idx]);
2326 /* We clear the previous instance of a buffered track throughout
2327 * the above loop to facilitate 'last' detection. Clear/notify
2328 * the last track here */
2329 if (last_idx >= 0)
2331 if (track_unbuffer_callback && tracks[last_idx].id3_hid > 0)
2332 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2333 clear_track_info(&tracks[last_idx]);
2337 static void audio_release_tracks(void)
2339 int cur_idx = track_ridx;
2341 logf("releasing all tracks");
2343 while (1)
2345 clear_track_info(&tracks[cur_idx]);
2347 cur_idx++;
2348 cur_idx &= MAX_TRACK_MASK;
2350 if (cur_idx == track_widx)
2351 break;
2355 #if 0
2356 /* FIXME: This code should be made more generic and move to metadata.c */
2357 static void audio_strip_tags(void)
2359 int i;
2360 static const unsigned char tag[] = "TAG";
2361 static const unsigned char apetag[] = "APETAGEX";
2362 size_t tag_idx;
2363 size_t cur_idx;
2364 size_t len, version;
2366 tag_idx = RINGBUF_SUB(buf_widx, 128);
2368 if (bufused() > 128 && tag_idx > buf_ridx)
2370 cur_idx = tag_idx;
2371 for(i = 0;i < 3;i++)
2373 if(filebuf[cur_idx] != tag[i])
2374 goto strip_ape_tag;
2376 cur_idx = RINGBUF_ADD(cur_idx, 1);
2379 /* Skip id3v1 tag */
2380 logf("Skipping ID3v1 tag");
2381 buf_widx = tag_idx;
2382 tracks[track_widx].available -= 128;
2383 tracks[track_widx].filesize -= 128;
2386 strip_ape_tag:
2387 /* Check for APE tag (look for the APE tag footer) */
2388 tag_idx = RINGBUF_SUB(buf_widx, 32);
2390 if (bufused() > 32 && tag_idx > buf_ridx)
2392 cur_idx = tag_idx;
2393 for(i = 0;i < 8;i++)
2395 if(filebuf[cur_idx] != apetag[i])
2396 return;
2398 cur_idx = RINGBUF_ADD(cur_idx, 1);
2401 /* Read the version and length from the footer */
2402 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2403 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2404 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2405 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2406 if (version == 2000)
2407 len += 32; /* APEv2 has a 32 byte header */
2409 /* Skip APE tag */
2410 if (bufused() > len)
2412 logf("Skipping APE tag (%ldB)", len);
2413 buf_widx = RINGBUF_SUB(buf_widx, len);
2414 tracks[track_widx].available -= len;
2415 tracks[track_widx].filesize -= len;
2419 #endif
2421 #if 0
2422 /* Returns true if a whole file is read, false otherwise */
2423 static bool audio_read_file(size_t minimum)
2425 bool ret_val = false;
2427 /* If we're called and no file is open, this is an error */
2428 if (current_fd < 0)
2430 logf("Bad fd in arf");
2431 /* Give some hope of miraculous recovery by forcing a track reload */
2432 tracks[track_widx].filesize = 0;
2433 /* Stop this buffering run */
2434 return ret_val;
2437 trigger_cpu_boost();
2438 while (tracks[track_widx].filerem > 0)
2440 size_t copy_n;
2441 int overlap;
2442 int rc;
2444 /* copy_n is the largest chunk that is safe to read */
2445 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2447 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2448 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2449 break;
2451 /* rc is the actual amount read */
2452 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2454 if (rc < 0)
2456 logf("File ended %ldB early", tracks[track_widx].filerem);
2457 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2458 tracks[track_widx].filerem = 0;
2459 break;
2462 /* How much of the playing track did we overwrite */
2463 if (buf_widx == CUR_TI->buf_idx)
2465 /* Special handling; zero or full overlap? */
2466 if (track_widx == track_ridx && CUR_TI->available == 0)
2467 overlap = 0;
2468 else
2469 overlap = rc;
2471 else
2472 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2474 if ((unsigned)rc > tracks[track_widx].filerem)
2476 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2477 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2478 tracks[track_widx].filerem = rc;
2481 /* Advance buffer */
2482 buf_widx = RINGBUF_ADD(buf_widx, rc);
2483 tracks[track_widx].available += rc;
2484 tracks[track_widx].filerem -= rc;
2486 /* If we write into the playing track, adjust it's buffer info */
2487 if (overlap > 0)
2489 CUR_TI->buf_idx += overlap;
2490 CUR_TI->start_pos += overlap;
2493 /* For a rebuffer, fill at least this minimum */
2494 if (minimum > (unsigned)rc)
2495 minimum -= rc;
2496 /* Let the codec process up to the watermark */
2497 /* Break immediately if this is a quick buffer, or there is an event */
2498 else if (minimum || audio_yield_codecs())
2500 /* Exit quickly, but don't stop the overall buffering process */
2501 ret_val = true;
2502 break;
2506 if (tracks[track_widx].filerem == 0)
2508 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2509 close(current_fd);
2510 current_fd = -1;
2511 audio_strip_tags();
2513 track_widx++;
2514 track_widx &= MAX_TRACK_MASK;
2516 tracks[track_widx].filesize = 0;
2517 return true;
2519 else
2521 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2522 tracks[track_widx].filesize - tracks[track_widx].filerem);
2523 return ret_val;
2526 #endif
2528 static bool audio_loadcodec(bool start_play)
2530 int fd;
2531 int prev_track;
2532 char codec_path[MAX_PATH]; /* Full path to codec */
2534 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play ? "true" : "false");
2536 if (tracks[track_widx].id3_hid <= 0) {
2537 DEBUGF("track ID3 info not ready\n");
2538 return false;
2541 const char * codec_fn =
2542 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2543 if (codec_fn == NULL)
2544 return false;
2546 tracks[track_widx].codec_hid = 0;
2548 if (start_play)
2550 /* Load the codec directly from disk and save some memory. */
2551 track_ridx = track_widx;
2552 ci.filesize = CUR_TI->filesize;
2553 ci.id3 = &curtrack_id3;
2554 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2555 ci.curpos = 0;
2556 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2557 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2558 return true;
2560 else
2562 /* If we already have another track than this one buffered */
2563 if (track_widx != track_ridx)
2565 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2567 /* If the previous codec is the same as this one, there is no need
2568 * to put another copy of it on the file buffer */
2569 if (get_codec_base_type(
2570 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2571 get_codec_base_type(
2572 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2573 && audio_codec_loaded)
2575 logf("Reusing prev. codec");
2576 return true;
2581 codec_get_full_path(codec_path, codec_fn);
2583 fd = open(codec_path, O_RDONLY);
2584 if (fd < 0)
2586 logf("Codec doesn't exist!");
2587 return false;
2590 tracks[track_widx].codecsize = filesize(fd);
2592 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2593 if (tracks[track_widx].codec_hid < 0)
2595 logf("Not enough space");
2596 close(fd);
2597 return false;
2600 close(fd);
2601 logf("Loaded codec");
2603 return true;
2606 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2607 static void audio_set_elapsed(struct mp3entry* id3)
2609 unsigned long offset = id3->offset > id3->first_frame_offset ?
2610 id3->offset - id3->first_frame_offset : 0;
2612 if ( id3->vbr ) {
2613 if ( id3->has_toc ) {
2614 /* calculate elapsed time using TOC */
2615 int i;
2616 unsigned int remainder, plen, relpos, nextpos;
2618 /* find wich percent we're at */
2619 for (i=0; i<100; i++ )
2620 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2621 break;
2623 i--;
2624 if (i < 0)
2625 i = 0;
2627 relpos = id3->toc[i];
2629 if (i < 99)
2630 nextpos = id3->toc[i+1];
2631 else
2632 nextpos = 256;
2634 remainder = offset - (relpos * (id3->filesize / 256));
2636 /* set time for this percent (divide before multiply to prevent
2637 overflow on long files. loss of precision is negligible on
2638 short files) */
2639 id3->elapsed = i * (id3->length / 100);
2641 /* calculate remainder time */
2642 plen = (nextpos - relpos) * (id3->filesize / 256);
2643 id3->elapsed += (((remainder * 100) / plen) *
2644 (id3->length / 10000));
2646 else {
2647 /* no TOC exists. set a rough estimate using average bitrate */
2648 int tpk = id3->length /
2649 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2650 1024);
2651 id3->elapsed = offset / 1024 * tpk;
2654 else
2656 /* constant bitrate, use exact calculation */
2657 if (id3->bitrate != 0)
2658 id3->elapsed = offset / (id3->bitrate / 8);
2662 /* Load one track by making the appropriate bufopen calls. Return true if
2663 everything required was loaded correctly, false if not. */
2664 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2666 (void)rebuffer;
2667 char *trackname;
2668 char msgbuf[80];
2669 int fd = -1;
2670 int file_offset = 0;
2671 struct mp3entry id3;
2673 /* Stop buffer filling if there is no free track entries.
2674 Don't fill up the last track entry (we wan't to store next track
2675 metadata there). */
2676 if (!audio_have_free_tracks())
2678 logf("No free tracks");
2679 return false;
2682 last_peek_offset++;
2683 peek_again:
2684 logf("Buffering track:%d/%d", track_widx, track_ridx);
2685 /* Get track name from current playlist read position. */
2686 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2688 /* Handle broken playlists. */
2689 fd = open(trackname, O_RDONLY);
2690 if (fd < 0)
2692 logf("Open failed");
2693 /* Skip invalid entry from playlist. */
2694 playlist_skip_entry(NULL, last_peek_offset);
2696 else
2697 break;
2700 if (!trackname)
2702 logf("End-of-playlist");
2703 playlist_end = true;
2704 return false;
2707 tracks[track_widx].filesize = filesize(fd);
2709 /* Set default values */
2710 if (start_play)
2712 int last_codec = current_codec;
2714 set_current_codec(CODEC_IDX_AUDIO);
2715 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2716 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2717 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2718 dsp_configure(DSP_RESET, 0);
2719 set_current_codec(last_codec);
2721 track_changed = true;
2722 playlist_update_resume_info(audio_current_track());
2725 /* Get track metadata if we don't already have it. */
2726 if (tracks[track_widx].id3_hid <= 0)
2728 if (get_metadata(&id3, fd, trackname))
2730 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2731 TYPE_ID3);
2732 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2734 if (tracks[track_widx].id3_hid <= 0)
2736 DEBUGF("failed to allocate space for metadata\n");
2737 last_peek_offset--;
2738 close(fd);
2739 return false;
2742 if (track_widx == track_ridx)
2743 copy_mp3entry(&curtrack_id3, &id3);
2744 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2745 copy_mp3entry(&nexttrack_id3, &id3);
2747 if (start_play)
2749 track_changed = true;
2750 playlist_update_resume_info(audio_current_track());
2753 else
2755 logf("mde:%s!",trackname);
2757 /* Skip invalid entry from playlist. */
2758 playlist_skip_entry(NULL, last_peek_offset);
2759 tracks[track_widx].taginfo_ready = false;
2760 goto peek_again;
2765 close(fd);
2767 #if 0
2768 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2770 char cuepath[MAX_PATH];
2772 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2774 if (look_for_cuesheet_file(trackname, cuepath) &&
2775 parse_cuesheet(cuepath, cue))
2777 strcpy((cue)->audio_filename, trackname);
2778 if (start_play)
2779 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2782 #endif
2784 /* Load the codec. */
2785 if (!audio_loadcodec(start_play))
2787 if (tracks[track_widx].codecsize)
2789 /* No space for codec on buffer, not an error */
2790 tracks[track_widx].codecsize = 0;
2791 return false;
2794 /* This is an error condition, either no codec was found, or reading
2795 * the codec file failed part way through, either way, skip the track */
2796 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2797 /* We should not use gui_syncplash from audio thread! */
2798 gui_syncsplash(HZ*2, msgbuf);
2799 /* Skip invalid entry from playlist. */
2800 playlist_skip_entry(NULL, last_peek_offset);
2801 tracks[track_widx].taginfo_ready = false;
2802 goto peek_again;
2805 struct mp3entry *track_id3;
2807 if (track_widx == track_ridx)
2808 track_id3 = &curtrack_id3;
2809 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2810 track_id3 = &nexttrack_id3;
2811 else
2812 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2814 set_filebuf_watermark(buffer_margin);
2815 track_id3->elapsed = 0;
2817 if (offset > 0)
2819 switch (track_id3->codectype) {
2820 case AFMT_MPA_L1:
2821 case AFMT_MPA_L2:
2822 case AFMT_MPA_L3:
2823 file_offset = offset;
2824 track_id3->offset = offset;
2825 audio_set_elapsed(track_id3);
2826 ci.curpos = offset;
2827 break;
2829 case AFMT_WAVPACK:
2830 file_offset = offset;
2831 track_id3->offset = offset;
2832 track_id3->elapsed = track_id3->length / 2;
2833 ci.curpos = offset;
2834 break;
2836 case AFMT_OGG_VORBIS:
2837 case AFMT_SPEEX:
2838 case AFMT_FLAC:
2839 case AFMT_PCM_WAV:
2840 case AFMT_A52:
2841 case AFMT_AAC:
2842 case AFMT_MPC:
2843 case AFMT_APE:
2844 track_id3->offset = offset;
2845 break;
2849 logf("alt:%s", trackname);
2851 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, TYPE_AUDIO);
2853 if (tracks[track_widx].audio_hid <= 0)
2854 return false;
2856 if (start_play)
2858 request_buffer_handle(tracks[track_widx].audio_hid);
2861 track_widx++;
2862 track_widx &= MAX_TRACK_MASK;
2864 return true;
2867 #if 0
2868 static bool audio_read_next_metadata(void)
2870 int fd;
2871 char *trackname;
2872 int next_idx;
2873 int status;
2875 next_idx = track_widx;
2876 if (tracks[next_idx].id3_hid > 0)
2878 next_idx++;
2879 next_idx &= MAX_TRACK_MASK;
2881 if (tracks[next_idx].id3_hid > 0)
2882 return true;
2885 trackname = playlist_peek(last_peek_offset + 1);
2886 if (!trackname)
2887 return false;
2889 fd = open(trackname, O_RDONLY);
2890 if (fd < 0)
2891 return false;
2893 struct mp3entry id3;
2895 status = get_metadata(&id3, fd, trackname);
2896 /* Preload the glyphs in the tags */
2897 if (status)
2899 tracks[next_idx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
2901 if (tracks[next_idx].id3_hid > 0)
2903 tracks[next_idx].taginfo_ready = true;
2904 if (id3.title)
2905 lcd_getstringsize(id3.title, NULL, NULL);
2906 if (id3.artist)
2907 lcd_getstringsize(id3.artist, NULL, NULL);
2908 if (id3.album)
2909 lcd_getstringsize(id3.album, NULL, NULL);
2911 else
2912 status = false;
2914 close(fd);
2916 return status;
2918 #endif
2920 /* Send callback events to notify about new tracks. */
2921 static void audio_generate_postbuffer_events(void)
2923 int cur_idx;
2924 int last_idx = -1;
2926 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2928 if (audio_have_tracks())
2930 cur_idx = track_ridx;
2932 while (1) {
2933 if (!tracks[cur_idx].event_sent)
2935 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2937 /* Mark the event 'sent' even if we don't really send one */
2938 tracks[last_idx].event_sent = true;
2939 if (track_buffer_callback && tracks[last_idx].id3_hid > 0)
2940 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2942 last_idx = cur_idx;
2944 if (cur_idx == track_widx)
2945 break;
2946 cur_idx++;
2947 cur_idx &= MAX_TRACK_MASK;
2950 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2952 tracks[last_idx].event_sent = true;
2953 if (track_buffer_callback && tracks[last_idx].id3_hid > 0)
2954 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2959 static bool audio_initialize_buffer_fill(bool clear_tracks)
2961 /* Don't initialize if we're already initialized */
2962 if (filling)
2963 return true;
2965 logf("Starting buffer fill");
2967 /* Set the filling flag true before calling audio_clear_tracks as that
2968 * function can yield and we start looping. */
2969 filling = true;
2971 if (clear_tracks)
2972 audio_clear_track_entries(false);
2974 /* Save the current resume position once. */
2975 playlist_update_resume_info(audio_current_track());
2977 return true;
2980 static void audio_fill_file_buffer(
2981 bool start_play, bool rebuffer, size_t offset)
2983 bool had_next_track = audio_next_track() != NULL;
2984 bool continue_buffering;
2986 /* Must reset the buffer before use if trashed or voice only - voice
2987 file size shouldn't have changed so we can go straight from
2988 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2989 if (buffer_state != BUFFER_STATE_INITIALIZED)
2990 audio_reset_buffer();
2992 if (!audio_initialize_buffer_fill(!start_play))
2993 return ;
2995 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2997 if (!had_next_track && audio_next_track())
2998 track_changed = true;
3000 /* If we're done buffering */
3001 if (!continue_buffering)
3003 //audio_read_next_metadata();
3005 audio_generate_postbuffer_events();
3006 filling = false;
3008 #ifndef SIMULATOR
3009 ata_sleep();
3010 #endif
3014 static void audio_rebuffer(void)
3016 logf("Forcing rebuffer");
3018 clear_track_info(CUR_TI);
3020 /* Reset track pointers */
3021 track_widx = track_ridx;
3022 audio_clear_track_entries(true);
3024 /* Fill the buffer */
3025 last_peek_offset = -1;
3026 ci.curpos = 0;
3028 if (!CUR_TI->taginfo_ready)
3029 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3031 audio_fill_file_buffer(false, true, 0);
3034 static int audio_check_new_track(void)
3036 DEBUGF("audio_check_new_track\n");
3038 int track_count = audio_track_count();
3039 int old_track_ridx = track_ridx;
3040 bool forward;
3042 if (dir_skip)
3044 dir_skip = false;
3045 if (playlist_next_dir(ci.new_track))
3047 ci.new_track = 0;
3048 audio_rebuffer();
3049 goto skip_done;
3051 else
3053 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3054 return Q_CODEC_REQUEST_FAILED;
3058 if (new_playlist)
3059 ci.new_track = 0;
3061 /* If the playlist isn't that big */
3062 if (!playlist_check(ci.new_track))
3064 if (ci.new_track >= 0)
3066 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3067 return Q_CODEC_REQUEST_FAILED;
3069 /* Find the beginning backward if the user over-skips it */
3070 while (!playlist_check(++ci.new_track))
3071 if (ci.new_track >= 0)
3073 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3074 return Q_CODEC_REQUEST_FAILED;
3077 /* Update the playlist */
3078 last_peek_offset -= ci.new_track;
3080 if (playlist_next(ci.new_track) < 0)
3082 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3083 return Q_CODEC_REQUEST_FAILED;
3086 if (new_playlist)
3088 ci.new_track = 1;
3089 new_playlist = false;
3092 /* Save the old track */
3093 /* prev_ti = CUR_TI; */
3095 int i, idx;
3096 for (i = 0; i < ci.new_track; i++)
3098 idx = (track_ridx + i) & MAX_TRACK_MASK;
3099 clear_track_info(&tracks[idx]);
3102 /* Move to the new track */
3103 track_ridx += ci.new_track;
3104 track_ridx &= MAX_TRACK_MASK;
3106 if (automatic_skip)
3107 playlist_end = false;
3109 track_changed = !automatic_skip;
3111 /* If it is not safe to even skip this many track entries */
3112 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3114 ci.new_track = 0;
3115 audio_rebuffer();
3116 goto skip_done;
3119 forward = ci.new_track > 0;
3120 ci.new_track = 0;
3122 /* If the target track is clearly not in memory */
3123 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3125 audio_rebuffer();
3126 goto skip_done;
3129 /* The track may be in memory, see if it really is */
3130 if (forward)
3132 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3133 audio_rebuffer();
3135 else
3137 int cur_idx = track_ridx;
3138 bool taginfo_ready = true;
3139 bool wrap = track_ridx > old_track_ridx;
3141 while (1)
3143 cur_idx++;
3144 cur_idx &= MAX_TRACK_MASK;
3145 if (!(wrap || cur_idx < old_track_ridx))
3146 break;
3148 /* If we hit a track in between without valid tag info, bail */
3149 if (!tracks[cur_idx].taginfo_ready)
3151 taginfo_ready = false;
3152 break;
3155 tracks[cur_idx].available = tracks[cur_idx].filesize;
3156 if (tracks[cur_idx].codecsize)
3157 tracks[cur_idx].has_codec = true;*/
3159 if (taginfo_ready)
3161 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3162 audio_rebuffer();
3164 else
3166 audio_rebuffer();
3170 skip_done:
3171 audio_update_trackinfo();
3172 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3173 return Q_CODEC_REQUEST_COMPLETE;
3176 #if 0
3177 static int audio_rebuffer_and_seek(size_t newpos)
3179 size_t real_preseek;
3180 int fd;
3181 char *trackname;
3183 /* (Re-)open current track's file handle. */
3184 trackname = playlist_peek(0);
3185 fd = open(trackname, O_RDONLY);
3186 if (fd < 0)
3188 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3189 return Q_CODEC_REQUEST_FAILED;
3192 if (current_fd >= 0)
3193 close(current_fd);
3194 current_fd = fd;
3196 playlist_end = false;
3198 ci.curpos = newpos;
3200 /* Clear codec buffer. */
3201 track_widx = track_ridx;
3202 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3204 last_peek_offset = 0;
3205 filling = false;
3206 audio_initialize_buffer_fill(true);
3208 /* This may have been tweaked by the id3v1 code */
3209 CUR_TI->filesize=filesize(fd);
3210 if (newpos > conf_preseek)
3212 CUR_TI->start_pos = newpos - conf_preseek;
3213 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3214 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3215 real_preseek = conf_preseek;
3217 else
3219 CUR_TI->start_pos = 0;
3220 CUR_TI->filerem = CUR_TI->filesize;
3221 real_preseek = newpos;
3224 CUR_TI->available = 0;
3226 audio_read_file(real_preseek);
3228 /* Account for the data we just read that is 'behind' us now */
3229 CUR_TI->available -= real_preseek;
3231 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3233 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3234 return Q_CODEC_REQUEST_COMPLETE;
3236 #endif
3238 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3239 bool last_track))
3241 track_buffer_callback = handler;
3244 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3245 bool last_track))
3247 track_unbuffer_callback = handler;
3250 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3252 track_changed_callback = handler;
3255 unsigned long audio_prev_elapsed(void)
3257 return prev_track_elapsed;
3260 static void audio_stop_codec_flush(void)
3262 ci.stop_codec = true;
3263 pcmbuf_pause(true);
3265 while (audio_codec_loaded)
3266 yield();
3268 /* If the audio codec is not loaded any more, and the audio is still
3269 * playing, it is now and _only_ now safe to call this function from the
3270 * audio thread */
3271 if (pcm_is_playing())
3272 pcmbuf_play_stop();
3273 pcmbuf_pause(paused);
3276 static void audio_stop_playback(void)
3278 /* If we were playing, save resume information */
3279 if (playing)
3281 struct mp3entry *id3 = NULL;
3283 if (!playlist_end || !ci.stop_codec)
3285 /* Set this early, the outside code yields and may allow the codec
3286 to try to wait for a reply on a buffer wait */
3287 ci.stop_codec = true;
3288 id3 = audio_current_track();
3291 /* Save the current playing spot, or NULL if the playlist has ended */
3292 playlist_update_resume_info(id3);
3294 prev_track_elapsed = curtrack_id3.elapsed;
3296 /* Increment index so runtime info is saved in audio_clear_track_entries().
3297 * Done here, as audio_stop_playback() may be called more than once.
3298 * Don't update runtime unless playback is stopped because of end of playlist.
3299 * Updating runtime when manually stopping a tracks, can destroy autoscores
3300 * and playcounts.
3302 if (playlist_end)
3304 track_ridx++;
3305 track_ridx &= MAX_TRACK_MASK;
3309 filling = false;
3310 paused = false;
3311 audio_stop_codec_flush();
3312 playing = false;
3314 /* Close all tracks */
3315 audio_release_tracks();
3317 /* Mark all entries null. */
3318 audio_clear_track_entries(false);
3320 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3321 memset(&nexttrack_id3, 0, sizeof(struct mp3entry));
3324 static void audio_play_start(size_t offset)
3326 #if INPUT_SRC_CAPS != 0
3327 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3328 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3329 #endif
3331 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3332 paused = false;
3333 audio_stop_codec_flush();
3335 track_changed = true;
3336 playlist_end = false;
3338 playing = true;
3340 ci.new_track = 0;
3341 ci.seek_time = 0;
3342 wps_offset = 0;
3344 sound_set_volume(global_settings.volume);
3345 track_widx = track_ridx = 0;
3347 /* Mark all entries null. */
3348 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3350 last_peek_offset = -1;
3352 /* Officially playing */
3353 queue_reply(&audio_queue, 1);
3355 audio_fill_file_buffer(true, false, offset);
3357 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3358 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3362 /* Invalidates all but currently playing track. */
3363 static void audio_invalidate_tracks(void)
3365 if (audio_have_tracks())
3367 last_peek_offset = 0;
3368 playlist_end = false;
3369 track_widx = track_ridx;
3371 /* Mark all other entries null (also buffered wrong metadata). */
3372 audio_clear_track_entries(true);
3374 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3376 audio_fill_file_buffer(false, true, 0);
3380 static void audio_new_playlist(void)
3382 /* Prepare to start a new fill from the beginning of the playlist */
3383 last_peek_offset = -1;
3384 if (audio_have_tracks())
3386 if (paused)
3387 skipped_during_pause = true;
3388 playlist_end = false;
3389 track_widx = track_ridx;
3390 audio_clear_track_entries(true);
3392 track_widx++;
3393 track_widx &= MAX_TRACK_MASK;
3395 /* Mark the current track as invalid to prevent skipping back to it */
3396 CUR_TI->taginfo_ready = false;
3399 /* Signal the codec to initiate a track change forward */
3400 new_playlist = true;
3401 ci.new_track = 1;
3403 /* Officially playing */
3404 queue_reply(&audio_queue, 1);
3406 audio_fill_file_buffer(false, true, 0);
3409 static void audio_initiate_track_change(long direction)
3411 playlist_end = false;
3412 ci.new_track += direction;
3413 wps_offset -= direction;
3414 if (paused)
3415 skipped_during_pause = true;
3418 static void audio_initiate_dir_change(long direction)
3420 playlist_end = false;
3421 dir_skip = true;
3422 ci.new_track = direction;
3423 if (paused)
3424 skipped_during_pause = true;
3428 * Layout audio buffer as follows - iram buffer depends on target:
3429 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3431 static void audio_reset_buffer(void)
3433 /* see audio_get_recording_buffer if this is modified */
3434 logf("audio_reset_buffer");
3436 /* If the setup of anything allocated before the file buffer is
3437 changed, do check the adjustments after the buffer_alloc call
3438 as it will likely be affected and need sliding over */
3440 /* Initially set up file buffer as all space available */
3441 malloc_buf = audiobuf + talk_get_bufsize();
3442 /* Align the malloc buf to line size. Especially important to cf
3443 targets that do line reads/writes. */
3444 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3445 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3446 filebuflen = audiobufend - filebuf;
3448 /* Allow for codec swap space at end of audio buffer */
3449 if (talk_voice_required())
3451 /* Layout of swap buffer:
3452 * #ifdef IRAM_STEAL (dedicated iram_buf):
3453 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3454 * #else:
3455 * audiobuf...|dram_buf|iram_buf|audiobufend
3457 #ifdef PLAYBACK_VOICE
3458 /* Check for an absolutely nasty situation which should never,
3459 ever happen - frankly should just panic */
3460 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3462 logf("buffer reset with voice swapped");
3464 /* line align length which line aligns the calculations below since
3465 all sizes are also at least line aligned - needed for memswap128 */
3466 filebuflen &= ~15;
3467 #ifdef IRAM_STEAL
3468 filebuflen -= CODEC_SIZE;
3469 #else
3470 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3471 #endif
3472 /* Allocate buffers for swapping voice <=> audio */
3473 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3474 and out of the way of buffer usage or else a call to audio_get_buffer
3475 and subsequent buffer use might trash the swap space. A plugin
3476 initializing IRAM after getting the full buffer would present similar
3477 problem. Options include: failing the request if the other buffer
3478 has been obtained already or never allowing use of the voice IRAM
3479 buffer within the audio buffer. Using buffer_alloc basically
3480 implements the second in a more convenient way. */
3481 dram_buf = filebuf + filebuflen;
3483 #ifdef IRAM_STEAL
3484 /* Allocate voice IRAM swap buffer once */
3485 if (iram_buf == NULL)
3487 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3488 /* buffer_alloc moves audiobuf; this is safe because only the end
3489 * has been touched so far in this function and the address of
3490 * filebuf + filebuflen is not changed */
3491 malloc_buf += CODEC_IRAM_SIZE;
3492 filebuf += CODEC_IRAM_SIZE;
3493 filebuflen -= CODEC_IRAM_SIZE;
3495 #else
3496 /* Allocate iram_buf after dram_buf */
3497 iram_buf = dram_buf + CODEC_SIZE;
3498 #endif /* IRAM_STEAL */
3499 #endif /* PLAYBACK_VOICE */
3501 else
3503 #ifdef PLAYBACK_VOICE
3504 /* No swap buffers needed */
3505 iram_buf = NULL;
3506 dram_buf = NULL;
3507 #endif
3510 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3511 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3513 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3514 will already be line aligned */
3515 filebuflen &= ~3;
3517 /* Set the high watermark as 75% full...or 25% empty :) */
3518 #if MEM > 8
3519 high_watermark = 3*filebuflen / 4;
3520 #endif
3522 /* Clear any references to the file buffer */
3523 buffer_state = BUFFER_STATE_INITIALIZED;
3525 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3526 /* Make sure everything adds up - yes, some info is a bit redundant but
3527 aids viewing and the sumation of certain variables should add up to
3528 the location of others. */
3530 size_t pcmbufsize;
3531 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3532 logf("mabuf: %08X", (unsigned)malloc_buf);
3533 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3534 logf("fbuf: %08X", (unsigned)filebuf);
3535 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3536 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3537 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3538 logf("pcmb: %08X", (unsigned)pcmbuf);
3539 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3540 if (dram_buf)
3542 logf("dramb: %08X", (unsigned)dram_buf);
3543 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3545 if (iram_buf)
3547 logf("iramb: %08X", (unsigned)iram_buf);
3548 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3551 #endif
3554 #if MEM > 8
3555 /* we dont want this rebuffering on targets with little ram
3556 because the disk may never spin down */
3557 static bool ata_fillbuffer_callback(void)
3559 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3560 return true;
3562 #endif
3564 static void audio_thread(void)
3566 struct queue_event ev;
3568 pcm_postinit();
3570 #ifdef PLAYBACK_VOICE
3571 /* Unlock semaphore that init stage locks before creating this thread */
3572 semaphore_release(&sem_codecthread);
3574 /* Buffers must be set up by now - should panic - really */
3575 if (buffer_state != BUFFER_STATE_INITIALIZED)
3577 logf("audio_thread start: no buffer");
3580 /* Have to wait for voice to load up or else the codec swap will be
3581 invalid when an audio codec is loaded */
3582 wait_for_voice_swap_in();
3583 #endif
3585 while (1)
3587 if (filling)
3589 queue_wait_w_tmo(&audio_queue, &ev, 0);
3590 if (ev.id == SYS_TIMEOUT)
3591 ev.id = Q_AUDIO_FILL_BUFFER;
3593 else
3595 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3596 #if MEM > 8
3597 if (playing && (ev.id == SYS_TIMEOUT) &&
3598 (bufused() < high_watermark))
3599 register_ata_idle_func(ata_fillbuffer_callback);
3600 #endif
3603 switch (ev.id) {
3604 #if MEM > 8
3605 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3606 /* only fill if the disk is still spining */
3607 #ifndef SIMULATOR
3608 if (!ata_disk_is_active())
3609 break;
3610 #endif
3611 #endif /* MEM > 8 */
3612 /* else fall through to Q_AUDIO_FILL_BUFFER */
3613 case Q_AUDIO_FILL_BUFFER:
3614 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3615 if (!filling)
3616 if (!playing || playlist_end || ci.stop_codec)
3617 break;
3618 audio_fill_file_buffer(false, false, 0);
3619 break;
3621 case Q_AUDIO_PLAY:
3622 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3623 if (playing && ev.data <= 0)
3624 audio_new_playlist();
3625 else
3627 audio_stop_playback();
3628 audio_play_start((size_t)ev.data);
3630 break;
3632 case Q_AUDIO_STOP:
3633 LOGFQUEUE("audio < Q_AUDIO_STOP");
3634 if (playing)
3635 audio_stop_playback();
3636 if (ev.data != 0)
3637 queue_clear(&audio_queue);
3638 break;
3640 case Q_AUDIO_PAUSE:
3641 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3642 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3643 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3644 skipped_during_pause = false;
3645 if (!playing)
3646 break;
3647 pcmbuf_pause((bool)ev.data);
3648 paused = (bool)ev.data;
3649 break;
3651 case Q_AUDIO_SKIP:
3652 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3653 audio_initiate_track_change((long)ev.data);
3654 break;
3656 case Q_AUDIO_PRE_FF_REWIND:
3657 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3658 if (!playing)
3659 break;
3660 pcmbuf_pause(true);
3661 break;
3663 case Q_AUDIO_FF_REWIND:
3664 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3665 if (!playing)
3666 break;
3667 ci.seek_time = (long)ev.data+1;
3668 break;
3670 #if 0
3671 case Q_AUDIO_REBUFFER_SEEK:
3672 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3673 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3674 break;
3675 #endif
3677 case Q_AUDIO_CHECK_NEW_TRACK:
3678 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3679 queue_reply(&audio_queue, audio_check_new_track());
3680 break;
3682 case Q_AUDIO_DIR_SKIP:
3683 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3684 playlist_end = false;
3685 audio_initiate_dir_change(ev.data);
3686 break;
3688 case Q_AUDIO_FLUSH:
3689 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3690 audio_invalidate_tracks();
3691 break;
3693 case Q_AUDIO_TRACK_CHANGED:
3694 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3695 if (track_changed_callback)
3696 track_changed_callback(&curtrack_id3);
3697 track_changed = true;
3698 playlist_update_resume_info(audio_current_track());
3699 break;
3701 #ifndef SIMULATOR
3702 case SYS_USB_CONNECTED:
3703 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3704 if (playing)
3705 audio_stop_playback();
3706 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3707 usb_wait_for_disconnect(&audio_queue);
3708 break;
3709 #endif
3711 case SYS_TIMEOUT:
3712 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3713 break;
3715 default:
3716 //LOGFQUEUE("audio < default");
3717 break;
3718 } /* end switch */
3719 } /* end while */
3722 #ifdef ROCKBOX_HAS_LOGF
3723 static void audio_test_track_changed_event(struct mp3entry *id3)
3725 (void)id3;
3727 logf("tce:%s", id3->path);
3729 #endif
3731 /* Initialize the audio system - called from init() in main.c.
3732 * Last function because of all the references to internal symbols
3734 void audio_init(void)
3736 #ifdef PLAYBACK_VOICE
3737 static bool voicetagtrue = true;
3738 static struct mp3entry id3_voice;
3739 struct thread_entry *voice_thread_p = NULL;
3740 #endif
3741 struct thread_entry *audio_thread_p;
3743 /* Can never do this twice */
3744 if (audio_is_initialized)
3746 logf("audio: already initialized");
3747 return;
3750 logf("audio: initializing");
3752 /* Initialize queues before giving control elsewhere in case it likes
3753 to send messages. Thread creation will be delayed however so nothing
3754 starts running until ready if something yields such as talk_init. */
3755 #ifdef PLAYBACK_VOICE
3756 /* Take ownership of lock to prevent playback of anything before audio
3757 hardware is initialized - audio thread unlocks it after final init
3758 stage */
3759 semaphore_init(&sem_codecthread, 1, 0);
3760 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3761 #endif
3762 queue_init(&audio_queue, true);
3763 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3764 queue_init(&codec_queue, true);
3765 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3767 pcm_init();
3769 #ifdef ROCKBOX_HAS_LOGF
3770 audio_set_track_changed_event(audio_test_track_changed_event);
3771 #endif
3773 /* Initialize codec api. */
3774 ci.read_filebuf = codec_filebuf_callback;
3775 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3776 ci.get_codec_memory = codec_get_memory_callback;
3777 ci.request_buffer = codec_request_buffer_callback;
3778 ci.advance_buffer = codec_advance_buffer_callback;
3779 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3780 ci.request_next_track = codec_request_next_track_callback;
3781 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3782 ci.seek_buffer = codec_seek_buffer_callback;
3783 ci.seek_complete = codec_seek_complete_callback;
3784 ci.set_elapsed = codec_set_elapsed_callback;
3785 ci.set_offset = codec_set_offset_callback;
3786 ci.configure = codec_configure_callback;
3787 ci.discard_codec = codec_discard_codec_callback;
3789 /* Initialize voice codec api. */
3790 #ifdef PLAYBACK_VOICE
3791 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3792 memset(&id3_voice, 0, sizeof(id3_voice));
3793 ci_voice.read_filebuf = voice_filebuf_callback;
3794 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3795 ci_voice.get_codec_memory = voice_get_memory_callback;
3796 ci_voice.request_buffer = voice_request_buffer_callback;
3797 ci_voice.advance_buffer = voice_advance_buffer_callback;
3798 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3799 ci_voice.request_next_track = voice_request_next_track_callback;
3800 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3801 ci_voice.seek_buffer = voice_seek_buffer_callback;
3802 ci_voice.seek_complete = voice_do_nothing;
3803 ci_voice.set_elapsed = voice_set_elapsed_callback;
3804 ci_voice.set_offset = voice_set_offset_callback;
3805 ci_voice.configure = voice_configure_callback;
3806 ci_voice.discard_codec = voice_do_nothing;
3807 ci_voice.taginfo_ready = &voicetagtrue;
3808 ci_voice.id3 = &id3_voice;
3809 id3_voice.frequency = 11200;
3810 id3_voice.length = 1000000L;
3811 #endif
3813 /* initialize the buffer */
3814 filebuf = audiobuf;
3816 /* audio_reset_buffer must to know the size of voice buffer so init
3817 talk first */
3818 talk_init();
3820 codec_thread_p = create_thread(
3821 codec_thread, codec_stack, sizeof(codec_stack),
3822 CREATE_THREAD_FROZEN,
3823 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3824 IF_COP(, CPU));
3826 audio_thread_p = create_thread(audio_thread, audio_stack,
3827 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3828 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3829 IF_COP(, CPU));
3831 #ifdef PLAYBACK_VOICE
3832 /* TODO: Change this around when various speech codecs can be used */
3833 if (talk_voice_required())
3835 logf("Starting voice codec");
3836 queue_init(&voice_queue, true);
3837 voice_thread_p = create_thread(voice_thread, voice_stack,
3838 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3839 voice_thread_name
3840 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3842 #endif
3844 /* Set crossfade setting for next buffer init which should be about... */
3845 pcmbuf_crossfade_enable(global_settings.crossfade);
3847 /* ...now! Set up the buffers */
3848 audio_reset_buffer();
3850 buffering_init(filebuf, filebuflen);
3852 /* Probably safe to say */
3853 audio_is_initialized = true;
3855 sound_settings_apply();
3856 #ifdef HAVE_WM8758
3857 eq_hw_enable(global_settings.eq_hw_enabled);
3858 #endif
3859 #ifndef HAVE_FLASH_STORAGE
3860 audio_set_buffer_margin(global_settings.buffer_margin);
3861 #endif
3863 /* it's safe to let the threads run now */
3864 thread_thaw(codec_thread_p);
3865 #ifdef PLAYBACK_VOICE
3866 if (voice_thread_p)
3867 thread_thaw(voice_thread_p);
3868 #endif
3869 thread_thaw(audio_thread_p);
3870 } /* audio_init */