Enable and correct audio_invalidate_tracks to make playlist reordering work
[Rockbox.git] / apps / playback.c
blobe7416773ca3a1696b02c8b07ecb02c3c000ad044
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 /* Buffering thread */
296 void buffering_thread(void);
297 static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
298 static const char buffering_thread_name[] = "buffering";
299 struct thread_entry *buffering_thread_p;
301 /* Voice thread */
302 #ifdef PLAYBACK_VOICE
304 extern struct codec_api ci_voice;
306 static struct thread_entry *voice_thread_p = NULL;
307 static struct event_queue voice_queue NOCACHEBSS_ATTR;
308 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
309 IBSS_ATTR_VOICE_STACK;
310 static const char voice_thread_name[] = "voice codec";
312 /* Voice codec swapping control */
313 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
315 #ifdef SIMULATOR
316 /* IRAM codec swap buffer for sim*/
317 static unsigned char sim_iram[CODEC_IRAM_SIZE];
318 #undef CODEC_IRAM_ORIGIN
319 #define CODEC_IRAM_ORIGIN sim_iram
320 #endif
322 /* iram_buf and dram_buf are either both NULL or both non-NULL */
323 /* Pointer to IRAM buffer for codec swapping */
324 static unsigned char *iram_buf = NULL;
325 /* Pointer to DRAM buffer for codec swapping */
326 static unsigned char *dram_buf = NULL;
327 /* Parity of swap_codec calls - needed because one codec swapping itself in
328 automatically swaps in the other and the swap when unlocking should not
329 happen if the parity is even.
331 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
332 /* Locking to control which codec (normal/voice) is running */
333 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
334 static struct event event_codecthread NOCACHEBSS_ATTR;
336 /* Voice state */
337 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
338 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
339 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
340 static unsigned char *voicebuf = NULL;
341 static size_t voice_remaining = 0;
343 #ifdef IRAM_STEAL
344 /* Voice IRAM has been stolen for other use */
345 static bool voice_iram_stolen = false;
346 #endif
348 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
350 struct voice_info {
351 void (*callback)(unsigned char **start, size_t* size);
352 size_t size;
353 unsigned char *buf;
355 static void voice_thread(void);
356 static void voice_stop(void);
358 #endif /* PLAYBACK_VOICE */
361 /* --- Helper functions --- */
363 struct mp3entry *bufgetid3(int handle_id)
365 if (handle_id < 0)
366 return NULL;
368 struct mp3entry *id3;
369 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
371 if (ret < 0 || ret != sizeof(struct mp3entry))
372 return NULL;
374 return id3;
377 void *bufgetcodec(struct track_info *track)
379 void *ptr;
380 ssize_t ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
382 if (ret == -2) {
383 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
384 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
387 while (ret == -2) {
388 sleep(1);
389 ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
392 if (ret < 0)
393 return NULL;
394 else
395 return ptr;
398 void clear_track_info(struct track_info *track)
400 if (!track)
401 return;
403 if (track->codec_hid > 0) {
404 bufclose(track->codec_hid);
407 if (track->id3_hid > 0) {
408 bufclose(track->id3_hid);
411 if (track->audio_hid > 0) {
412 bufclose(track->audio_hid);
415 memset(track, 0, sizeof(struct track_info));
418 /* --- External interfaces --- */
420 void mp3_play_data(const unsigned char* start, int size,
421 void (*get_more)(unsigned char** start, size_t* size))
423 #ifdef PLAYBACK_VOICE
424 static struct voice_info voice_clip;
425 voice_clip.callback = get_more;
426 voice_clip.buf = (unsigned char*)start;
427 voice_clip.size = size;
428 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
429 queue_post(&voice_queue, Q_VOICE_STOP, 0);
430 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
431 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
432 voice_thread_start = true;
433 trigger_cpu_boost();
434 #else
435 (void) start;
436 (void) size;
437 (void) get_more;
438 #endif
441 void mp3_play_stop(void)
443 #ifdef PLAYBACK_VOICE
444 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
445 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
446 queue_post(&voice_queue, Q_VOICE_STOP, 1);
447 #endif
450 void mp3_play_pause(bool play)
452 /* a dummy */
453 (void)play;
456 bool mp3_is_playing(void)
458 #ifdef PLAYBACK_VOICE
459 return voice_is_playing;
460 #else
461 return false;
462 #endif
465 /* If voice could be swapped out - wait for it to return
466 * Used by buffer claming functions.
468 static void wait_for_voice_swap_in(void)
470 #ifdef PLAYBACK_VOICE
471 if (NULL == iram_buf)
472 return;
474 event_wait(&event_codecthread, STATE_NONSIGNALED);
475 #endif /* PLAYBACK_VOICE */
478 /* This sends a stop message and the audio thread will dump all it's
479 subsequenct messages */
480 static void audio_hard_stop(void)
482 /* Stop playback */
483 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
484 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
487 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
489 unsigned char *buf, *end;
491 if (audio_is_initialized)
493 audio_hard_stop();
494 wait_for_voice_swap_in();
495 #ifdef PLAYBACK_VOICE
496 voice_stop();
497 #endif
499 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
501 if (buffer_size == NULL)
503 /* Special case for talk_init to use since it already knows it's
504 trashed */
505 buffer_state = BUFFER_STATE_TRASHED;
506 return NULL;
509 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
510 || !talk_voice_required())
512 logf("get buffer: talk, audio");
513 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
514 the talk buffer is not needed because voice isn't being used, or
515 could be BUFFER_STATE_TRASHED already. If state is
516 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
517 without the caller knowing what's going on. Changing certain settings
518 may move it to a worse condition but the memory in use by something
519 else will remain undisturbed.
521 if (buffer_state != BUFFER_STATE_TRASHED)
523 talk_buffer_steal();
524 buffer_state = BUFFER_STATE_TRASHED;
527 buf = audiobuf;
528 end = audiobufend;
530 else
532 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
533 still BUFFER_STATE_INITIALIZED */
534 /* Skip talk buffer and move pcm buffer to end to maximize available
535 contiguous memory - no audio running means voice will not need the
536 swap space */
537 logf("get buffer: audio");
538 buf = audiobuf + talk_get_bufsize();
539 end = audiobufend - pcmbuf_init(audiobufend);
540 buffer_state = BUFFER_STATE_VOICED_ONLY;
543 *buffer_size = end - buf;
545 return buf;
548 #ifdef IRAM_STEAL
549 void audio_iram_steal(void)
551 /* We need to stop audio playback in order to use codec IRAM */
552 audio_hard_stop();
554 #ifdef PLAYBACK_VOICE
555 if (NULL != iram_buf)
557 /* Can't already be stolen */
558 if (voice_iram_stolen)
559 return;
561 /* Must wait for voice to be current again if it is swapped which
562 would cause the caller's buffer to get clobbered when voice locks
563 and runs - we'll wait for it to lock and yield again then make sure
564 the ride has come to a complete stop */
565 wait_for_voice_swap_in();
566 voice_stop();
568 /* Save voice IRAM but just memcpy - safe to do here since voice
569 is current and no audio codec is loaded */
570 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
571 voice_iram_stolen = true;
573 else
575 /* Nothing much to do if no voice */
576 voice_iram_stolen = false;
578 #endif
580 #endif /* IRAM_STEAL */
582 #ifdef HAVE_RECORDING
583 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
585 /* Don't allow overwrite of voice swap area or we'll trash the
586 swapped-out voice codec but can use whole thing if none */
587 unsigned char *end;
589 /* Stop audio and voice. Wait for voice to swap in and be clear
590 of pending events to ensure trouble-free operation of encoders */
591 audio_hard_stop();
592 wait_for_voice_swap_in();
593 #ifdef PLAYBACK_VOICE
594 voice_stop();
595 #endif
596 talk_buffer_steal();
598 #ifdef PLAYBACK_VOICE
599 /* If no dram_buf, swap space not used and recording gets more
600 memory. Codec swap areas will remain unaffected by the next init
601 since they're allocated at the end of the buffer and their sizes
602 don't change between calls */
603 end = dram_buf;
604 if (NULL == end)
605 #endif /* PLAYBACK_VOICE */
606 end = audiobufend;
608 buffer_state = BUFFER_STATE_TRASHED;
610 *buffer_size = end - audiobuf;
612 return (unsigned char *)audiobuf;
615 bool audio_load_encoder(int afmt)
617 #ifndef SIMULATOR
618 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
619 if (!enc_fn)
620 return false;
622 audio_remove_encoder();
623 ci.enc_codec_loaded = 0; /* clear any previous error condition */
625 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
626 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
628 while (ci.enc_codec_loaded == 0)
629 yield();
631 logf("codec loaded: %d", ci.enc_codec_loaded);
633 return ci.enc_codec_loaded > 0;
634 #else
635 (void)afmt;
636 return true;
637 #endif
638 } /* audio_load_encoder */
640 void audio_remove_encoder(void)
642 #ifndef SIMULATOR
643 /* force encoder codec unload (if currently loaded) */
644 if (ci.enc_codec_loaded <= 0)
645 return;
647 ci.stop_encoder = true;
648 while (ci.enc_codec_loaded > 0)
649 yield();
650 #endif
651 } /* audio_remove_encoder */
653 #endif /* HAVE_RECORDING */
655 struct mp3entry* audio_current_track(void)
657 const char *filename;
658 const char *p;
659 static struct mp3entry temp_id3;
660 int cur_idx;
661 int offset = ci.new_track + wps_offset;
663 cur_idx = track_ridx + offset;
664 cur_idx &= MAX_TRACK_MASK;
666 if (cur_idx == track_ridx && *curtrack_id3.path)
667 return &curtrack_id3;
668 else if (tracks[cur_idx].id3_hid > 0)
669 return bufgetid3(tracks[cur_idx].id3_hid);
671 memset(&temp_id3, 0, sizeof(struct mp3entry));
673 filename = playlist_peek(0);
674 if (!filename)
675 filename = "No file!";
677 #ifdef HAVE_TC_RAMCACHE
678 if (tagcache_fill_tags(&temp_id3, filename))
679 return &temp_id3;
680 #endif
682 p = strrchr(filename, '/');
683 if (!p)
684 p = filename;
685 else
686 p++;
688 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
689 temp_id3.title = &temp_id3.path[0];
691 return &temp_id3;
694 struct mp3entry* audio_next_track(void)
696 int next_idx = track_ridx;
698 if (!audio_have_tracks())
699 return NULL;
701 next_idx++;
702 next_idx &= MAX_TRACK_MASK;
704 if (tracks[next_idx].id3_hid <= 0)
705 return NULL;
707 return &nexttrack_id3;
710 bool audio_has_changed_track(void)
712 if (track_changed)
714 track_changed = false;
715 return true;
718 return false;
721 void audio_play(long offset)
723 logf("audio_play");
725 #ifdef PLAYBACK_VOICE
726 /* Truncate any existing voice output so we don't have spelling
727 * etc. over the first part of the played track */
728 talk_force_shutup();
729 #endif
731 /* Start playback */
732 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
733 /* Don't return until playback has actually started */
734 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
737 void audio_stop(void)
739 /* Stop playback */
740 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
741 /* Don't return until playback has actually stopped */
742 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
745 void audio_pause(void)
747 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
748 /* Don't return until playback has actually paused */
749 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
752 void audio_resume(void)
754 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
755 /* Don't return until playback has actually resumed */
756 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
759 void audio_next(void)
761 if (playlist_check(ci.new_track + wps_offset + 1))
763 if (global_settings.beep)
764 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
766 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
767 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
768 /* Update wps while our message travels inside deep playback queues. */
769 wps_offset++;
770 track_changed = true;
772 else
774 /* No more tracks. */
775 if (global_settings.beep)
776 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
780 void audio_prev(void)
782 if (playlist_check(ci.new_track + wps_offset - 1))
784 if (global_settings.beep)
785 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
787 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
788 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
789 /* Update wps while our message travels inside deep playback queues. */
790 wps_offset--;
791 track_changed = true;
793 else
795 /* No more tracks. */
796 if (global_settings.beep)
797 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
801 void audio_next_dir(void)
803 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
804 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
807 void audio_prev_dir(void)
809 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
810 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
813 void audio_pre_ff_rewind(void)
815 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
816 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
819 void audio_ff_rewind(long newpos)
821 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
822 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
825 void audio_flush_and_reload_tracks(void)
827 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
828 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
831 void audio_error_clear(void)
833 #ifdef AUDIO_HAVE_RECORDING
834 pcm_rec_error_clear();
835 #endif
838 int audio_status(void)
840 int ret = 0;
842 if (playing)
843 ret |= AUDIO_STATUS_PLAY;
845 if (paused)
846 ret |= AUDIO_STATUS_PAUSE;
848 #ifdef HAVE_RECORDING
849 /* Do this here for constitency with mpeg.c version */
850 ret |= pcm_rec_status();
851 #endif
853 return ret;
856 int audio_get_file_pos(void)
858 return 0;
861 #ifndef HAVE_FLASH_STORAGE
862 void audio_set_buffer_margin(int setting)
864 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
865 buffer_margin = lookup[setting];
866 logf("buffer margin: %d", buffer_margin);
867 set_filebuf_watermark(buffer_margin);
869 #endif
871 /* Take nescessary steps to enable or disable the crossfade setting */
872 void audio_set_crossfade(int enable)
874 size_t offset;
875 bool was_playing;
876 size_t size;
878 /* Tell it the next setting to use */
879 pcmbuf_crossfade_enable(enable);
881 /* Return if size hasn't changed or this is too early to determine
882 which in the second case there's no way we could be playing
883 anything at all */
884 if (pcmbuf_is_same_size())
886 /* This function is a copout and just syncs some variables -
887 to be removed at a later date */
888 pcmbuf_crossfade_enable_finished();
889 return;
892 offset = 0;
893 was_playing = playing;
895 /* Playback has to be stopped before changing the buffer size */
896 if (was_playing)
898 /* Store the track resume position */
899 offset = curtrack_id3.offset;
900 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
903 /* Blast it - audio buffer will have to be setup again next time
904 something plays */
905 audio_get_buffer(true, &size);
907 /* Restart playback if audio was running previously */
908 if (was_playing)
909 audio_play(offset);
912 /* --- Routines called from multiple threads --- */
913 static void set_current_codec(int codec_idx)
915 current_codec = codec_idx;
916 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
919 #ifdef PLAYBACK_VOICE
920 static void swap_codec(void)
922 int my_codec;
924 /* Swap nothing if no swap buffers exist */
925 if (dram_buf == NULL)
927 logf("swap: no swap buffers");
928 return;
931 my_codec = current_codec;
933 logf("swapping out codec: %d", my_codec);
935 /* Invert this when a codec thread enters and leaves */
936 swap_codec_parity = !swap_codec_parity;
938 /* If this is true, an odd number of calls has occurred and there's
939 no codec thread waiting to swap us out when it locks and runs. This
940 occurs when playback is stopped or when just starting playback and
941 the audio thread is loading a codec; parities should always be even
942 on entry when a thread calls this during playback */
943 if (swap_codec_parity)
945 /* Save our current IRAM and DRAM */
946 #ifdef IRAM_STEAL
947 if (voice_iram_stolen)
949 logf("swap: iram restore");
950 voice_iram_stolen = false;
951 /* Don't swap trashed data into buffer as the voice IRAM will
952 already be swapped out - should _always_ be the case if
953 voice_iram_stolen is true since the voice has been swapped
954 in beforehand */
955 if (my_codec == CODEC_IDX_VOICE)
957 logf("voice iram already swapped");
958 goto skip_iram_swap;
961 #endif
963 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
965 #ifdef IRAM_STEAL
966 skip_iram_swap:
967 #endif
969 memswap128(dram_buf, codecbuf, CODEC_SIZE);
970 /* No cache invalidation needed; it will be done in codec_load_ram
971 or we won't be here otherwise */
974 /* Release my semaphore */
975 semaphore_release(&sem_codecthread);
976 logf("unlocked: %d", my_codec);
978 /* Wait for other codec */
979 event_wait(&event_codecthread,
980 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
982 /* Wait for other codec to unlock */
983 logf("waiting for lock: %d", my_codec);
984 semaphore_wait(&sem_codecthread);
986 /* Take control */
987 set_current_codec(my_codec);
988 event_set_state(&event_codecthread,
989 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
991 /* Reload our IRAM and DRAM */
992 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
993 memswap128(dram_buf, codecbuf, CODEC_SIZE);
994 invalidate_icache();
996 /* Flip parity again */
997 swap_codec_parity = !swap_codec_parity;
999 logf("resuming codec: %d", my_codec);
1002 /* This function is meant to be used by the buffer stealing functions to
1003 ensure the codec is no longer active and so voice will be swapped-in
1004 before it is called */
1005 static void voice_stop(void)
1007 /* Must have a voice codec loaded or we'll hang forever here */
1008 if (!voice_codec_loaded)
1009 return;
1011 talk_force_shutup();
1013 /* Loop until voice empties it's queue, stops and picks up on the new
1014 track; the voice thread must be stopped and waiting for messages
1015 outside the codec */
1016 while (voice_is_playing || !queue_empty(&voice_queue) ||
1017 ci_voice.new_track)
1018 yield();
1020 if (!playing)
1021 pcmbuf_play_stop();
1022 } /* voice_stop */
1024 /* Is voice still speaking */
1025 /* Unfortunately only reliable when music is not also playing. */
1026 static bool is_voice_speaking(void)
1028 return is_voice_queued()
1029 || voice_is_playing
1030 || (!playing && pcm_is_playing());
1033 #endif /* PLAYBACK_VOICE */
1035 /* Wait for voice to finish speaking. */
1036 /* Also only reliable when music is not also playing. */
1037 void voice_wait(void)
1039 #ifdef PLAYBACK_VOICE
1040 while (is_voice_speaking())
1041 sleep(HZ/10);
1042 #endif
1045 static void set_filebuf_watermark(int seconds)
1047 size_t bytes;
1049 if (!filebuf)
1050 return; /* Audio buffers not yet set up */
1052 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), conf_watermark);
1053 bytes = MIN(bytes, filebuflen / 2);
1054 conf_watermark = bytes;
1057 const char * get_codec_filename(int cod_spec)
1059 const char *fname;
1061 #ifdef HAVE_RECORDING
1062 /* Can choose decoder or encoder if one available */
1063 int type = cod_spec & CODEC_TYPE_MASK;
1064 int afmt = cod_spec & CODEC_AFMT_MASK;
1066 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1067 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1069 fname = (type == CODEC_TYPE_ENCODER) ?
1070 audio_formats[afmt].codec_enc_root_fn :
1071 audio_formats[afmt].codec_root_fn;
1073 logf("%s: %d - %s",
1074 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1075 afmt, fname ? fname : "<unknown>");
1076 #else /* !HAVE_RECORDING */
1077 /* Always decoder */
1078 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1079 cod_spec = AFMT_UNKNOWN;
1080 fname = audio_formats[cod_spec].codec_root_fn;
1081 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1082 #endif /* HAVE_RECORDING */
1084 return fname;
1085 } /* get_codec_filename */
1088 /* --- Voice thread --- */
1090 #ifdef PLAYBACK_VOICE
1092 static bool voice_pcmbuf_insert_callback(
1093 const void *ch1, const void *ch2, int count)
1095 const char *src[2] = { ch1, ch2 };
1097 while (count > 0)
1099 int out_count = dsp_output_count(count);
1100 int inp_count;
1101 char *dest;
1103 while ((dest = pcmbuf_request_voice_buffer(
1104 &out_count, playing)) == NULL)
1106 if (playing && audio_codec_loaded)
1107 swap_codec();
1108 else
1109 yield();
1112 /* Get the real input_size for output_size bytes, guarding
1113 * against resampling buffer overflows. */
1114 inp_count = dsp_input_count(out_count);
1116 if (inp_count <= 0)
1117 return true;
1119 /* Input size has grown, no error, just don't write more than length */
1120 if (inp_count > count)
1121 inp_count = count;
1123 out_count = dsp_process(dest, src, inp_count);
1125 if (out_count <= 0)
1126 return true;
1128 if (playing)
1130 pcmbuf_mix_voice(out_count);
1131 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1132 audio_codec_loaded)
1133 swap_codec();
1135 else
1136 pcmbuf_write_complete(out_count);
1138 count -= inp_count;
1141 return true;
1142 } /* voice_pcmbuf_insert_callback */
1144 static void* voice_get_memory_callback(size_t *size)
1146 /* Voice should have no use for this. If it did, we'd have to
1147 swap the malloc buffer as well. */
1148 *size = 0;
1149 return NULL;
1152 static void voice_set_elapsed_callback(unsigned int value)
1154 (void)value;
1157 static void voice_set_offset_callback(size_t value)
1159 (void)value;
1162 static void voice_configure_callback(int setting, intptr_t value)
1164 if (!dsp_configure(setting, value))
1166 logf("Illegal key:%d", setting);
1170 static size_t voice_filebuf_callback(void *ptr, size_t size)
1172 (void)ptr;
1173 (void)size;
1175 return 0;
1178 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1179 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1181 if (aborting && !playing)
1183 /* Aborting: Slight hack - flush PCM buffer if
1184 only being used for voice */
1185 pcmbuf_play_stop();
1188 if (voice_is_playing)
1190 /* Clear the current buffer */
1191 voice_is_playing = false;
1192 voice_getmore = NULL;
1193 voice_remaining = 0;
1194 voicebuf = NULL;
1196 /* Cancel any automatic boost if no more clips requested. */
1197 if (!playing || !voice_thread_start)
1198 sleep(0);
1200 /* Force the codec to think it's changing tracks */
1201 ci_voice.new_track = 1;
1203 *realsize = 0;
1204 return true; /* Yes, change tracks */
1207 return false;
1210 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1212 struct queue_event ev;
1214 if (ci_voice.new_track)
1216 *realsize = 0;
1217 return NULL;
1220 while (1)
1222 if (voice_is_playing || playing)
1224 queue_wait_w_tmo(&voice_queue, &ev, 0);
1225 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1226 ev.id = Q_AUDIO_PLAY;
1228 else
1230 queue_wait(&voice_queue, &ev);
1233 switch (ev.id) {
1234 case Q_AUDIO_PLAY:
1235 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1236 if (playing)
1238 if (audio_codec_loaded)
1239 swap_codec();
1240 yield();
1242 break;
1244 #ifdef AUDIO_HAVE_RECORDING
1245 case Q_ENCODER_RECORD:
1246 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1247 swap_codec();
1248 break;
1249 #endif
1251 case Q_VOICE_STOP:
1252 LOGFQUEUE("voice < Q_VOICE_STOP");
1253 if (voice_on_voice_stop(ev.data, realsize))
1254 return NULL;
1255 break;
1257 case SYS_USB_CONNECTED:
1259 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1260 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1261 /* Voice is obviously current so let us swap ourselves away if
1262 playing so audio may stop itself - audio_codec_loaded can
1263 only be true in this case if we're here even if the codec
1264 is only about to load */
1265 if (audio_codec_loaded)
1266 swap_codec();
1267 /* Playback should be finished by now - ack and wait */
1268 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1269 usb_wait_for_disconnect(&voice_queue);
1270 if (change_tracks)
1271 return NULL;
1272 break;
1275 case Q_VOICE_PLAY:
1276 LOGFQUEUE("voice < Q_VOICE_PLAY");
1277 if (!voice_is_playing)
1279 /* Set up new voice data */
1280 struct voice_info *voice_data;
1281 #ifdef IRAM_STEAL
1282 if (voice_iram_stolen)
1284 /* Voice is the first to run again and is currently
1285 loaded */
1286 logf("voice: iram restore");
1287 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1288 voice_iram_stolen = false;
1290 #endif
1291 /* Must reset the buffer before any playback begins if
1292 needed */
1293 if (buffer_state == BUFFER_STATE_TRASHED)
1294 audio_reset_buffer();
1296 voice_is_playing = true;
1297 trigger_cpu_boost();
1298 voice_data = (struct voice_info *)ev.data;
1299 voice_remaining = voice_data->size;
1300 voicebuf = voice_data->buf;
1301 voice_getmore = voice_data->callback;
1303 goto voice_play_clip; /* To exit both switch and while */
1305 case SYS_TIMEOUT:
1306 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1307 goto voice_play_clip;
1309 default:
1310 LOGFQUEUE("voice < default");
1314 voice_play_clip:
1316 if (voice_remaining == 0 || voicebuf == NULL)
1318 if (voice_getmore)
1319 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1321 /* If this clip is done */
1322 if (voice_remaining == 0)
1324 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1325 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1326 /* Force pcm playback. */
1327 if (!pcm_is_playing())
1328 pcmbuf_play_start();
1332 *realsize = MIN(voice_remaining, reqsize);
1334 if (*realsize == 0)
1335 return NULL;
1337 return voicebuf;
1338 } /* voice_request_buffer_callback */
1340 static void voice_advance_buffer_callback(size_t amount)
1342 amount = MIN(amount, voice_remaining);
1343 voicebuf += amount;
1344 voice_remaining -= amount;
1347 static void voice_advance_buffer_loc_callback(void *ptr)
1349 size_t amount = (size_t)ptr - (size_t)voicebuf;
1351 voice_advance_buffer_callback(amount);
1354 static off_t voice_mp3_get_filepos_callback(int newtime)
1356 (void)newtime;
1358 return 0;
1361 static void voice_do_nothing(void)
1363 return;
1366 static bool voice_seek_buffer_callback(size_t newpos)
1368 (void)newpos;
1370 return false;
1373 static bool voice_request_next_track_callback(void)
1375 ci_voice.new_track = 0;
1376 return true;
1379 static void voice_thread(void)
1381 logf("Loading voice codec");
1382 voice_codec_loaded = true;
1383 semaphore_wait(&sem_codecthread);
1384 event_set_state(&event_codecthread, false);
1385 set_current_codec(CODEC_IDX_VOICE);
1386 dsp_configure(DSP_RESET, 0);
1387 voice_remaining = 0;
1388 voice_getmore = NULL;
1390 /* FIXME: If we being starting the voice thread without reboot, the
1391 voice_queue could be full of old stuff and we must flush it. */
1392 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1394 logf("Voice codec finished");
1395 voice_codec_loaded = false;
1396 voice_thread_p = NULL;
1397 semaphore_release(&sem_codecthread);
1398 } /* voice_thread */
1400 #endif /* PLAYBACK_VOICE */
1402 /* --- Codec thread --- */
1403 static bool codec_pcmbuf_insert_callback(
1404 const void *ch1, const void *ch2, int count)
1406 const char *src[2] = { ch1, ch2 };
1408 while (count > 0)
1410 int out_count = dsp_output_count(count);
1411 int inp_count;
1412 char *dest;
1414 /* Prevent audio from a previous track from playing */
1415 if (ci.new_track || ci.stop_codec)
1416 return true;
1418 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1420 sleep(1);
1421 if (ci.seek_time || ci.new_track || ci.stop_codec)
1422 return true;
1425 /* Get the real input_size for output_size bytes, guarding
1426 * against resampling buffer overflows. */
1427 inp_count = dsp_input_count(out_count);
1429 if (inp_count <= 0)
1430 return true;
1432 /* Input size has grown, no error, just don't write more than length */
1433 if (inp_count > count)
1434 inp_count = count;
1436 out_count = dsp_process(dest, src, inp_count);
1438 if (out_count <= 0)
1439 return true;
1441 pcmbuf_write_complete(out_count);
1443 #ifdef PLAYBACK_VOICE
1444 if ((voice_is_playing || voice_thread_start)
1445 && pcm_is_playing() && voice_codec_loaded &&
1446 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1448 voice_thread_start = false;
1449 swap_codec();
1451 #endif
1453 count -= inp_count;
1456 return true;
1457 } /* codec_pcmbuf_insert_callback */
1459 static void* codec_get_memory_callback(size_t *size)
1461 *size = MALLOC_BUFSIZE;
1462 return malloc_buf;
1465 #if 0
1466 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1467 static void codec_pcmbuf_position_callback(size_t size)
1469 /* This is called from an ISR, so be quick */
1470 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1471 prev_ti->id3.elapsed;
1473 if (time >= prev_ti->id3.length)
1475 pcmbuf_set_position_callback(NULL);
1476 prev_ti->id3.elapsed = prev_ti->id3.length;
1478 else
1479 prev_ti->id3.elapsed = time;
1481 #endif
1483 static void codec_set_elapsed_callback(unsigned int value)
1485 unsigned int latency;
1486 if (ci.seek_time)
1487 return;
1489 #ifdef AB_REPEAT_ENABLE
1490 ab_position_report(value);
1491 #endif
1493 latency = pcmbuf_get_latency();
1494 if (value < latency)
1495 curtrack_id3.elapsed = 0;
1496 else if (value - latency > curtrack_id3.elapsed ||
1497 value - latency < curtrack_id3.elapsed - 2)
1499 curtrack_id3.elapsed = value - latency;
1503 static void codec_set_offset_callback(size_t value)
1505 unsigned int latency;
1507 if (ci.seek_time)
1508 return;
1510 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1511 if (value < latency)
1512 curtrack_id3.offset = 0;
1513 else
1514 curtrack_id3.offset = value - latency;
1517 /* copy up-to size bytes into ptr and return the actual size copied */
1518 static size_t codec_filebuf_callback(void *ptr, size_t size)
1520 ssize_t copy_n;
1522 if (ci.stop_codec || !playing)
1523 return 0;
1525 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1527 /* Nothing requested OR nothing left */
1528 if (copy_n == 0)
1529 return 0;
1532 if (copy_n == -2)
1534 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
1535 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
1538 /* Let the disk buffer catch fill until enough data is available */
1539 while (copy_n == -2)
1541 sleep(1);
1543 if (ci.stop_codec || ci.new_track)
1544 return 0;
1546 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1549 /* Update read and other position pointers */
1550 bufadvance(CUR_TI->audio_hid, copy_n);
1551 ci.curpos += copy_n;
1553 /* Return the actual amount of data copied to the buffer */
1554 return copy_n;
1555 } /* codec_filebuf_callback */
1557 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1559 size_t copy_n = reqsize;
1560 ssize_t ret;
1561 void *ptr;
1563 if (!playing)
1565 *realsize = 0;
1566 return NULL;
1569 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1570 if (ret >= 0)
1571 copy_n = MIN((size_t)ret, reqsize);
1573 if (copy_n == 0)
1575 *realsize = 0;
1576 return NULL;
1579 if (ret == -2)
1581 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
1582 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
1585 /* Let the disk buffer catch fill until enough data is available */
1586 while (ret == -2)
1588 sleep(1);
1590 if (ci.stop_codec || ci.new_track)
1592 *realsize = 0;
1593 return NULL;
1595 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1597 copy_n = MIN((size_t)ret, reqsize);
1599 *realsize = copy_n;
1601 return ptr;
1602 } /* codec_request_buffer_callback */
1604 static int get_codec_base_type(int type)
1606 switch (type) {
1607 case AFMT_MPA_L1:
1608 case AFMT_MPA_L2:
1609 case AFMT_MPA_L3:
1610 return AFMT_MPA_L3;
1613 return type;
1616 static void codec_advance_buffer_callback(size_t amount)
1618 bufadvance(CUR_TI->audio_hid, amount);
1619 ci.curpos += amount;
1620 codec_set_offset_callback(ci.curpos);
1623 static void codec_advance_buffer_loc_callback(void *ptr)
1625 size_t amount = get_offset(CUR_TI->audio_hid, ptr);
1627 codec_advance_buffer_callback(amount);
1630 /* Copied from mpeg.c. Should be moved somewhere else. */
1631 static int codec_get_file_pos(void)
1633 int pos = -1;
1634 struct mp3entry *id3 = audio_current_track();
1636 if (id3->vbr)
1638 if (id3->has_toc)
1640 /* Use the TOC to find the new position */
1641 unsigned int percent, remainder;
1642 int curtoc, nexttoc, plen;
1644 percent = (id3->elapsed*100)/id3->length;
1645 if (percent > 99)
1646 percent = 99;
1648 curtoc = id3->toc[percent];
1650 if (percent < 99)
1651 nexttoc = id3->toc[percent+1];
1652 else
1653 nexttoc = 256;
1655 pos = (id3->filesize/256)*curtoc;
1657 /* Use the remainder to get a more accurate position */
1658 remainder = (id3->elapsed*100)%id3->length;
1659 remainder = (remainder*100)/id3->length;
1660 plen = (nexttoc - curtoc)*(id3->filesize/256);
1661 pos += (plen/100)*remainder;
1663 else
1665 /* No TOC exists, estimate the new position */
1666 pos = (id3->filesize / (id3->length / 1000)) *
1667 (id3->elapsed / 1000);
1670 else if (id3->bitrate)
1671 pos = id3->elapsed * (id3->bitrate / 8);
1672 else
1673 return -1;
1675 pos += id3->first_frame_offset;
1677 /* Don't seek right to the end of the file so that we can
1678 transition properly to the next song */
1679 if (pos >= (int)(id3->filesize - id3->id3v1len))
1680 pos = id3->filesize - id3->id3v1len - 1;
1682 return pos;
1685 static off_t codec_mp3_get_filepos_callback(int newtime)
1687 off_t newpos;
1689 curtrack_id3.elapsed = newtime;
1690 newpos = codec_get_file_pos();
1692 return newpos;
1695 static void codec_seek_complete_callback(void)
1697 logf("seek_complete");
1698 if (pcm_is_paused())
1700 /* If this is not a seamless seek, clear the buffer */
1701 pcmbuf_play_stop();
1702 dsp_configure(DSP_FLUSH, 0);
1704 /* If playback was not 'deliberately' paused, unpause now */
1705 if (!paused)
1706 pcmbuf_pause(false);
1708 ci.seek_time = 0;
1711 static bool codec_seek_buffer_callback(size_t newpos)
1713 logf("codec_seek_buffer_callback");
1715 int ret = bufseek(CUR_TI->audio_hid, newpos);
1716 if (ret == 0) {
1717 ci.curpos = newpos;
1718 return true;
1720 else {
1721 return false;
1725 static void codec_configure_callback(int setting, intptr_t value)
1727 switch (setting) {
1728 case CODEC_SET_FILEBUF_WATERMARK:
1729 conf_watermark = value;
1730 set_filebuf_watermark(buffer_margin);
1731 break;
1733 case CODEC_SET_FILEBUF_CHUNKSIZE:
1734 conf_filechunk = value;
1735 break;
1737 case CODEC_SET_FILEBUF_PRESEEK:
1738 conf_preseek = value;
1739 break;
1741 default:
1742 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1746 static void codec_track_changed(void)
1748 automatic_skip = false;
1749 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1750 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1753 static void codec_pcmbuf_track_changed_callback(void)
1755 pcmbuf_set_position_callback(NULL);
1756 codec_track_changed();
1759 static void codec_discard_codec_callback(void)
1761 if (CUR_TI->codec_hid > 0)
1763 bufclose(CUR_TI->codec_hid);
1764 CUR_TI->codec_hid = 0;
1765 CUR_TI->codecsize = 0;
1768 #if 0
1769 /* Check if a buffer desync has happened, log it and stop playback. */
1770 if (buf_ridx != CUR_TI->buf_idx)
1772 int offset = CUR_TI->buf_idx - buf_ridx;
1773 size_t new_used = bufused() - offset;
1775 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1776 logf("Used off:%d",bufused() - new_used);
1778 /* This is a fatal internal error and it's not safe to
1779 * continue playback. */
1780 ci.stop_codec = true;
1781 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1783 #endif
1786 static inline void codec_gapless_track_change(void) {
1787 /* callback keeps the progress bar moving while the pcmbuf empties */
1788 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1789 /* set the pcmbuf callback for when the track really changes */
1790 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1793 static inline void codec_crossfade_track_change(void) {
1794 /* Initiate automatic crossfade mode */
1795 pcmbuf_crossfade_init(false);
1796 /* Notify the wps that the track change starts now */
1797 codec_track_changed();
1800 static void codec_track_skip_done(bool was_manual)
1802 int crossfade_mode = global_settings.crossfade;
1804 /* Manual track change (always crossfade or flush audio). */
1805 if (was_manual)
1807 pcmbuf_crossfade_init(true);
1808 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1809 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1811 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1812 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1813 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1815 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1817 if (global_settings.playlist_shuffle)
1818 /* shuffle mode is on, so crossfade: */
1819 codec_crossfade_track_change();
1820 else
1821 /* shuffle mode is off, so do a gapless track change */
1822 codec_gapless_track_change();
1824 else
1825 /* normal crossfade: */
1826 codec_crossfade_track_change();
1828 else
1829 /* normal gapless playback. */
1830 codec_gapless_track_change();
1833 static bool codec_load_next_track(void)
1835 intptr_t result = Q_CODEC_REQUEST_FAILED;
1837 prev_track_elapsed = curtrack_id3.elapsed;
1839 if (ci.seek_time)
1840 codec_seek_complete_callback();
1842 #ifdef AB_REPEAT_ENABLE
1843 ab_end_of_track_report();
1844 #endif
1846 logf("Request new track");
1848 if (ci.new_track == 0)
1850 ci.new_track++;
1851 automatic_skip = true;
1854 if (!ci.stop_codec)
1856 trigger_cpu_boost();
1857 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1858 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1861 switch (result)
1863 case Q_CODEC_REQUEST_COMPLETE:
1864 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1865 codec_track_skip_done(!automatic_skip);
1866 return true;
1868 case Q_CODEC_REQUEST_FAILED:
1869 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1870 ci.new_track = 0;
1871 ci.stop_codec = true;
1872 return false;
1874 default:
1875 LOGFQUEUE("codec |< default");
1876 ci.stop_codec = true;
1877 return false;
1881 static bool codec_request_next_track_callback(void)
1883 int prev_codectype;
1885 if (ci.stop_codec || !playing)
1886 return false;
1888 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1890 if (!codec_load_next_track())
1891 return false;
1893 /* Check if the next codec is the same file. */
1894 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1896 logf("New track loaded");
1897 codec_discard_codec_callback();
1898 return true;
1900 else
1902 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1903 return false;
1907 static void codec_thread(void)
1909 struct queue_event ev;
1910 int status;
1911 size_t wrap;
1913 while (1) {
1914 status = 0;
1915 queue_wait(&codec_queue, &ev);
1917 switch (ev.id) {
1918 case Q_CODEC_LOAD_DISK:
1919 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1920 queue_reply(&codec_queue, 1);
1921 audio_codec_loaded = true;
1922 #ifdef PLAYBACK_VOICE
1923 /* Don't sent messages to voice codec if it's already swapped
1924 out or it will never get this */
1925 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1927 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1928 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1930 semaphore_wait(&sem_codecthread);
1931 event_set_state(&event_codecthread, true);
1932 #endif
1933 set_current_codec(CODEC_IDX_AUDIO);
1934 ci.stop_codec = false;
1935 status = codec_load_file((const char *)ev.data, &ci);
1936 DEBUGF("codec_load = %d\n", status);
1937 #ifdef PLAYBACK_VOICE
1938 semaphore_release(&sem_codecthread);
1939 #endif
1940 break;
1942 case Q_CODEC_LOAD:
1943 LOGFQUEUE("codec < Q_CODEC_LOAD");
1944 if (CUR_TI->codec_hid <= 0) {
1945 logf("Codec slot is empty!");
1946 /* Wait for the pcm buffer to go empty */
1947 while (pcm_is_playing())
1948 yield();
1949 /* This must be set to prevent an infinite loop */
1950 ci.stop_codec = true;
1951 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1952 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1953 break;
1956 audio_codec_loaded = true;
1957 #ifdef PLAYBACK_VOICE
1958 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1960 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1961 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1963 semaphore_wait(&sem_codecthread);
1964 event_set_state(&event_codecthread, true);
1965 #endif
1966 set_current_codec(CODEC_IDX_AUDIO);
1967 ci.stop_codec = false;
1968 wrap = (size_t)&filebuf[filebuflen] - (size_t)bufgetcodec(CUR_TI);
1969 status = codec_load_ram(bufgetcodec(CUR_TI), CUR_TI->codecsize,
1970 &filebuf[0], wrap, &ci);
1971 #ifdef PLAYBACK_VOICE
1972 semaphore_release(&sem_codecthread);
1973 #endif
1974 break;
1976 #ifdef AUDIO_HAVE_RECORDING
1977 case Q_ENCODER_LOAD_DISK:
1978 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1979 audio_codec_loaded = false; /* Not audio codec! */
1980 #ifdef PLAYBACK_VOICE
1981 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1983 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1984 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
1986 semaphore_wait(&sem_codecthread);
1987 event_set_state(&event_codecthread, true);
1988 #endif
1989 logf("loading encoder");
1990 set_current_codec(CODEC_IDX_AUDIO);
1991 ci.stop_encoder = false;
1992 status = codec_load_file((const char *)ev.data, &ci);
1993 #ifdef PLAYBACK_VOICE
1994 semaphore_release(&sem_codecthread);
1995 #endif
1996 logf("encoder stopped");
1997 break;
1998 #endif /* AUDIO_HAVE_RECORDING */
2000 #ifndef SIMULATOR
2001 case SYS_USB_CONNECTED:
2002 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2003 queue_clear(&codec_queue);
2004 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2005 usb_wait_for_disconnect(&codec_queue);
2006 break;
2007 #endif
2009 default:
2010 LOGFQUEUE("codec < default");
2013 if (audio_codec_loaded)
2015 if (ci.stop_codec)
2017 status = CODEC_OK;
2018 if (!playing)
2019 pcmbuf_play_stop();
2022 audio_codec_loaded = false;
2025 switch (ev.id) {
2026 case Q_CODEC_LOAD_DISK:
2027 case Q_CODEC_LOAD:
2028 LOGFQUEUE("codec < Q_CODEC_LOAD");
2029 if (playing)
2031 if (ci.new_track || status != CODEC_OK)
2033 if (!ci.new_track)
2035 logf("Codec failure");
2036 gui_syncsplash(HZ*2, "Codec failure");
2039 if (!codec_load_next_track())
2041 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2042 /* End of playlist */
2043 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2044 break;
2047 else
2049 logf("Codec finished");
2050 if (ci.stop_codec)
2052 /* Wait for the audio to stop playing before
2053 * triggering the WPS exit */
2054 while(pcm_is_playing())
2056 curtrack_id3.elapsed =
2057 curtrack_id3.length - pcmbuf_get_latency();
2058 sleep(1);
2060 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2061 /* End of playlist */
2062 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2063 break;
2067 if (CUR_TI->codec_hid > 0)
2069 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2070 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2072 else
2074 const char *codec_fn =
2075 get_codec_filename(curtrack_id3.codectype);
2076 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2077 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2078 (intptr_t)codec_fn);
2081 break;
2083 #ifdef AUDIO_HAVE_RECORDING
2084 case Q_ENCODER_LOAD_DISK:
2085 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2087 if (status == CODEC_OK)
2088 break;
2090 logf("Encoder failure");
2091 gui_syncsplash(HZ*2, "Encoder failure");
2093 if (ci.enc_codec_loaded < 0)
2094 break;
2096 logf("Encoder failed to load");
2097 ci.enc_codec_loaded = -1;
2098 break;
2099 #endif /* AUDIO_HAVE_RECORDING */
2101 default:
2102 LOGFQUEUE("codec < default");
2104 } /* end switch */
2109 /* --- Audio thread --- */
2111 #if 0
2112 static bool audio_filebuf_is_lowdata(void)
2114 return bufused() < AUDIO_FILEBUF_CRITICAL;
2116 #endif
2118 static bool audio_have_tracks(void)
2120 return track_ridx != track_widx || CUR_TI->filesize;
2123 static bool audio_have_free_tracks(void)
2125 if (track_widx < track_ridx)
2126 return track_widx + 1 < track_ridx;
2127 else if (track_ridx == 0)
2128 return track_widx < MAX_TRACK - 1;
2130 return true;
2133 int audio_track_count(void)
2135 if (audio_have_tracks())
2137 int relative_track_widx = track_widx;
2139 if (track_ridx > track_widx)
2140 relative_track_widx += MAX_TRACK;
2142 return relative_track_widx - track_ridx + 1;
2145 return 0;
2148 long audio_filebufused(void)
2150 return (long) bufused();
2153 #if 0
2154 /* Count the data BETWEEN the selected tracks */
2155 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2157 size_t amount = 0;
2158 bool need_wrap = to_track < from_track;
2160 while (1)
2162 if (++from_track >= MAX_TRACK)
2164 from_track -= MAX_TRACK;
2165 need_wrap = false;
2168 if (from_track >= to_track && !need_wrap)
2169 break;
2171 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2173 return amount;
2175 #endif
2177 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2179 (void)new_track_ridx;
2180 (void)old_track_ridx;
2181 #if 0
2182 size_t amount;
2184 /* Start with the remainder of the previously playing track */
2185 amount = tracks[old_track_ridx].filesize - ci.curpos;
2186 /* Then collect all data from tracks in between them */
2187 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2188 logf("bwf:%ldB", (long) amount);
2190 if (amount > bufused())
2191 return false;
2193 /* Wind the buffer to the beginning of the target track or its codec */
2194 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2195 #endif
2196 return true;
2199 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2201 (void)new_track_ridx;
2202 (void)old_track_ridx;
2203 #if 0
2204 /* Available buffer data */
2205 size_t buf_back;
2206 /* Start with the previously playing track's data and our data */
2207 size_t amount;
2209 amount = ci.curpos;
2210 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2212 /* If we're not just resetting the current track */
2213 if (new_track_ridx != old_track_ridx)
2215 /* Need to wind to before the old track's codec and our filesize */
2216 amount += tracks[old_track_ridx].codecsize;
2217 amount += tracks[new_track_ridx].filesize;
2219 /* Rewind the old track to its beginning */
2220 tracks[old_track_ridx].available =
2221 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2224 /* If the codec was ever buffered */
2225 if (tracks[new_track_ridx].codecsize)
2227 /* Add the codec to the needed size */
2228 amount += tracks[new_track_ridx].codecsize;
2229 tracks[new_track_ridx].has_codec = true;
2232 /* Then collect all data from tracks between new and old */
2233 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2235 /* Do we have space to make this skip? */
2236 if (amount > buf_back)
2237 return false;
2239 logf("bwb:%ldB",amount);
2241 /* Rewind the buffer to the beginning of the target track or its codec */
2242 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2244 /* Reset to the beginning of the new track */
2245 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2246 #endif
2247 return true;
2250 static void audio_update_trackinfo(void)
2252 if (CUR_TI->id3_hid > 0)
2253 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
2255 CUR_TI->taginfo_ready = (CUR_TI->id3_hid > 0);
2257 int next_idx = track_ridx + 1;
2258 next_idx &= MAX_TRACK_MASK;
2260 if (tracks[next_idx].id3_hid > 0)
2261 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
2263 tracks[next_idx].taginfo_ready = (tracks[next_idx].id3_hid > 0);
2265 ci.filesize = CUR_TI->filesize;
2266 curtrack_id3.elapsed = 0;
2267 curtrack_id3.offset = 0;
2268 ci.id3 = &curtrack_id3;
2269 ci.curpos = 0;
2270 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2273 #if 0
2274 /* Yield to codecs for as long as possible if they are in need of data
2275 * return true if the caller should break to let the audio thread process
2276 * new events */
2277 static bool audio_yield_codecs(void)
2279 yield();
2281 if (!queue_empty(&audio_queue))
2282 return true;
2284 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2285 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2287 if (filling)
2288 yield();
2289 else
2290 sleep(2);
2292 if (!queue_empty(&audio_queue))
2293 return true;
2296 return false;
2298 #endif
2300 static void audio_clear_track_entries(bool clear_unbuffered)
2302 int cur_idx = track_widx;
2303 int last_idx = -1;
2305 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2307 /* Loop over all tracks from write-to-read */
2308 while (1)
2310 cur_idx++;
2311 cur_idx &= MAX_TRACK_MASK;
2313 if (cur_idx == track_ridx)
2314 break;
2316 /* If the track is buffered, conditionally clear/notify,
2317 * otherwise clear the track if that option is selected */
2318 if (tracks[cur_idx].event_sent)
2320 if (last_idx >= 0)
2322 /* If there is an unbuffer callback, call it, otherwise,
2323 * just clear the track */
2324 if (track_unbuffer_callback)
2325 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2327 clear_track_info(&tracks[last_idx]);
2329 last_idx = cur_idx;
2331 else if (clear_unbuffered)
2332 clear_track_info(&tracks[cur_idx]);
2335 /* We clear the previous instance of a buffered track throughout
2336 * the above loop to facilitate 'last' detection. Clear/notify
2337 * the last track here */
2338 if (last_idx >= 0)
2340 if (track_unbuffer_callback)
2341 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2342 clear_track_info(&tracks[last_idx]);
2346 static void audio_release_tracks(void)
2348 int cur_idx = track_ridx;
2350 logf("releasing all tracks");
2352 while (1)
2354 clear_track_info(&tracks[cur_idx]);
2356 cur_idx++;
2357 cur_idx &= MAX_TRACK_MASK;
2359 if (cur_idx == track_widx)
2360 break;
2364 #if 0
2365 /* FIXME: This code should be made more generic and move to metadata.c */
2366 static void audio_strip_tags(void)
2368 int i;
2369 static const unsigned char tag[] = "TAG";
2370 static const unsigned char apetag[] = "APETAGEX";
2371 size_t tag_idx;
2372 size_t cur_idx;
2373 size_t len, version;
2375 tag_idx = RINGBUF_SUB(buf_widx, 128);
2377 if (bufused() > 128 && tag_idx > buf_ridx)
2379 cur_idx = tag_idx;
2380 for(i = 0;i < 3;i++)
2382 if(filebuf[cur_idx] != tag[i])
2383 goto strip_ape_tag;
2385 cur_idx = RINGBUF_ADD(cur_idx, 1);
2388 /* Skip id3v1 tag */
2389 logf("Skipping ID3v1 tag");
2390 buf_widx = tag_idx;
2391 tracks[track_widx].available -= 128;
2392 tracks[track_widx].filesize -= 128;
2395 strip_ape_tag:
2396 /* Check for APE tag (look for the APE tag footer) */
2397 tag_idx = RINGBUF_SUB(buf_widx, 32);
2399 if (bufused() > 32 && tag_idx > buf_ridx)
2401 cur_idx = tag_idx;
2402 for(i = 0;i < 8;i++)
2404 if(filebuf[cur_idx] != apetag[i])
2405 return;
2407 cur_idx = RINGBUF_ADD(cur_idx, 1);
2410 /* Read the version and length from the footer */
2411 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2412 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2413 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2414 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2415 if (version == 2000)
2416 len += 32; /* APEv2 has a 32 byte header */
2418 /* Skip APE tag */
2419 if (bufused() > len)
2421 logf("Skipping APE tag (%ldB)", len);
2422 buf_widx = RINGBUF_SUB(buf_widx, len);
2423 tracks[track_widx].available -= len;
2424 tracks[track_widx].filesize -= len;
2428 #endif
2430 #if 0
2431 /* Returns true if a whole file is read, false otherwise */
2432 static bool audio_read_file(size_t minimum)
2434 bool ret_val = false;
2436 /* If we're called and no file is open, this is an error */
2437 if (current_fd < 0)
2439 logf("Bad fd in arf");
2440 /* Give some hope of miraculous recovery by forcing a track reload */
2441 tracks[track_widx].filesize = 0;
2442 /* Stop this buffering run */
2443 return ret_val;
2446 trigger_cpu_boost();
2447 while (tracks[track_widx].filerem > 0)
2449 size_t copy_n;
2450 int overlap;
2451 int rc;
2453 /* copy_n is the largest chunk that is safe to read */
2454 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2456 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2457 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2458 break;
2460 /* rc is the actual amount read */
2461 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2463 if (rc < 0)
2465 logf("File ended %ldB early", tracks[track_widx].filerem);
2466 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2467 tracks[track_widx].filerem = 0;
2468 break;
2471 /* How much of the playing track did we overwrite */
2472 if (buf_widx == CUR_TI->buf_idx)
2474 /* Special handling; zero or full overlap? */
2475 if (track_widx == track_ridx && CUR_TI->available == 0)
2476 overlap = 0;
2477 else
2478 overlap = rc;
2480 else
2481 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2483 if ((unsigned)rc > tracks[track_widx].filerem)
2485 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2486 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2487 tracks[track_widx].filerem = rc;
2490 /* Advance buffer */
2491 buf_widx = RINGBUF_ADD(buf_widx, rc);
2492 tracks[track_widx].available += rc;
2493 tracks[track_widx].filerem -= rc;
2495 /* If we write into the playing track, adjust it's buffer info */
2496 if (overlap > 0)
2498 CUR_TI->buf_idx += overlap;
2499 CUR_TI->start_pos += overlap;
2502 /* For a rebuffer, fill at least this minimum */
2503 if (minimum > (unsigned)rc)
2504 minimum -= rc;
2505 /* Let the codec process up to the watermark */
2506 /* Break immediately if this is a quick buffer, or there is an event */
2507 else if (minimum || audio_yield_codecs())
2509 /* Exit quickly, but don't stop the overall buffering process */
2510 ret_val = true;
2511 break;
2515 if (tracks[track_widx].filerem == 0)
2517 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2518 close(current_fd);
2519 current_fd = -1;
2520 audio_strip_tags();
2522 track_widx++;
2523 track_widx &= MAX_TRACK_MASK;
2525 tracks[track_widx].filesize = 0;
2526 return true;
2528 else
2530 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2531 tracks[track_widx].filesize - tracks[track_widx].filerem);
2532 return ret_val;
2535 #endif
2537 static bool audio_loadcodec(bool start_play)
2539 int fd;
2540 int prev_track;
2541 char codec_path[MAX_PATH]; /* Full path to codec */
2543 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play ? "true" : "false");
2545 if (tracks[track_widx].id3_hid <= 0) {
2546 DEBUGF("track ID3 info not ready\n");
2547 return false;
2550 const char * codec_fn =
2551 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2552 if (codec_fn == NULL)
2553 return false;
2555 tracks[track_widx].codec_hid = 0;
2557 if (start_play)
2559 /* Load the codec directly from disk and save some memory. */
2560 track_ridx = track_widx;
2561 ci.filesize = CUR_TI->filesize;
2562 ci.id3 = &curtrack_id3;
2563 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2564 ci.curpos = 0;
2565 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2566 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2567 return true;
2569 else
2571 /* If we already have another track than this one buffered */
2572 if (track_widx != track_ridx)
2574 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2576 /* If the previous codec is the same as this one, there is no need
2577 * to put another copy of it on the file buffer */
2578 if (get_codec_base_type(
2579 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2580 get_codec_base_type(
2581 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2582 && audio_codec_loaded)
2584 logf("Reusing prev. codec");
2585 return true;
2590 codec_get_full_path(codec_path, codec_fn);
2592 fd = open(codec_path, O_RDONLY);
2593 if (fd < 0)
2595 logf("Codec doesn't exist!");
2596 return false;
2599 tracks[track_widx].codecsize = filesize(fd);
2601 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2602 if (tracks[track_widx].codec_hid < 0)
2604 logf("Not enough space");
2605 close(fd);
2606 return false;
2609 close(fd);
2610 logf("Loaded codec");
2612 return true;
2615 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2616 static void audio_set_elapsed(struct mp3entry* id3)
2618 unsigned long offset = id3->offset > id3->first_frame_offset ?
2619 id3->offset - id3->first_frame_offset : 0;
2621 if ( id3->vbr ) {
2622 if ( id3->has_toc ) {
2623 /* calculate elapsed time using TOC */
2624 int i;
2625 unsigned int remainder, plen, relpos, nextpos;
2627 /* find wich percent we're at */
2628 for (i=0; i<100; i++ )
2629 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2630 break;
2632 i--;
2633 if (i < 0)
2634 i = 0;
2636 relpos = id3->toc[i];
2638 if (i < 99)
2639 nextpos = id3->toc[i+1];
2640 else
2641 nextpos = 256;
2643 remainder = offset - (relpos * (id3->filesize / 256));
2645 /* set time for this percent (divide before multiply to prevent
2646 overflow on long files. loss of precision is negligible on
2647 short files) */
2648 id3->elapsed = i * (id3->length / 100);
2650 /* calculate remainder time */
2651 plen = (nextpos - relpos) * (id3->filesize / 256);
2652 id3->elapsed += (((remainder * 100) / plen) *
2653 (id3->length / 10000));
2655 else {
2656 /* no TOC exists. set a rough estimate using average bitrate */
2657 int tpk = id3->length /
2658 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2659 1024);
2660 id3->elapsed = offset / 1024 * tpk;
2663 else
2665 /* constant bitrate, use exact calculation */
2666 if (id3->bitrate != 0)
2667 id3->elapsed = offset / (id3->bitrate / 8);
2671 /* Load one track by making the appropriate bufopen calls. Return true if
2672 everything required was loaded correctly, false if not. */
2673 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2675 (void)rebuffer;
2676 char *trackname;
2677 char msgbuf[80];
2678 int fd = -1;
2679 int file_offset = 0;
2680 struct mp3entry id3;
2682 /* Stop buffer filling if there is no free track entries.
2683 Don't fill up the last track entry (we wan't to store next track
2684 metadata there). */
2685 if (!audio_have_free_tracks())
2687 logf("No free tracks");
2688 return false;
2691 last_peek_offset++;
2692 peek_again:
2693 logf("Buffering track:%d/%d", track_widx, track_ridx);
2694 /* Get track name from current playlist read position. */
2695 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2697 /* Handle broken playlists. */
2698 fd = open(trackname, O_RDONLY);
2699 if (fd < 0)
2701 logf("Open failed");
2702 /* Skip invalid entry from playlist. */
2703 playlist_skip_entry(NULL, last_peek_offset);
2705 else
2706 break;
2709 if (!trackname)
2711 logf("End-of-playlist");
2712 playlist_end = true;
2713 return false;
2716 tracks[track_widx].filesize = filesize(fd);
2718 /* Set default values */
2719 if (start_play)
2721 int last_codec = current_codec;
2723 set_current_codec(CODEC_IDX_AUDIO);
2724 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2725 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2726 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2727 dsp_configure(DSP_RESET, 0);
2728 set_current_codec(last_codec);
2730 track_changed = true;
2731 playlist_update_resume_info(audio_current_track());
2734 /* Get track metadata if we don't already have it. */
2735 if (tracks[track_widx].id3_hid <= 0)
2737 if (get_metadata(&id3, fd, trackname))
2739 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2740 TYPE_ID3);
2741 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2743 if (tracks[track_widx].id3_hid <= 0)
2745 DEBUGF("failed to allocate space for metadata\n");
2746 last_peek_offset--;
2747 close(fd);
2748 return false;
2751 if (track_widx == track_ridx)
2752 copy_mp3entry(&curtrack_id3, &id3);
2753 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2754 copy_mp3entry(&nexttrack_id3, &id3);
2756 if (start_play)
2758 track_changed = true;
2759 playlist_update_resume_info(audio_current_track());
2762 else
2764 logf("mde:%s!",trackname);
2766 /* Skip invalid entry from playlist. */
2767 playlist_skip_entry(NULL, last_peek_offset);
2768 tracks[track_widx].taginfo_ready = false;
2769 goto peek_again;
2774 close(fd);
2776 #if 0
2777 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2779 char cuepath[MAX_PATH];
2781 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2783 if (look_for_cuesheet_file(trackname, cuepath) &&
2784 parse_cuesheet(cuepath, cue))
2786 strcpy((cue)->audio_filename, trackname);
2787 if (start_play)
2788 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2791 #endif
2793 /* Load the codec. */
2794 if (!audio_loadcodec(start_play))
2796 if (tracks[track_widx].codecsize)
2798 /* No space for codec on buffer, not an error */
2799 tracks[track_widx].codecsize = 0;
2800 return false;
2803 /* This is an error condition, either no codec was found, or reading
2804 * the codec file failed part way through, either way, skip the track */
2805 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2806 /* We should not use gui_syncplash from audio thread! */
2807 gui_syncsplash(HZ*2, msgbuf);
2808 /* Skip invalid entry from playlist. */
2809 playlist_skip_entry(NULL, last_peek_offset);
2810 tracks[track_widx].taginfo_ready = false;
2811 goto peek_again;
2814 struct mp3entry *track_id3;
2816 if (track_widx == track_ridx)
2817 track_id3 = &curtrack_id3;
2818 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2819 track_id3 = &nexttrack_id3;
2820 else
2821 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2823 set_filebuf_watermark(buffer_margin);
2824 track_id3->elapsed = 0;
2826 if (offset > 0)
2828 switch (track_id3->codectype) {
2829 case AFMT_MPA_L1:
2830 case AFMT_MPA_L2:
2831 case AFMT_MPA_L3:
2832 file_offset = offset;
2833 track_id3->offset = offset;
2834 audio_set_elapsed(track_id3);
2835 ci.curpos = offset;
2836 break;
2838 case AFMT_WAVPACK:
2839 file_offset = offset;
2840 track_id3->offset = offset;
2841 track_id3->elapsed = track_id3->length / 2;
2842 ci.curpos = offset;
2843 break;
2845 case AFMT_OGG_VORBIS:
2846 case AFMT_SPEEX:
2847 case AFMT_FLAC:
2848 case AFMT_PCM_WAV:
2849 case AFMT_A52:
2850 case AFMT_AAC:
2851 case AFMT_MPC:
2852 case AFMT_APE:
2853 track_id3->offset = offset;
2854 break;
2858 logf("alt:%s", trackname);
2860 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, TYPE_AUDIO);
2862 if (tracks[track_widx].audio_hid <= 0)
2863 return false;
2865 if (start_play)
2867 LOGFQUEUE("audio >| buffering Q_BUFFER_HANDLE");
2868 queue_send(&buffering_queue, Q_BUFFER_HANDLE, tracks[track_widx].audio_hid);
2871 track_widx++;
2872 track_widx &= MAX_TRACK_MASK;
2874 return true;
2877 #if 0
2878 static bool audio_read_next_metadata(void)
2880 int fd;
2881 char *trackname;
2882 int next_idx;
2883 int status;
2885 next_idx = track_widx;
2886 if (tracks[next_idx].id3_hid > 0)
2888 next_idx++;
2889 next_idx &= MAX_TRACK_MASK;
2891 if (tracks[next_idx].id3_hid > 0)
2892 return true;
2895 trackname = playlist_peek(last_peek_offset + 1);
2896 if (!trackname)
2897 return false;
2899 fd = open(trackname, O_RDONLY);
2900 if (fd < 0)
2901 return false;
2903 struct mp3entry id3;
2905 status = get_metadata(&id3, fd, trackname);
2906 /* Preload the glyphs in the tags */
2907 if (status)
2909 tracks[next_idx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
2911 if (tracks[next_idx].id3_hid > 0)
2913 tracks[next_idx].taginfo_ready = true;
2914 if (id3.title)
2915 lcd_getstringsize(id3.title, NULL, NULL);
2916 if (id3.artist)
2917 lcd_getstringsize(id3.artist, NULL, NULL);
2918 if (id3.album)
2919 lcd_getstringsize(id3.album, NULL, NULL);
2921 else
2922 status = false;
2924 close(fd);
2926 return status;
2928 #endif
2930 /* Send callback events to notify about new tracks. */
2931 static void audio_generate_postbuffer_events(void)
2933 int cur_idx;
2934 int last_idx = -1;
2936 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2938 if (audio_have_tracks())
2940 cur_idx = track_ridx;
2942 while (1) {
2943 if (!tracks[cur_idx].event_sent)
2945 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2947 /* Mark the event 'sent' even if we don't really send one */
2948 tracks[last_idx].event_sent = true;
2949 if (track_buffer_callback)
2950 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2952 last_idx = cur_idx;
2954 if (cur_idx == track_widx)
2955 break;
2956 cur_idx++;
2957 cur_idx &= MAX_TRACK_MASK;
2960 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2962 tracks[last_idx].event_sent = true;
2963 if (track_buffer_callback)
2964 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2969 static bool audio_initialize_buffer_fill(bool clear_tracks)
2971 /* Don't initialize if we're already initialized */
2972 if (filling)
2973 return true;
2975 logf("Starting buffer fill");
2977 /* Set the filling flag true before calling audio_clear_tracks as that
2978 * function can yield and we start looping. */
2979 filling = true;
2981 if (clear_tracks)
2982 audio_clear_track_entries(false);
2984 /* Save the current resume position once. */
2985 playlist_update_resume_info(audio_current_track());
2987 return true;
2990 static void audio_fill_file_buffer(
2991 bool start_play, bool rebuffer, size_t offset)
2993 bool had_next_track = audio_next_track() != NULL;
2994 bool continue_buffering;
2996 /* Must reset the buffer before use if trashed or voice only - voice
2997 file size shouldn't have changed so we can go straight from
2998 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2999 if (buffer_state != BUFFER_STATE_INITIALIZED)
3000 audio_reset_buffer();
3002 if (!audio_initialize_buffer_fill(!start_play))
3003 return ;
3005 continue_buffering = audio_load_track(offset, start_play, rebuffer);
3007 if (!had_next_track && audio_next_track())
3008 track_changed = true;
3010 /* If we're done buffering */
3011 if (!continue_buffering)
3013 //audio_read_next_metadata();
3015 audio_generate_postbuffer_events();
3016 filling = false;
3018 #ifndef SIMULATOR
3019 ata_sleep();
3020 #endif
3024 static void audio_rebuffer(void)
3026 logf("Forcing rebuffer");
3028 clear_track_info(CUR_TI);
3030 /* Reset track pointers */
3031 track_widx = track_ridx;
3032 audio_clear_track_entries(true);
3034 /* Fill the buffer */
3035 last_peek_offset = -1;
3036 ci.curpos = 0;
3038 if (!CUR_TI->taginfo_ready)
3039 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3041 audio_fill_file_buffer(false, true, 0);
3044 static int audio_check_new_track(void)
3046 DEBUGF("audio_check_new_track\n");
3048 int track_count = audio_track_count();
3049 int old_track_ridx = track_ridx;
3050 bool forward;
3052 if (dir_skip)
3054 dir_skip = false;
3055 if (playlist_next_dir(ci.new_track))
3057 ci.new_track = 0;
3058 audio_rebuffer();
3059 goto skip_done;
3061 else
3063 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3064 return Q_CODEC_REQUEST_FAILED;
3068 if (new_playlist)
3069 ci.new_track = 0;
3071 /* If the playlist isn't that big */
3072 if (!playlist_check(ci.new_track))
3074 if (ci.new_track >= 0)
3076 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3077 return Q_CODEC_REQUEST_FAILED;
3079 /* Find the beginning backward if the user over-skips it */
3080 while (!playlist_check(++ci.new_track))
3081 if (ci.new_track >= 0)
3083 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3084 return Q_CODEC_REQUEST_FAILED;
3087 /* Update the playlist */
3088 last_peek_offset -= ci.new_track;
3090 if (playlist_next(ci.new_track) < 0)
3092 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3093 return Q_CODEC_REQUEST_FAILED;
3096 if (new_playlist)
3098 ci.new_track = 1;
3099 new_playlist = false;
3102 /* Save the old track */
3103 /* prev_ti = CUR_TI; */
3105 int i, idx;
3106 for (i = 0; i < ci.new_track; i++)
3108 idx = (track_ridx + i) & MAX_TRACK_MASK;
3109 clear_track_info(&tracks[idx]);
3112 /* Move to the new track */
3113 track_ridx += ci.new_track;
3114 track_ridx &= MAX_TRACK_MASK;
3116 if (automatic_skip)
3117 playlist_end = false;
3119 track_changed = !automatic_skip;
3121 /* If it is not safe to even skip this many track entries */
3122 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3124 ci.new_track = 0;
3125 audio_rebuffer();
3126 goto skip_done;
3129 forward = ci.new_track > 0;
3130 ci.new_track = 0;
3132 /* If the target track is clearly not in memory */
3133 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3135 audio_rebuffer();
3136 goto skip_done;
3139 /* The track may be in memory, see if it really is */
3140 if (forward)
3142 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3143 audio_rebuffer();
3145 else
3147 int cur_idx = track_ridx;
3148 bool taginfo_ready = true;
3149 bool wrap = track_ridx > old_track_ridx;
3151 while (1)
3153 cur_idx++;
3154 cur_idx &= MAX_TRACK_MASK;
3155 if (!(wrap || cur_idx < old_track_ridx))
3156 break;
3158 /* If we hit a track in between without valid tag info, bail */
3159 if (!tracks[cur_idx].taginfo_ready)
3161 taginfo_ready = false;
3162 break;
3165 tracks[cur_idx].available = tracks[cur_idx].filesize;
3166 if (tracks[cur_idx].codecsize)
3167 tracks[cur_idx].has_codec = true;*/
3169 if (taginfo_ready)
3171 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3172 audio_rebuffer();
3174 else
3176 audio_rebuffer();
3180 skip_done:
3181 audio_update_trackinfo();
3182 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3183 return Q_CODEC_REQUEST_COMPLETE;
3186 #if 0
3187 static int audio_rebuffer_and_seek(size_t newpos)
3189 size_t real_preseek;
3190 int fd;
3191 char *trackname;
3193 /* (Re-)open current track's file handle. */
3194 trackname = playlist_peek(0);
3195 fd = open(trackname, O_RDONLY);
3196 if (fd < 0)
3198 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3199 return Q_CODEC_REQUEST_FAILED;
3202 if (current_fd >= 0)
3203 close(current_fd);
3204 current_fd = fd;
3206 playlist_end = false;
3208 ci.curpos = newpos;
3210 /* Clear codec buffer. */
3211 track_widx = track_ridx;
3212 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3214 last_peek_offset = 0;
3215 filling = false;
3216 audio_initialize_buffer_fill(true);
3218 /* This may have been tweaked by the id3v1 code */
3219 CUR_TI->filesize=filesize(fd);
3220 if (newpos > conf_preseek)
3222 CUR_TI->start_pos = newpos - conf_preseek;
3223 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3224 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3225 real_preseek = conf_preseek;
3227 else
3229 CUR_TI->start_pos = 0;
3230 CUR_TI->filerem = CUR_TI->filesize;
3231 real_preseek = newpos;
3234 CUR_TI->available = 0;
3236 audio_read_file(real_preseek);
3238 /* Account for the data we just read that is 'behind' us now */
3239 CUR_TI->available -= real_preseek;
3241 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3243 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3244 return Q_CODEC_REQUEST_COMPLETE;
3246 #endif
3248 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3249 bool last_track))
3251 track_buffer_callback = handler;
3254 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3255 bool last_track))
3257 track_unbuffer_callback = handler;
3260 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3262 track_changed_callback = handler;
3265 unsigned long audio_prev_elapsed(void)
3267 return prev_track_elapsed;
3270 static void audio_stop_codec_flush(void)
3272 ci.stop_codec = true;
3273 pcmbuf_pause(true);
3275 while (audio_codec_loaded)
3276 yield();
3278 /* If the audio codec is not loaded any more, and the audio is still
3279 * playing, it is now and _only_ now safe to call this function from the
3280 * audio thread */
3281 if (pcm_is_playing())
3282 pcmbuf_play_stop();
3283 pcmbuf_pause(paused);
3286 static void audio_stop_playback(void)
3288 /* If we were playing, save resume information */
3289 if (playing)
3291 struct mp3entry *id3 = NULL;
3293 if (!playlist_end || !ci.stop_codec)
3295 /* Set this early, the outside code yields and may allow the codec
3296 to try to wait for a reply on a buffer wait */
3297 ci.stop_codec = true;
3298 id3 = audio_current_track();
3301 /* Save the current playing spot, or NULL if the playlist has ended */
3302 playlist_update_resume_info(id3);
3304 prev_track_elapsed = curtrack_id3.elapsed;
3306 /* Increment index so runtime info is saved in audio_clear_track_entries().
3307 * Done here, as audio_stop_playback() may be called more than once.
3308 * Don't update runtime unless playback is stopped because of end of playlist.
3309 * Updating runtime when manually stopping a tracks, can destroy autoscores
3310 * and playcounts.
3312 if (playlist_end)
3314 track_ridx++;
3315 track_ridx &= MAX_TRACK_MASK;
3319 filling = false;
3320 paused = false;
3321 audio_stop_codec_flush();
3322 playing = false;
3324 /* Close all tracks */
3325 audio_release_tracks();
3327 /* Mark all entries null. */
3328 audio_clear_track_entries(false);
3330 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3331 memset(&nexttrack_id3, 0, sizeof(struct mp3entry));
3334 static void audio_play_start(size_t offset)
3336 #if INPUT_SRC_CAPS != 0
3337 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3338 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3339 #endif
3341 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3342 paused = false;
3343 audio_stop_codec_flush();
3345 track_changed = true;
3346 playlist_end = false;
3348 playing = true;
3350 ci.new_track = 0;
3351 ci.seek_time = 0;
3352 wps_offset = 0;
3354 sound_set_volume(global_settings.volume);
3355 track_widx = track_ridx = 0;
3357 /* Mark all entries null. */
3358 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3360 last_peek_offset = -1;
3362 /* Officially playing */
3363 queue_reply(&audio_queue, 1);
3365 audio_fill_file_buffer(true, false, offset);
3367 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3368 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3372 /* Invalidates all but currently playing track. */
3373 static void audio_invalidate_tracks(void)
3375 if (audio_have_tracks())
3377 last_peek_offset = 0;
3378 playlist_end = false;
3379 track_widx = track_ridx;
3381 /* Mark all other entries null (also buffered wrong metadata). */
3382 audio_clear_track_entries(true);
3384 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3388 static void audio_new_playlist(void)
3390 /* Prepare to start a new fill from the beginning of the playlist */
3391 last_peek_offset = -1;
3392 if (audio_have_tracks())
3394 if (paused)
3395 skipped_during_pause = true;
3396 playlist_end = false;
3397 track_widx = track_ridx;
3398 audio_clear_track_entries(true);
3400 track_widx++;
3401 track_widx &= MAX_TRACK_MASK;
3403 /* Mark the current track as invalid to prevent skipping back to it */
3404 CUR_TI->taginfo_ready = false;
3407 /* Signal the codec to initiate a track change forward */
3408 new_playlist = true;
3409 ci.new_track = 1;
3411 /* Officially playing */
3412 queue_reply(&audio_queue, 1);
3414 audio_fill_file_buffer(false, true, 0);
3417 static void audio_initiate_track_change(long direction)
3419 playlist_end = false;
3420 ci.new_track += direction;
3421 wps_offset -= direction;
3422 if (paused)
3423 skipped_during_pause = true;
3426 static void audio_initiate_dir_change(long direction)
3428 playlist_end = false;
3429 dir_skip = true;
3430 ci.new_track = direction;
3431 if (paused)
3432 skipped_during_pause = true;
3436 * Layout audio buffer as follows - iram buffer depends on target:
3437 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3439 static void audio_reset_buffer(void)
3441 /* see audio_get_recording_buffer if this is modified */
3442 logf("audio_reset_buffer");
3444 /* If the setup of anything allocated before the file buffer is
3445 changed, do check the adjustments after the buffer_alloc call
3446 as it will likely be affected and need sliding over */
3448 /* Initially set up file buffer as all space available */
3449 malloc_buf = audiobuf + talk_get_bufsize();
3450 /* Align the malloc buf to line size. Especially important to cf
3451 targets that do line reads/writes. */
3452 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3453 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3454 filebuflen = audiobufend - filebuf;
3456 /* Allow for codec swap space at end of audio buffer */
3457 if (talk_voice_required())
3459 /* Layout of swap buffer:
3460 * #ifdef IRAM_STEAL (dedicated iram_buf):
3461 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3462 * #else:
3463 * audiobuf...|dram_buf|iram_buf|audiobufend
3465 #ifdef PLAYBACK_VOICE
3466 /* Check for an absolutely nasty situation which should never,
3467 ever happen - frankly should just panic */
3468 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3470 logf("buffer reset with voice swapped");
3472 /* line align length which line aligns the calculations below since
3473 all sizes are also at least line aligned - needed for memswap128 */
3474 filebuflen &= ~15;
3475 #ifdef IRAM_STEAL
3476 filebuflen -= CODEC_SIZE;
3477 #else
3478 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3479 #endif
3480 /* Allocate buffers for swapping voice <=> audio */
3481 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3482 and out of the way of buffer usage or else a call to audio_get_buffer
3483 and subsequent buffer use might trash the swap space. A plugin
3484 initializing IRAM after getting the full buffer would present similar
3485 problem. Options include: failing the request if the other buffer
3486 has been obtained already or never allowing use of the voice IRAM
3487 buffer within the audio buffer. Using buffer_alloc basically
3488 implements the second in a more convenient way. */
3489 dram_buf = filebuf + filebuflen;
3491 #ifdef IRAM_STEAL
3492 /* Allocate voice IRAM swap buffer once */
3493 if (iram_buf == NULL)
3495 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3496 /* buffer_alloc moves audiobuf; this is safe because only the end
3497 * has been touched so far in this function and the address of
3498 * filebuf + filebuflen is not changed */
3499 malloc_buf += CODEC_IRAM_SIZE;
3500 filebuf += CODEC_IRAM_SIZE;
3501 filebuflen -= CODEC_IRAM_SIZE;
3503 #else
3504 /* Allocate iram_buf after dram_buf */
3505 iram_buf = dram_buf + CODEC_SIZE;
3506 #endif /* IRAM_STEAL */
3507 #endif /* PLAYBACK_VOICE */
3509 else
3511 #ifdef PLAYBACK_VOICE
3512 /* No swap buffers needed */
3513 iram_buf = NULL;
3514 dram_buf = NULL;
3515 #endif
3518 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3519 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3521 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3522 will already be line aligned */
3523 filebuflen &= ~3;
3525 /* Set the high watermark as 75% full...or 25% empty :) */
3526 #if MEM > 8
3527 high_watermark = 3*filebuflen / 4;
3528 #endif
3530 /* Clear any references to the file buffer */
3531 buffer_state = BUFFER_STATE_INITIALIZED;
3533 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3534 /* Make sure everything adds up - yes, some info is a bit redundant but
3535 aids viewing and the sumation of certain variables should add up to
3536 the location of others. */
3538 size_t pcmbufsize;
3539 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3540 logf("mabuf: %08X", (unsigned)malloc_buf);
3541 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3542 logf("fbuf: %08X", (unsigned)filebuf);
3543 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3544 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3545 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3546 logf("pcmb: %08X", (unsigned)pcmbuf);
3547 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3548 if (dram_buf)
3550 logf("dramb: %08X", (unsigned)dram_buf);
3551 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3553 if (iram_buf)
3555 logf("iramb: %08X", (unsigned)iram_buf);
3556 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3559 #endif
3562 #if MEM > 8
3563 /* we dont want this rebuffering on targets with little ram
3564 because the disk may never spin down */
3565 static bool ata_fillbuffer_callback(void)
3567 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3568 return true;
3570 #endif
3572 static void audio_thread(void)
3574 struct queue_event ev;
3576 pcm_postinit();
3578 #ifdef PLAYBACK_VOICE
3579 /* Unlock semaphore that init stage locks before creating this thread */
3580 semaphore_release(&sem_codecthread);
3582 /* Buffers must be set up by now - should panic - really */
3583 if (buffer_state != BUFFER_STATE_INITIALIZED)
3585 logf("audio_thread start: no buffer");
3588 /* Have to wait for voice to load up or else the codec swap will be
3589 invalid when an audio codec is loaded */
3590 wait_for_voice_swap_in();
3591 #endif
3593 while (1)
3595 if (filling)
3597 queue_wait_w_tmo(&audio_queue, &ev, 0);
3598 if (ev.id == SYS_TIMEOUT)
3599 ev.id = Q_AUDIO_FILL_BUFFER;
3601 else
3603 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3604 #if MEM > 8
3605 if (playing && (ev.id == SYS_TIMEOUT) &&
3606 (bufused() < high_watermark))
3607 register_ata_idle_func(ata_fillbuffer_callback);
3608 #endif
3611 switch (ev.id) {
3612 #if MEM > 8
3613 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3614 /* only fill if the disk is still spining */
3615 #ifndef SIMULATOR
3616 if (!ata_disk_is_active())
3617 break;
3618 #endif
3619 #endif /* MEM > 8 */
3620 /* else fall through to Q_AUDIO_FILL_BUFFER */
3621 case Q_AUDIO_FILL_BUFFER:
3622 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3623 if (!filling)
3624 if (!playing || playlist_end || ci.stop_codec)
3625 break;
3626 audio_fill_file_buffer(false, false, 0);
3627 break;
3629 case Q_AUDIO_PLAY:
3630 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3631 if (playing && ev.data <= 0)
3632 audio_new_playlist();
3633 else
3635 audio_stop_playback();
3636 audio_play_start((size_t)ev.data);
3638 break;
3640 case Q_AUDIO_STOP:
3641 LOGFQUEUE("audio < Q_AUDIO_STOP");
3642 if (playing)
3643 audio_stop_playback();
3644 if (ev.data != 0)
3645 queue_clear(&audio_queue);
3646 break;
3648 case Q_AUDIO_PAUSE:
3649 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3650 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3651 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3652 skipped_during_pause = false;
3653 if (!playing)
3654 break;
3655 pcmbuf_pause((bool)ev.data);
3656 paused = (bool)ev.data;
3657 break;
3659 case Q_AUDIO_SKIP:
3660 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3661 audio_initiate_track_change((long)ev.data);
3662 break;
3664 case Q_AUDIO_PRE_FF_REWIND:
3665 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3666 if (!playing)
3667 break;
3668 pcmbuf_pause(true);
3669 break;
3671 case Q_AUDIO_FF_REWIND:
3672 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3673 if (!playing)
3674 break;
3675 ci.seek_time = (long)ev.data+1;
3676 break;
3678 #if 0
3679 case Q_AUDIO_REBUFFER_SEEK:
3680 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3681 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3682 break;
3683 #endif
3685 case Q_AUDIO_CHECK_NEW_TRACK:
3686 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3687 queue_reply(&audio_queue, audio_check_new_track());
3688 break;
3690 case Q_AUDIO_DIR_SKIP:
3691 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3692 playlist_end = false;
3693 audio_initiate_dir_change(ev.data);
3694 break;
3696 case Q_AUDIO_FLUSH:
3697 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3698 audio_invalidate_tracks();
3699 break;
3701 case Q_AUDIO_TRACK_CHANGED:
3702 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3703 if (track_changed_callback)
3704 track_changed_callback(&curtrack_id3);
3705 track_changed = true;
3706 playlist_update_resume_info(audio_current_track());
3707 break;
3709 #ifndef SIMULATOR
3710 case SYS_USB_CONNECTED:
3711 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3712 if (playing)
3713 audio_stop_playback();
3714 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3715 usb_wait_for_disconnect(&audio_queue);
3716 break;
3717 #endif
3719 case SYS_TIMEOUT:
3720 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3721 break;
3723 default:
3724 //LOGFQUEUE("audio < default");
3725 break;
3726 } /* end switch */
3727 } /* end while */
3730 #ifdef ROCKBOX_HAS_LOGF
3731 static void audio_test_track_changed_event(struct mp3entry *id3)
3733 (void)id3;
3735 logf("tce:%s", id3->path);
3737 #endif
3739 /* Initialize the audio system - called from init() in main.c.
3740 * Last function because of all the references to internal symbols
3742 void audio_init(void)
3744 #ifdef PLAYBACK_VOICE
3745 static bool voicetagtrue = true;
3746 static struct mp3entry id3_voice;
3747 struct thread_entry *voice_thread_p = NULL;
3748 #endif
3749 struct thread_entry *audio_thread_p;
3751 /* Can never do this twice */
3752 if (audio_is_initialized)
3754 logf("audio: already initialized");
3755 return;
3758 logf("audio: initializing");
3760 /* Initialize queues before giving control elsewhere in case it likes
3761 to send messages. Thread creation will be delayed however so nothing
3762 starts running until ready if something yields such as talk_init. */
3763 #ifdef PLAYBACK_VOICE
3764 /* Take ownership of lock to prevent playback of anything before audio
3765 hardware is initialized - audio thread unlocks it after final init
3766 stage */
3767 semaphore_init(&sem_codecthread, 1, 0);
3768 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3769 #endif
3770 queue_init(&audio_queue, true);
3771 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3772 queue_init(&codec_queue, true);
3773 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3775 pcm_init();
3777 #ifdef ROCKBOX_HAS_LOGF
3778 audio_set_track_changed_event(audio_test_track_changed_event);
3779 #endif
3781 /* Initialize codec api. */
3782 ci.read_filebuf = codec_filebuf_callback;
3783 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3784 ci.get_codec_memory = codec_get_memory_callback;
3785 ci.request_buffer = codec_request_buffer_callback;
3786 ci.advance_buffer = codec_advance_buffer_callback;
3787 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3788 ci.request_next_track = codec_request_next_track_callback;
3789 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3790 ci.seek_buffer = codec_seek_buffer_callback;
3791 ci.seek_complete = codec_seek_complete_callback;
3792 ci.set_elapsed = codec_set_elapsed_callback;
3793 ci.set_offset = codec_set_offset_callback;
3794 ci.configure = codec_configure_callback;
3795 ci.discard_codec = codec_discard_codec_callback;
3797 /* Initialize voice codec api. */
3798 #ifdef PLAYBACK_VOICE
3799 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3800 memset(&id3_voice, 0, sizeof(id3_voice));
3801 ci_voice.read_filebuf = voice_filebuf_callback;
3802 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3803 ci_voice.get_codec_memory = voice_get_memory_callback;
3804 ci_voice.request_buffer = voice_request_buffer_callback;
3805 ci_voice.advance_buffer = voice_advance_buffer_callback;
3806 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3807 ci_voice.request_next_track = voice_request_next_track_callback;
3808 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3809 ci_voice.seek_buffer = voice_seek_buffer_callback;
3810 ci_voice.seek_complete = voice_do_nothing;
3811 ci_voice.set_elapsed = voice_set_elapsed_callback;
3812 ci_voice.set_offset = voice_set_offset_callback;
3813 ci_voice.configure = voice_configure_callback;
3814 ci_voice.discard_codec = voice_do_nothing;
3815 ci_voice.taginfo_ready = &voicetagtrue;
3816 ci_voice.id3 = &id3_voice;
3817 id3_voice.frequency = 11200;
3818 id3_voice.length = 1000000L;
3819 #endif
3821 /* initialize the buffer */
3822 filebuf = audiobuf;
3824 /* audio_reset_buffer must to know the size of voice buffer so init
3825 talk first */
3826 talk_init();
3828 codec_thread_p = create_thread(
3829 codec_thread, codec_stack, sizeof(codec_stack),
3830 CREATE_THREAD_FROZEN,
3831 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3832 IF_COP(, CPU));
3834 audio_thread_p = create_thread(audio_thread, audio_stack,
3835 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3836 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3837 IF_COP(, CPU));
3839 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
3840 sizeof(buffering_stack), CREATE_THREAD_FROZEN,
3841 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3842 IF_COP(, CPU, true));
3844 #ifdef PLAYBACK_VOICE
3845 /* TODO: Change this around when various speech codecs can be used */
3846 if (talk_voice_required())
3848 logf("Starting voice codec");
3849 queue_init(&voice_queue, true);
3850 voice_thread_p = create_thread(voice_thread, voice_stack,
3851 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3852 voice_thread_name
3853 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3855 #endif
3857 /* Set crossfade setting for next buffer init which should be about... */
3858 pcmbuf_crossfade_enable(global_settings.crossfade);
3860 /* ...now! Set up the buffers */
3861 audio_reset_buffer();
3863 buffering_init(filebuf, filebuflen);
3865 /* Probably safe to say */
3866 audio_is_initialized = true;
3868 sound_settings_apply();
3869 #ifdef HAVE_WM8758
3870 eq_hw_enable(global_settings.eq_hw_enabled);
3871 #endif
3872 #ifndef HAVE_FLASH_STORAGE
3873 audio_set_buffer_margin(global_settings.buffer_margin);
3874 #endif
3876 /* it's safe to let the threads run now */
3877 thread_thaw(codec_thread_p);
3878 #ifdef PLAYBACK_VOICE
3879 if (voice_thread_p)
3880 thread_thaw(voice_thread_p);
3881 #endif
3882 thread_thaw(audio_thread_p);
3883 thread_thaw(buffering_thread_p);
3884 } /* audio_init */