A patch by Robert Keevil that's been in the tracker way to long, fixes FS #6213:...
[Rockbox.git] / apps / playback.c
blob6b4b37170deb85a9207739768f4d6688e215d940
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 "logf.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 /* default point to start buffer refill */
92 #define AUDIO_DEFAULT_WATERMARK (1024*512)
93 /* amount of data to read in one read() call */
94 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
95 /* point at which the file buffer will fight for CPU time */
96 #define AUDIO_FILEBUF_CRITICAL (1024*128)
97 /* amount of guess-space to allow for codecs that must hunt and peck
98 * for their correct seeek target, 32k seems a good size */
99 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
101 /* macros to enable logf for queues
102 logging on SYS_TIMEOUT can be disabled */
103 #ifdef SIMULATOR
104 /* Define this for logf output of all queuing except SYS_TIMEOUT */
105 #define PLAYBACK_LOGQUEUES
106 /* Define this to logf SYS_TIMEOUT messages */
107 #define PLAYBACK_LOGQUEUES_SYS_TIMEOUT
108 #endif
110 #ifdef PLAYBACK_LOGQUEUES
111 #define LOGFQUEUE logf
112 #else
113 #define LOGFQUEUE(...)
114 #endif
116 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
117 #define LOGFQUEUE_SYS_TIMEOUT logf
118 #else
119 #define LOGFQUEUE_SYS_TIMEOUT(...)
120 #endif
123 /* Define one constant that includes recording related functionality */
124 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
125 #define AUDIO_HAVE_RECORDING
126 #endif
128 enum {
129 Q_AUDIO_PLAY = 1,
130 Q_AUDIO_STOP,
131 Q_AUDIO_PAUSE,
132 Q_AUDIO_SKIP,
133 Q_AUDIO_PRE_FF_REWIND,
134 Q_AUDIO_FF_REWIND,
135 Q_AUDIO_REBUFFER_SEEK,
136 Q_AUDIO_CHECK_NEW_TRACK,
137 Q_AUDIO_FLUSH,
138 Q_AUDIO_TRACK_CHANGED,
139 Q_AUDIO_DIR_SKIP,
140 Q_AUDIO_POSTINIT,
141 Q_AUDIO_FILL_BUFFER,
142 #if MEM > 8
143 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
144 #endif
145 Q_CODEC_REQUEST_COMPLETE,
146 Q_CODEC_REQUEST_FAILED,
148 Q_VOICE_PLAY,
149 Q_VOICE_STOP,
151 Q_CODEC_LOAD,
152 Q_CODEC_LOAD_DISK,
154 #ifdef AUDIO_HAVE_RECORDING
155 Q_ENCODER_LOAD_DISK,
156 Q_ENCODER_RECORD,
157 #endif
160 /* As defined in plugins/lib/xxx2wav.h */
161 #if MEM > 1
162 #define MALLOC_BUFSIZE (512*1024)
163 #define GUARD_BUFSIZE (32*1024)
164 #else
165 #define MALLOC_BUFSIZE (100*1024)
166 #define GUARD_BUFSIZE (8*1024)
167 #endif
169 /* As defined in plugin.lds */
170 #if defined(CPU_PP)
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
174 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
175 #define CODEC_IRAM_SIZE ((size_t)0x10000)
176 #else
177 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
178 #define CODEC_IRAM_SIZE ((size_t)0xc000)
179 #endif
181 #ifndef IBSS_ATTR_VOICE_STACK
182 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
183 #endif
185 bool audio_is_initialized = false;
187 /* Variables are commented with the threads that use them: *
188 * A=audio, C=codec, V=voice. A suffix of - indicates that *
189 * the variable is read but not updated on that thread. */
190 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
192 /* Main state control */
193 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
194 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
195 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
196 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
198 /* Ring buffer where compressed audio and codecs are loaded */
199 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
200 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
201 /* FIXME: make filebuflen static */
202 size_t filebuflen = 0; /* Size of buffer (A/C-) */
203 /* FIXME: make buf_ridx (C/A-) */
204 static volatile size_t buf_ridx IDATA_ATTR = 0; /* Buffer read position (A/C)*/
205 static volatile size_t buf_widx IDATA_ATTR = 0; /* Buffer write position (A/C-) */
207 /* Possible arrangements of the buffer */
208 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
209 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
210 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
211 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
213 /* Compressed ring buffer helper macros */
214 /* Buffer pointer (p) plus value (v), wrapped if necessary */
215 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
216 /* Buffer pointer (p) minus value (v), wrapped if necessary */
217 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
218 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
219 #define RINGBUF_ADD_CROSS(p1,v,p2) \
220 ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
221 /* Bytes available in the buffer */
222 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
224 /* Track info structure about songs in the file buffer (A/C-) */
225 static struct track_info tracks[MAX_TRACK];
226 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
227 static int track_widx = 0; /* Track being buffered (A) */
229 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
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;
239 /* Partially loaded track file handle to continue buffering (A) */
240 static int current_fd = -1;
242 /* Scrobbler support */
243 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
245 /* Track change controls */
246 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
247 static bool playlist_end = false; /* Has the current playlist ended? (A) */
248 static bool dir_skip = false; /* Is a directory skip pending? (A) */
249 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
250 /* Pending track change offset, to keep WPS responsive (A) */
251 static int wps_offset = 0;
253 /* Callbacks which applications or plugins may set */
254 /* When the playing track has changed from the user's perspective */
255 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
256 /* When a track has been buffered */
257 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
258 /* When a track's buffer has been overwritten or cleared */
259 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
261 /* Configuration */
262 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
263 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
264 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
265 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
266 static bool v1first = false; /* ID3 data control, true if V1 then V2 (A) */
267 #if MEM > 8
268 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
269 #endif
271 /* Multiple threads */
272 static void set_current_codec(int codec_idx);
273 /* Set the watermark to trigger buffer fill (A/C) FIXME */
274 static void set_filebuf_watermark(int seconds);
276 /* Audio thread */
277 static struct event_queue audio_queue;
278 static struct queue_sender_list audio_queue_sender_list;
279 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
280 static const char audio_thread_name[] = "audio";
282 static void audio_thread(void);
283 static void audio_initiate_track_change(long direction);
284 static bool audio_have_tracks(void);
285 static void audio_reset_buffer(void);
287 /* Codec thread */
288 extern struct codec_api ci;
289 static struct event_queue codec_queue NOCACHEBSS_ATTR;
290 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
291 IBSS_ATTR;
292 static const char codec_thread_name[] = "codec";
293 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
295 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
297 /* Voice thread */
298 #ifdef PLAYBACK_VOICE
300 extern struct codec_api ci_voice;
302 static struct thread_entry *voice_thread_p = NULL;
303 static struct event_queue voice_queue NOCACHEBSS_ATTR;
304 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
305 IBSS_ATTR_VOICE_STACK;
306 static const char voice_thread_name[] = "voice codec";
308 /* Voice codec swapping control */
309 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
311 #ifdef SIMULATOR
312 /* IRAM codec swap buffer for sim*/
313 static unsigned char sim_iram[CODEC_IRAM_SIZE];
314 #undef CODEC_IRAM_ORIGIN
315 #define CODEC_IRAM_ORIGIN sim_iram
316 #endif
318 /* iram_buf and dram_buf are either both NULL or both non-NULL */
319 /* Pointer to IRAM buffer for codec swapping */
320 static unsigned char *iram_buf = NULL;
321 /* Pointer to DRAM buffer for codec swapping */
322 static unsigned char *dram_buf = NULL;
323 /* Parity of swap_codec calls - needed because one codec swapping itself in
324 automatically swaps in the other and the swap when unlocking should not
325 happen if the parity is even.
327 static bool swap_codec_parity = false; /* true=odd, false=even */
328 /* Mutex to control which codec (normal/voice) is running */
329 static struct mutex mutex_codecthread NOCACHEBSS_ATTR;
331 /* Voice state */
332 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
333 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
334 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
335 static unsigned char *voicebuf = NULL;
336 static size_t voice_remaining = 0;
338 #ifdef IRAM_STEAL
339 /* Voice IRAM has been stolen for other use */
340 static bool voice_iram_stolen = false;
341 #endif
343 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
345 struct voice_info {
346 void (*callback)(unsigned char **start, size_t* size);
347 size_t size;
348 unsigned char *buf;
350 static void voice_thread(void);
351 static void voice_stop(void);
353 #endif /* PLAYBACK_VOICE */
355 /* --- External interfaces --- */
357 void mp3_play_data(const unsigned char* start, int size,
358 void (*get_more)(unsigned char** start, size_t* size))
360 #ifdef PLAYBACK_VOICE
361 static struct voice_info voice_clip;
362 voice_clip.callback = get_more;
363 voice_clip.buf = (unsigned char*)start;
364 voice_clip.size = size;
365 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
366 queue_post(&voice_queue, Q_VOICE_STOP, 0);
367 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
368 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
369 voice_thread_start = true;
370 trigger_cpu_boost();
371 #else
372 (void) start;
373 (void) size;
374 (void) get_more;
375 #endif
378 void mp3_play_stop(void)
380 #ifdef PLAYBACK_VOICE
381 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
382 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
383 queue_post(&voice_queue, Q_VOICE_STOP, 1);
384 #endif
387 void mp3_play_pause(bool play)
389 /* a dummy */
390 (void)play;
393 bool mp3_is_playing(void)
395 return voice_is_playing;
398 void mpeg_id3_options(bool _v1first)
400 v1first = _v1first;
403 /* If voice could be swapped out - wait for it to return
404 * Used by buffer claming functions.
406 static void wait_for_voice_swap_in(void)
408 #ifdef PLAYBACK_VOICE
409 if (NULL == iram_buf)
410 return;
412 while (current_codec != CODEC_IDX_VOICE)
413 yield();
414 #endif /* PLAYBACK_VOICE */
417 /* This sends a stop message and the audio thread will dump all it's
418 subsequenct messages */
419 static void audio_hard_stop(void)
421 /* Stop playback */
422 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
423 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
426 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
428 unsigned char *buf, *end;
430 if (audio_is_initialized)
432 audio_hard_stop();
433 wait_for_voice_swap_in();
434 voice_stop();
436 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
438 if (buffer_size == NULL)
440 /* Special case for talk_init to use since it already knows it's
441 trashed */
442 buffer_state = BUFFER_STATE_TRASHED;
443 return NULL;
446 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
447 || !talk_voice_required())
449 logf("get buffer: talk, audio");
450 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
451 the talk buffer is not needed because voice isn't being used, or
452 could be BUFFER_STATE_TRASHED already. If state is
453 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
454 without the caller knowing what's going on. Changing certain settings
455 may move it to a worse condition but the memory in use by something
456 else will remain undisturbed.
458 if (buffer_state != BUFFER_STATE_TRASHED)
460 talk_buffer_steal();
461 buffer_state = BUFFER_STATE_TRASHED;
464 buf = audiobuf;
465 end = audiobufend;
467 else
469 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
470 still BUFFER_STATE_INITIALIZED */
471 /* Skip talk buffer and move pcm buffer to end to maximize available
472 contiguous memory - no audio running means voice will not need the
473 swap space */
474 logf("get buffer: audio");
475 buf = audiobuf + talk_get_bufsize();
476 end = audiobufend - pcmbuf_init(audiobufend);
477 buffer_state = BUFFER_STATE_VOICED_ONLY;
480 *buffer_size = end - buf;
482 return buf;
485 #ifdef IRAM_STEAL
486 void audio_iram_steal(void)
488 /* We need to stop audio playback in order to use codec IRAM */
489 audio_hard_stop();
491 #ifdef PLAYBACK_VOICE
492 if (NULL != iram_buf)
494 /* Can't already be stolen */
495 if (voice_iram_stolen)
496 return;
498 /* Must wait for voice to be current again if it is swapped which
499 would cause the caller's buffer to get clobbered when voice locks
500 and runs - we'll wait for it to lock and yield again then make sure
501 the ride has come to a complete stop */
502 wait_for_voice_swap_in();
503 voice_stop();
505 /* Save voice IRAM but just memcpy - safe to do here since voice
506 is current and no audio codec is loaded */
507 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
508 voice_iram_stolen = true;
510 else
512 /* Nothing much to do if no voice */
513 voice_iram_stolen = false;
515 #endif
517 #endif /* IRAM_STEAL */
519 #ifdef HAVE_RECORDING
520 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
522 /* Don't allow overwrite of voice swap area or we'll trash the
523 swapped-out voice codec but can use whole thing if none */
524 unsigned char *end;
526 /* Stop audio and voice. Wait for voice to swap in and be clear
527 of pending events to ensure trouble-free operation of encoders */
528 audio_hard_stop();
529 wait_for_voice_swap_in();
530 voice_stop();
531 talk_buffer_steal();
533 #ifdef PLAYBACK_VOICE
534 /* If no dram_buf, swap space not used and recording gets more
535 memory. Codec swap areas will remain unaffected by the next init
536 since they're allocated at the end of the buffer and their sizes
537 don't change between calls */
538 end = dram_buf;
539 if (NULL == end)
540 #endif /* PLAYBACK_VOICE */
541 end = audiobufend;
543 buffer_state = BUFFER_STATE_TRASHED;
545 *buffer_size = end - audiobuf;
547 return (unsigned char *)audiobuf;
550 bool audio_load_encoder(int afmt)
552 #ifndef SIMULATOR
553 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
554 if (!enc_fn)
555 return false;
557 audio_remove_encoder();
558 ci.enc_codec_loaded = 0; /* clear any previous error condition */
560 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
561 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
563 while (ci.enc_codec_loaded == 0)
564 yield();
566 logf("codec loaded: %d", ci.enc_codec_loaded);
568 return ci.enc_codec_loaded > 0;
569 #else
570 (void)afmt;
571 return true;
572 #endif
573 } /* audio_load_encoder */
575 void audio_remove_encoder(void)
577 #ifndef SIMULATOR
578 /* force encoder codec unload (if currently loaded) */
579 if (ci.enc_codec_loaded <= 0)
580 return;
582 ci.stop_encoder = true;
583 while (ci.enc_codec_loaded > 0)
584 yield();
585 #endif
586 } /* audio_remove_encoder */
588 #endif /* HAVE_RECORDING */
590 struct mp3entry* audio_current_track(void)
592 const char *filename;
593 const char *p;
594 static struct mp3entry temp_id3;
595 int cur_idx;
596 int offset = ci.new_track + wps_offset;
598 cur_idx = track_ridx + offset;
599 cur_idx &= MAX_TRACK_MASK;
601 if (tracks[cur_idx].taginfo_ready)
602 return &tracks[cur_idx].id3;
604 memset(&temp_id3, 0, sizeof(struct mp3entry));
606 filename = playlist_peek(offset);
607 if (!filename)
608 filename = "No file!";
610 #ifdef HAVE_TC_RAMCACHE
611 if (tagcache_fill_tags(&temp_id3, filename))
612 return &temp_id3;
613 #endif
615 p = strrchr(filename, '/');
616 if (!p)
617 p = filename;
618 else
619 p++;
621 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
622 temp_id3.title = &temp_id3.path[0];
624 return &temp_id3;
627 struct mp3entry* audio_next_track(void)
629 int next_idx = track_ridx;
631 if (!audio_have_tracks())
632 return NULL;
634 next_idx++;
635 next_idx &= MAX_TRACK_MASK;
637 if (!tracks[next_idx].taginfo_ready)
638 return NULL;
640 return &tracks[next_idx].id3;
643 bool audio_has_changed_track(void)
645 if (track_changed)
647 track_changed = false;
648 return true;
651 return false;
654 void audio_play(long offset)
656 logf("audio_play");
658 #ifdef PLAYBACK_VOICE
659 /* Truncate any existing voice output so we don't have spelling
660 * etc. over the first part of the played track */
661 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
662 queue_post(&voice_queue, Q_VOICE_STOP, 1);
663 #endif
665 /* Start playback */
666 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
667 /* Don't return until playback has actually started */
668 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
671 void audio_stop(void)
673 /* Stop playback */
674 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
675 /* Don't return until playback has actually stopped */
676 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
679 void audio_pause(void)
681 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
682 /* Don't return until playback has actually paused */
683 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
686 void audio_resume(void)
688 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
689 /* Don't return until playback has actually resumed */
690 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
693 void audio_next(void)
695 if (playlist_check(ci.new_track + wps_offset + 1))
697 if (global_settings.beep)
698 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
700 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
701 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
702 /* Update wps while our message travels inside deep playback queues. */
703 wps_offset++;
704 track_changed = true;
706 else
708 /* No more tracks. */
709 if (global_settings.beep)
710 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
714 void audio_prev(void)
716 if (playlist_check(ci.new_track + wps_offset - 1))
718 if (global_settings.beep)
719 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
721 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
722 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
723 /* Update wps while our message travels inside deep playback queues. */
724 wps_offset--;
725 track_changed = true;
727 else
729 /* No more tracks. */
730 if (global_settings.beep)
731 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
735 void audio_next_dir(void)
737 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
738 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
741 void audio_prev_dir(void)
743 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
744 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
747 void audio_pre_ff_rewind(void)
749 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
750 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
753 void audio_ff_rewind(long newpos)
755 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
756 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
759 void audio_flush_and_reload_tracks(void)
761 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
762 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
765 void audio_error_clear(void)
767 #ifdef AUDIO_HAVE_RECORDING
768 pcm_rec_error_clear();
769 #endif
772 int audio_status(void)
774 int ret = 0;
776 if (playing)
777 ret |= AUDIO_STATUS_PLAY;
779 if (paused)
780 ret |= AUDIO_STATUS_PAUSE;
782 #ifdef HAVE_RECORDING
783 /* Do this here for constitency with mpeg.c version */
784 ret |= pcm_rec_status();
785 #endif
787 return ret;
790 int audio_get_file_pos(void)
792 return 0;
795 void audio_set_buffer_margin(int setting)
797 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
798 buffer_margin = lookup[setting];
799 logf("buffer margin: %ld", buffer_margin);
800 set_filebuf_watermark(buffer_margin);
803 /* Take nescessary steps to enable or disable the crossfade setting */
804 void audio_set_crossfade(int enable)
806 size_t offset;
807 bool was_playing;
808 size_t size;
810 /* Tell it the next setting to use */
811 pcmbuf_crossfade_enable(enable);
813 /* Return if size hasn't changed or this is too early to determine
814 which in the second case there's no way we could be playing
815 anything at all */
816 if (pcmbuf_is_same_size())
818 /* This function is a copout and just syncs some variables -
819 to be removed at a later date */
820 pcmbuf_crossfade_enable_finished();
821 return;
824 offset = 0;
825 was_playing = playing;
827 /* Playback has to be stopped before changing the buffer size */
828 if (was_playing)
830 /* Store the track resume position */
831 offset = CUR_TI->id3.offset;
832 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
835 /* Blast it - audio buffer will have to be setup again next time
836 something plays */
837 audio_get_buffer(true, &size);
839 /* Restart playback if audio was running previously */
840 if (was_playing)
841 audio_play(offset);
844 /* --- Routines called from multiple threads --- */
845 static void set_current_codec(int codec_idx)
847 current_codec = codec_idx;
848 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
851 #ifdef PLAYBACK_VOICE
852 static void swap_codec(void)
854 int my_codec;
856 /* Swap nothing if no swap buffers exist */
857 if (dram_buf == NULL)
859 logf("swap: no swap buffers");
860 return;
863 my_codec = current_codec;
865 logf("swapping out codec: %d", my_codec);
867 /* Invert this when a codec thread enters and leaves */
868 swap_codec_parity = !swap_codec_parity;
870 /* If this is true, an odd number of calls has occurred and there's
871 no codec thread waiting to swap us out when it locks and runs. This
872 occurs when playback is stopped or when just starting playback and
873 the audio thread is loading a codec; parities should always be even
874 on entry when a thread calls this during playback */
875 if (swap_codec_parity)
877 /* Save our current IRAM and DRAM */
878 #ifdef IRAM_STEAL
879 if (voice_iram_stolen)
881 logf("swap: iram restore");
882 voice_iram_stolen = false;
883 /* Don't swap trashed data into buffer as the voice IRAM will
884 already be swapped out - should _always_ be the case if
885 voice_iram_stolen is true since the voice has been swapped
886 in beforehand */
887 if (my_codec == CODEC_IDX_VOICE)
889 logf("voice iram already swapped");
890 goto skip_iram_swap;
893 #endif
895 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
897 #ifdef IRAM_STEAL
898 skip_iram_swap:
899 #endif
901 memswap128(dram_buf, codecbuf, CODEC_SIZE);
902 /* No cache invalidation needed; it will be done in codec_load_ram
903 or we won't be here otherwise */
906 /* Release my semaphore */
907 mutex_unlock(&mutex_codecthread);
908 logf("unlocked: %d", my_codec);
910 /* Loop until the other codec has locked and run */
911 do {
912 /* Release my semaphore and force a task switch. */
913 yield();
914 } while (my_codec == current_codec);
916 /* Wait for other codec to unlock */
917 /* FIXME: We need some sort of timed boost cancellation here or the CPU
918 doesn't unboost during playback when the voice codec goes back to
919 waiting - recall that mutex_lock calls block_thread which is an
920 indefinite wait that doesn't cancel the thread's CPU boost */
921 mutex_lock(&mutex_codecthread);
923 /* Take control */
924 logf("waiting for lock: %d", my_codec);
925 set_current_codec(my_codec);
927 /* Reload our IRAM and DRAM */
928 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
929 memswap128(dram_buf, codecbuf, CODEC_SIZE);
930 invalidate_icache();
932 /* Flip parity again */
933 swap_codec_parity = !swap_codec_parity;
935 logf("resuming codec: %d", my_codec);
938 /* This function is meant to be used by the buffer stealing functions to
939 ensure the codec is no longer active and so voice will be swapped-in
940 before it is called */
941 static void voice_stop(void)
943 #ifdef PLAYBACK_VOICE
944 /* Must have a voice codec loaded or we'll hang forever here */
945 if (!voice_codec_loaded)
946 return;
948 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
949 queue_post(&voice_queue, Q_VOICE_STOP, 0);
951 /* Loop until voice empties it's queue, stops and picks up on the new
952 track; the voice thread must be stopped and waiting for messages
953 outside the codec */
954 while (voice_is_playing || !queue_empty(&voice_queue) ||
955 ci_voice.new_track)
956 yield();
958 if (!playing)
959 pcmbuf_play_stop();
960 #endif
961 } /* voice_stop */
962 #endif /* PLAYBACK_VOICE */
964 static void set_filebuf_watermark(int seconds)
966 size_t bytes;
968 if (!filebuf)
969 return; /* Audio buffers not yet set up */
971 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
972 bytes = MIN(bytes, filebuflen / 2);
973 conf_watermark = bytes;
976 const char * get_codec_filename(int cod_spec)
978 const char *fname;
980 #ifdef HAVE_RECORDING
981 /* Can choose decoder or encoder if one available */
982 int type = cod_spec & CODEC_TYPE_MASK;
983 int afmt = cod_spec & CODEC_AFMT_MASK;
985 if ((unsigned)afmt >= AFMT_NUM_CODECS)
986 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
988 fname = (type == CODEC_TYPE_ENCODER) ?
989 audio_formats[afmt].codec_enc_root_fn :
990 audio_formats[afmt].codec_root_fn;
992 logf("%s: %d - %s",
993 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
994 afmt, fname ? fname : "<unknown>");
995 #else /* !HAVE_RECORDING */
996 /* Always decoder */
997 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
998 cod_spec = AFMT_UNKNOWN;
999 fname = audio_formats[cod_spec].codec_root_fn;
1000 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1001 #endif /* HAVE_RECORDING */
1003 return fname;
1004 } /* get_codec_filename */
1007 /* --- Voice thread --- */
1009 #ifdef PLAYBACK_VOICE
1011 static bool voice_pcmbuf_insert_callback(
1012 const void *ch1, const void *ch2, int count)
1014 const char *src[2] = { ch1, ch2 };
1016 while (count > 0)
1018 int out_count = dsp_output_count(count);
1019 int inp_count;
1020 char *dest;
1022 while ((dest = pcmbuf_request_voice_buffer(
1023 &out_count, playing)) == NULL)
1025 if (playing && audio_codec_loaded)
1026 swap_codec();
1027 else
1028 yield();
1031 /* Get the real input_size for output_size bytes, guarding
1032 * against resampling buffer overflows. */
1033 inp_count = dsp_input_count(out_count);
1035 if (inp_count <= 0)
1036 return true;
1038 /* Input size has grown, no error, just don't write more than length */
1039 if (inp_count > count)
1040 inp_count = count;
1042 out_count = dsp_process(dest, src, inp_count);
1044 if (out_count <= 0)
1045 return true;
1047 if (playing)
1049 pcmbuf_mix_voice(out_count);
1050 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1051 audio_codec_loaded)
1052 swap_codec();
1054 else
1055 pcmbuf_write_complete(out_count);
1057 count -= inp_count;
1060 return true;
1061 } /* voice_pcmbuf_insert_callback */
1063 static void* voice_get_memory_callback(size_t *size)
1065 /* Voice should have no use for this. If it did, we'd have to
1066 swap the malloc buffer as well. */
1067 *size = 0;
1068 return NULL;
1071 static void voice_set_elapsed_callback(unsigned int value)
1073 (void)value;
1076 static void voice_set_offset_callback(size_t value)
1078 (void)value;
1081 static void voice_configure_callback(int setting, intptr_t value)
1083 if (!dsp_configure(setting, value))
1085 logf("Illegal key:%d", setting);
1089 static size_t voice_filebuf_callback(void *ptr, size_t size)
1091 (void)ptr;
1092 (void)size;
1094 return 0;
1097 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1098 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1100 if (aborting && !playing && pcm_is_playing())
1102 /* Aborting: Slight hack - flush PCM buffer if
1103 only being used for voice */
1104 pcmbuf_play_stop();
1107 if (voice_is_playing)
1109 /* Clear the current buffer */
1110 voice_is_playing = false;
1111 voice_getmore = NULL;
1112 voice_remaining = 0;
1113 voicebuf = NULL;
1115 /* Force the codec to think it's changing tracks */
1116 ci_voice.new_track = 1;
1118 *realsize = 0;
1119 return true; /* Yes, change tracks */
1122 return false;
1125 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1127 struct event ev;
1129 if (ci_voice.new_track)
1131 *realsize = 0;
1132 return NULL;
1135 while (1)
1137 if (voice_is_playing || playing)
1139 queue_wait_w_tmo(&voice_queue, &ev, 0);
1140 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1141 ev.id = Q_AUDIO_PLAY;
1143 else
1145 /* We must use queue_wait_w_tmo() because queue_wait() doesn't
1146 unboost the CPU */
1147 /* FIXME: when long timeouts work correctly max out the the timeout
1148 (we'll still need the timeout guard here) or an infinite timeout
1149 can unboost, use that */
1151 queue_wait_w_tmo(&voice_queue, &ev, HZ*5);
1152 while (ev.id == SYS_TIMEOUT); /* Fake infinite wait */
1155 switch (ev.id) {
1156 case Q_AUDIO_PLAY:
1157 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1158 if (playing)
1160 if (audio_codec_loaded)
1161 swap_codec();
1162 yield();
1164 break;
1166 #ifdef AUDIO_HAVE_RECORDING
1167 case Q_ENCODER_RECORD:
1168 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1169 swap_codec();
1170 break;
1171 #endif
1173 case Q_VOICE_STOP:
1174 LOGFQUEUE("voice < Q_VOICE_STOP");
1175 if (voice_on_voice_stop(ev.data, realsize))
1176 return NULL;
1177 break;
1179 case SYS_USB_CONNECTED:
1181 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1182 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1183 /* Voice is obviously current so let us swap ourselves away if
1184 playing so audio may stop itself - audio_codec_loaded can
1185 only be true in this case if we're here even if the codec
1186 is only about to load */
1187 if (audio_codec_loaded)
1188 swap_codec();
1189 /* Playback should be finished by now - ack and wait */
1190 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1191 usb_wait_for_disconnect(&voice_queue);
1192 if (change_tracks)
1193 return NULL;
1194 break;
1197 case Q_VOICE_PLAY:
1198 LOGFQUEUE("voice < Q_VOICE_PLAY");
1199 if (!voice_is_playing)
1201 /* Set up new voice data */
1202 struct voice_info *voice_data;
1203 #ifdef IRAM_STEAL
1204 if (voice_iram_stolen)
1206 /* Voice is the first to run again and is currently
1207 loaded */
1208 logf("voice: iram restore");
1209 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1210 voice_iram_stolen = false;
1212 #endif
1213 /* Must reset the buffer before any playback begins if
1214 needed */
1215 if (buffer_state == BUFFER_STATE_TRASHED)
1216 audio_reset_buffer();
1218 voice_is_playing = true;
1219 trigger_cpu_boost();
1220 voice_data = (struct voice_info *)ev.data;
1221 voice_remaining = voice_data->size;
1222 voicebuf = voice_data->buf;
1223 voice_getmore = voice_data->callback;
1225 goto voice_play_clip; /* To exit both switch and while */
1227 case SYS_TIMEOUT:
1228 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1229 goto voice_play_clip;
1231 default:
1232 LOGFQUEUE("voice < default");
1236 voice_play_clip:
1238 if (voice_remaining == 0 || voicebuf == NULL)
1240 if (voice_getmore)
1241 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1243 /* If this clip is done */
1244 if (voice_remaining == 0)
1246 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1247 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1248 /* Force pcm playback. */
1249 if (!pcm_is_playing())
1250 pcmbuf_play_start();
1254 *realsize = MIN(voice_remaining, reqsize);
1256 if (*realsize == 0)
1257 return NULL;
1259 return voicebuf;
1260 } /* voice_request_buffer_callback */
1262 static void voice_advance_buffer_callback(size_t amount)
1264 amount = MIN(amount, voice_remaining);
1265 voicebuf += amount;
1266 voice_remaining -= amount;
1269 static void voice_advance_buffer_loc_callback(void *ptr)
1271 size_t amount = (size_t)ptr - (size_t)voicebuf;
1273 voice_advance_buffer_callback(amount);
1276 static off_t voice_mp3_get_filepos_callback(int newtime)
1278 (void)newtime;
1280 return 0;
1283 static void voice_do_nothing(void)
1285 return;
1288 static bool voice_seek_buffer_callback(size_t newpos)
1290 (void)newpos;
1292 return false;
1295 static bool voice_request_next_track_callback(void)
1297 ci_voice.new_track = 0;
1298 return true;
1301 static void voice_thread(void)
1303 logf("Loading voice codec");
1304 voice_codec_loaded = true;
1305 mutex_lock(&mutex_codecthread);
1306 set_current_codec(CODEC_IDX_VOICE);
1307 dsp_configure(DSP_RESET, 0);
1308 voice_remaining = 0;
1309 voice_getmore = NULL;
1311 /* FIXME: If we being starting the voice thread without reboot, the
1312 voice_queue could be full of old stuff and we must flush it. */
1313 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1315 logf("Voice codec finished");
1316 voice_codec_loaded = false;
1317 mutex_unlock(&mutex_codecthread);
1318 voice_thread_p = NULL;
1319 remove_thread(NULL);
1320 } /* voice_thread */
1322 #endif /* PLAYBACK_VOICE */
1324 /* --- Codec thread --- */
1325 static bool codec_pcmbuf_insert_callback(
1326 const void *ch1, const void *ch2, int count)
1328 const char *src[2] = { ch1, ch2 };
1330 while (count > 0)
1332 int out_count = dsp_output_count(count);
1333 int inp_count;
1334 char *dest;
1336 /* Prevent audio from a previous track from playing */
1337 if (ci.new_track || ci.stop_codec)
1338 return true;
1340 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1342 sleep(1);
1343 if (ci.seek_time || ci.new_track || ci.stop_codec)
1344 return true;
1347 /* Get the real input_size for output_size bytes, guarding
1348 * against resampling buffer overflows. */
1349 inp_count = dsp_input_count(out_count);
1351 if (inp_count <= 0)
1352 return true;
1354 /* Input size has grown, no error, just don't write more than length */
1355 if (inp_count > count)
1356 inp_count = count;
1358 out_count = dsp_process(dest, src, inp_count);
1360 if (out_count <= 0)
1361 return true;
1363 pcmbuf_write_complete(out_count);
1365 #ifdef PLAYBACK_VOICE
1366 if ((voice_is_playing || voice_thread_start)
1367 && pcm_is_playing() && voice_codec_loaded &&
1368 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1370 voice_thread_start = false;
1371 swap_codec();
1373 #endif
1375 count -= inp_count;
1378 return true;
1379 } /* codec_pcmbuf_insert_callback */
1381 static void* codec_get_memory_callback(size_t *size)
1383 *size = MALLOC_BUFSIZE;
1384 return malloc_buf;
1387 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1388 static void codec_pcmbuf_position_callback(size_t size)
1390 /* This is called from an ISR, so be quick */
1391 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1392 prev_ti->id3.elapsed;
1394 if (time >= prev_ti->id3.length)
1396 pcmbuf_set_position_callback(NULL);
1397 prev_ti->id3.elapsed = prev_ti->id3.length;
1399 else
1400 prev_ti->id3.elapsed = time;
1403 static void codec_set_elapsed_callback(unsigned int value)
1405 unsigned int latency;
1406 if (ci.seek_time)
1407 return;
1409 #ifdef AB_REPEAT_ENABLE
1410 ab_position_report(value);
1411 #endif
1413 latency = pcmbuf_get_latency();
1414 if (value < latency)
1415 CUR_TI->id3.elapsed = 0;
1416 else if (value - latency > CUR_TI->id3.elapsed ||
1417 value - latency < CUR_TI->id3.elapsed - 2)
1419 CUR_TI->id3.elapsed = value - latency;
1423 static void codec_set_offset_callback(size_t value)
1425 unsigned int latency;
1427 if (ci.seek_time)
1428 return;
1430 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1431 if (value < latency)
1432 CUR_TI->id3.offset = 0;
1433 else
1434 CUR_TI->id3.offset = value - latency;
1437 static void codec_advance_buffer_counters(size_t amount)
1439 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1440 ci.curpos += amount;
1441 CUR_TI->available -= amount;
1443 /* Start buffer filling as necessary. */
1444 if (!pcmbuf_is_lowdata() && !filling)
1446 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1448 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1449 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1454 /* copy up-to size bytes into ptr and return the actual size copied */
1455 static size_t codec_filebuf_callback(void *ptr, size_t size)
1457 char *buf = (char *)ptr;
1458 size_t copy_n;
1459 size_t part_n;
1461 if (ci.stop_codec || !playing)
1462 return 0;
1464 /* The ammount to copy is the lesser of the requested amount and the
1465 * amount left of the current track (both on disk and already loaded) */
1466 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1468 /* Nothing requested OR nothing left */
1469 if (copy_n == 0)
1470 return 0;
1472 /* Let the disk buffer catch fill until enough data is available */
1473 while (copy_n > CUR_TI->available)
1475 if (!filling)
1477 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1478 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1481 sleep(1);
1482 if (ci.stop_codec || ci.new_track)
1483 return 0;
1486 /* Copy as much as possible without wrapping */
1487 part_n = MIN(copy_n, filebuflen - buf_ridx);
1488 memcpy(buf, &filebuf[buf_ridx], part_n);
1489 /* Copy the rest in the case of a wrap */
1490 if (part_n < copy_n) {
1491 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1494 /* Update read and other position pointers */
1495 codec_advance_buffer_counters(copy_n);
1497 /* Return the actual amount of data copied to the buffer */
1498 return copy_n;
1499 } /* codec_filebuf_callback */
1501 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1503 size_t short_n, copy_n, buf_rem;
1505 if (!playing)
1507 *realsize = 0;
1508 return NULL;
1511 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1512 if (copy_n == 0)
1514 *realsize = 0;
1515 return NULL;
1518 while (copy_n > CUR_TI->available)
1520 if (!filling)
1522 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1523 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1526 sleep(1);
1527 if (ci.stop_codec || ci.new_track)
1529 *realsize = 0;
1530 return NULL;
1534 /* How much is left at the end of the file buffer before wrap? */
1535 buf_rem = filebuflen - buf_ridx;
1537 /* If we can't satisfy the request without wrapping */
1538 if (buf_rem < copy_n)
1540 /* How short are we? */
1541 short_n = copy_n - buf_rem;
1543 /* If we can fudge it with the guardbuf */
1544 if (short_n < GUARD_BUFSIZE)
1545 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1546 else
1547 copy_n = buf_rem;
1550 *realsize = copy_n;
1552 return (char *)&filebuf[buf_ridx];
1553 } /* codec_request_buffer_callback */
1555 static int get_codec_base_type(int type)
1557 switch (type) {
1558 case AFMT_MPA_L1:
1559 case AFMT_MPA_L2:
1560 case AFMT_MPA_L3:
1561 return AFMT_MPA_L3;
1564 return type;
1567 static void codec_advance_buffer_callback(size_t amount)
1569 if (amount > CUR_TI->available + CUR_TI->filerem)
1570 amount = CUR_TI->available + CUR_TI->filerem;
1572 while (amount > CUR_TI->available && filling)
1573 sleep(1);
1575 if (amount > CUR_TI->available)
1577 intptr_t result = Q_CODEC_REQUEST_FAILED;
1579 if (!ci.stop_codec)
1581 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1582 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1583 ci.curpos + amount);
1586 switch (result)
1588 case Q_CODEC_REQUEST_FAILED:
1589 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1590 ci.stop_codec = true;
1591 return;
1593 case Q_CODEC_REQUEST_COMPLETE:
1594 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1595 return;
1597 default:
1598 LOGFQUEUE("codec |< default");
1599 ci.stop_codec = true;
1600 return;
1604 codec_advance_buffer_counters(amount);
1606 codec_set_offset_callback(ci.curpos);
1609 static void codec_advance_buffer_loc_callback(void *ptr)
1611 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1613 codec_advance_buffer_callback(amount);
1616 /* Copied from mpeg.c. Should be moved somewhere else. */
1617 static int codec_get_file_pos(void)
1619 int pos = -1;
1620 struct mp3entry *id3 = audio_current_track();
1622 if (id3->vbr)
1624 if (id3->has_toc)
1626 /* Use the TOC to find the new position */
1627 unsigned int percent, remainder;
1628 int curtoc, nexttoc, plen;
1630 percent = (id3->elapsed*100)/id3->length;
1631 if (percent > 99)
1632 percent = 99;
1634 curtoc = id3->toc[percent];
1636 if (percent < 99)
1637 nexttoc = id3->toc[percent+1];
1638 else
1639 nexttoc = 256;
1641 pos = (id3->filesize/256)*curtoc;
1643 /* Use the remainder to get a more accurate position */
1644 remainder = (id3->elapsed*100)%id3->length;
1645 remainder = (remainder*100)/id3->length;
1646 plen = (nexttoc - curtoc)*(id3->filesize/256);
1647 pos += (plen/100)*remainder;
1649 else
1651 /* No TOC exists, estimate the new position */
1652 pos = (id3->filesize / (id3->length / 1000)) *
1653 (id3->elapsed / 1000);
1656 else if (id3->bitrate)
1657 pos = id3->elapsed * (id3->bitrate / 8);
1658 else
1659 return -1;
1661 pos += id3->first_frame_offset;
1663 /* Don't seek right to the end of the file so that we can
1664 transition properly to the next song */
1665 if (pos >= (int)(id3->filesize - id3->id3v1len))
1666 pos = id3->filesize - id3->id3v1len - 1;
1668 return pos;
1671 static off_t codec_mp3_get_filepos_callback(int newtime)
1673 off_t newpos;
1675 CUR_TI->id3.elapsed = newtime;
1676 newpos = codec_get_file_pos();
1678 return newpos;
1681 static void codec_seek_complete_callback(void)
1683 logf("seek_complete");
1684 if (pcm_is_paused())
1686 /* If this is not a seamless seek, clear the buffer */
1687 pcmbuf_play_stop();
1688 dsp_configure(DSP_FLUSH, 0);
1690 /* If playback was not 'deliberately' paused, unpause now */
1691 if (!paused)
1692 pcmbuf_pause(false);
1694 ci.seek_time = 0;
1697 static bool codec_seek_buffer_callback(size_t newpos)
1699 int difference;
1701 logf("codec_seek_buffer_callback");
1703 if (newpos >= CUR_TI->filesize)
1704 newpos = CUR_TI->filesize - 1;
1706 difference = newpos - ci.curpos;
1707 if (difference >= 0)
1709 /* Seeking forward */
1710 logf("seek: +%d", difference);
1711 codec_advance_buffer_callback(difference);
1712 return true;
1715 /* Seeking backward */
1716 difference = -difference;
1717 if (ci.curpos - difference < 0)
1718 difference = ci.curpos;
1720 /* We need to reload the song. */
1721 if (newpos < CUR_TI->start_pos)
1723 intptr_t result = Q_CODEC_REQUEST_FAILED;
1725 if (!ci.stop_codec)
1727 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1728 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1729 newpos);
1732 switch (result)
1734 case Q_CODEC_REQUEST_COMPLETE:
1735 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1736 return true;
1738 case Q_CODEC_REQUEST_FAILED:
1739 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1740 ci.stop_codec = true;
1741 return false;
1743 default:
1744 LOGFQUEUE("codec |< default");
1745 return false;
1749 /* Seeking inside buffer space. */
1750 logf("seek: -%d", difference);
1751 CUR_TI->available += difference;
1752 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1753 ci.curpos -= difference;
1755 return true;
1758 static void codec_configure_callback(int setting, intptr_t value)
1760 switch (setting) {
1761 case CODEC_SET_FILEBUF_WATERMARK:
1762 conf_watermark = value;
1763 set_filebuf_watermark(buffer_margin);
1764 break;
1766 case CODEC_SET_FILEBUF_CHUNKSIZE:
1767 conf_filechunk = value;
1768 break;
1770 case CODEC_SET_FILEBUF_PRESEEK:
1771 conf_preseek = value;
1772 break;
1774 default:
1775 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1779 static void codec_track_changed(void)
1781 automatic_skip = false;
1782 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1783 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1786 static void codec_pcmbuf_track_changed_callback(void)
1788 pcmbuf_set_position_callback(NULL);
1789 codec_track_changed();
1792 static void codec_discard_codec_callback(void)
1794 if (CUR_TI->has_codec)
1796 CUR_TI->has_codec = false;
1797 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1800 #if 0
1801 /* Check if a buffer desync has happened, log it and stop playback. */
1802 if (buf_ridx != CUR_TI->buf_idx)
1804 int offset = CUR_TI->buf_idx - buf_ridx;
1805 size_t new_used = FILEBUFUSED - offset;
1807 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1808 logf("Used off:%d",FILEBUFUSED - new_used);
1810 /* This is a fatal internal error and it's not safe to
1811 * continue playback. */
1812 ci.stop_codec = true;
1813 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1815 #endif
1818 static inline void codec_gapless_track_change(void) {
1819 /* callback keeps the progress bar moving while the pcmbuf empties */
1820 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1821 /* set the pcmbuf callback for when the track really changes */
1822 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1825 static inline void codec_crossfade_track_change(void) {
1826 /* Initiate automatic crossfade mode */
1827 pcmbuf_crossfade_init(false);
1828 /* Notify the wps that the track change starts now */
1829 codec_track_changed();
1832 static void codec_track_skip_done(bool was_manual)
1834 int crossfade_mode = global_settings.crossfade;
1836 /* Manual track change (always crossfade or flush audio). */
1837 if (was_manual)
1839 pcmbuf_crossfade_init(true);
1840 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1841 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1843 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1844 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1845 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1847 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1849 if (global_settings.playlist_shuffle)
1850 /* shuffle mode is on, so crossfade: */
1851 codec_crossfade_track_change();
1852 else
1853 /* shuffle mode is off, so do a gapless track change */
1854 codec_gapless_track_change();
1856 else
1857 /* normal crossfade: */
1858 codec_crossfade_track_change();
1860 else
1861 /* normal gapless playback. */
1862 codec_gapless_track_change();
1865 static bool codec_load_next_track(void)
1867 intptr_t result = Q_CODEC_REQUEST_FAILED;
1869 prev_track_elapsed = CUR_TI->id3.elapsed;
1871 if (ci.seek_time)
1872 codec_seek_complete_callback();
1874 #ifdef AB_REPEAT_ENABLE
1875 ab_end_of_track_report();
1876 #endif
1878 logf("Request new track");
1880 if (ci.new_track == 0)
1882 ci.new_track++;
1883 automatic_skip = true;
1886 if (!ci.stop_codec)
1888 trigger_cpu_boost();
1889 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1890 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1893 switch (result)
1895 case Q_CODEC_REQUEST_COMPLETE:
1896 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1897 codec_track_skip_done(!automatic_skip);
1898 return true;
1900 case Q_CODEC_REQUEST_FAILED:
1901 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1902 ci.new_track = 0;
1903 ci.stop_codec = true;
1904 return false;
1906 default:
1907 LOGFQUEUE("codec |< default");
1908 ci.stop_codec = true;
1909 return false;
1913 static bool codec_request_next_track_callback(void)
1915 int prev_codectype;
1917 if (ci.stop_codec || !playing)
1918 return false;
1920 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1922 if (!codec_load_next_track())
1923 return false;
1925 /* Check if the next codec is the same file. */
1926 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1928 logf("New track loaded");
1929 codec_discard_codec_callback();
1930 return true;
1932 else
1934 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1935 return false;
1939 static void codec_thread(void)
1941 struct event ev;
1942 int status;
1943 size_t wrap;
1945 while (1) {
1946 status = 0;
1947 queue_wait(&codec_queue, &ev);
1949 switch (ev.id) {
1950 case Q_CODEC_LOAD_DISK:
1951 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1952 audio_codec_loaded = true;
1953 #ifdef PLAYBACK_VOICE
1954 /* Don't sent messages to voice codec if it's already swapped
1955 out or it will never get this */
1956 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1958 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1959 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1961 mutex_lock(&mutex_codecthread);
1962 #endif
1963 set_current_codec(CODEC_IDX_AUDIO);
1964 ci.stop_codec = false;
1965 status = codec_load_file((const char *)ev.data, &ci);
1966 #ifdef PLAYBACK_VOICE
1967 mutex_unlock(&mutex_codecthread);
1968 #endif
1969 break ;
1971 case Q_CODEC_LOAD:
1972 LOGFQUEUE("codec < Q_CODEC_LOAD");
1973 if (!CUR_TI->has_codec) {
1974 logf("Codec slot is empty!");
1975 /* Wait for the pcm buffer to go empty */
1976 while (pcm_is_playing())
1977 yield();
1978 /* This must be set to prevent an infinite loop */
1979 ci.stop_codec = true;
1980 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1981 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1982 break ;
1985 audio_codec_loaded = true;
1986 #ifdef PLAYBACK_VOICE
1987 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1989 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1990 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1992 mutex_lock(&mutex_codecthread);
1993 #endif
1994 set_current_codec(CODEC_IDX_AUDIO);
1995 ci.stop_codec = false;
1996 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
1997 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
1998 &filebuf[0], wrap, &ci);
1999 #ifdef PLAYBACK_VOICE
2000 mutex_unlock(&mutex_codecthread);
2001 #endif
2002 break ;
2004 #ifdef AUDIO_HAVE_RECORDING
2005 case Q_ENCODER_LOAD_DISK:
2006 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2007 audio_codec_loaded = false; /* Not audio codec! */
2008 #ifdef PLAYBACK_VOICE
2009 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2011 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2012 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2014 mutex_lock(&mutex_codecthread);
2015 #endif
2016 logf("loading encoder");
2017 set_current_codec(CODEC_IDX_AUDIO);
2018 ci.stop_encoder = false;
2019 status = codec_load_file((const char *)ev.data, &ci);
2020 #ifdef PLAYBACK_VOICE
2021 mutex_unlock(&mutex_codecthread);
2022 #endif
2023 logf("encoder stopped");
2024 break;
2025 #endif /* AUDIO_HAVE_RECORDING */
2027 #ifndef SIMULATOR
2028 case SYS_USB_CONNECTED:
2029 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2030 queue_clear(&codec_queue);
2031 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2032 usb_wait_for_disconnect(&codec_queue);
2033 break;
2034 #endif
2036 default:
2037 LOGFQUEUE("codec < default");
2040 if (audio_codec_loaded)
2042 if (ci.stop_codec)
2044 status = CODEC_OK;
2045 if (!playing)
2046 pcmbuf_play_stop();
2049 audio_codec_loaded = false;
2052 switch (ev.id) {
2053 case Q_CODEC_LOAD_DISK:
2054 case Q_CODEC_LOAD:
2055 LOGFQUEUE("codec < Q_CODEC_LOAD");
2056 if (playing)
2058 if (ci.new_track || status != CODEC_OK)
2060 if (!ci.new_track)
2062 logf("Codec failure");
2063 gui_syncsplash(HZ*2, "Codec failure");
2066 if (!codec_load_next_track())
2068 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2069 /* End of playlist */
2070 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2071 break;
2074 else
2076 logf("Codec finished");
2077 if (ci.stop_codec)
2079 /* Wait for the audio to stop playing before
2080 * triggering the WPS exit */
2081 while(pcm_is_playing())
2083 CUR_TI->id3.elapsed =
2084 CUR_TI->id3.length - pcmbuf_get_latency();
2085 sleep(1);
2087 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2088 /* End of playlist */
2089 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2090 break;
2094 if (CUR_TI->has_codec)
2096 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2097 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2099 else
2101 const char *codec_fn =
2102 get_codec_filename(CUR_TI->id3.codectype);
2103 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2104 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2105 (intptr_t)codec_fn);
2108 break;
2110 #ifdef AUDIO_HAVE_RECORDING
2111 case Q_ENCODER_LOAD_DISK:
2112 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2114 if (status == CODEC_OK)
2115 break;
2117 logf("Encoder failure");
2118 gui_syncsplash(HZ*2, "Encoder failure");
2120 if (ci.enc_codec_loaded < 0)
2121 break;
2123 logf("Encoder failed to load");
2124 ci.enc_codec_loaded = -1;
2125 break;
2126 #endif /* AUDIO_HAVE_RECORDING */
2128 default:
2129 LOGFQUEUE("codec < default");
2131 } /* end switch */
2136 /* --- Audio thread --- */
2138 static bool audio_filebuf_is_lowdata(void)
2140 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
2143 static bool audio_have_tracks(void)
2145 return track_ridx != track_widx || CUR_TI->filesize;
2148 static bool audio_have_free_tracks(void)
2150 if (track_widx < track_ridx)
2151 return track_widx + 1 < track_ridx;
2152 else if (track_ridx == 0)
2153 return track_widx < MAX_TRACK - 1;
2155 return true;
2158 int audio_track_count(void)
2160 if (audio_have_tracks())
2162 int relative_track_widx = track_widx;
2164 if (track_ridx > track_widx)
2165 relative_track_widx += MAX_TRACK;
2167 return relative_track_widx - track_ridx + 1;
2170 return 0;
2173 long audio_filebufused(void)
2175 return (long) FILEBUFUSED;
2178 /* Count the data BETWEEN the selected tracks */
2179 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2181 size_t amount = 0;
2182 bool need_wrap = to_track < from_track;
2184 while (1)
2186 if (++from_track >= MAX_TRACK)
2188 from_track -= MAX_TRACK;
2189 need_wrap = false;
2192 if (from_track >= to_track && !need_wrap)
2193 break;
2195 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2197 return amount;
2200 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2202 size_t amount;
2204 /* Start with the remainder of the previously playing track */
2205 amount = tracks[old_track_ridx].filesize - ci.curpos;
2206 /* Then collect all data from tracks in between them */
2207 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2208 logf("bwf:%ldB", (long) amount);
2210 if (amount > FILEBUFUSED)
2211 return false;
2213 /* Wind the buffer to the beginning of the target track or its codec */
2214 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2216 return true;
2219 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2221 /* Available buffer data */
2222 size_t buf_back;
2223 /* Start with the previously playing track's data and our data */
2224 size_t amount;
2226 amount = ci.curpos;
2227 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2229 /* If we're not just resetting the current track */
2230 if (new_track_ridx != old_track_ridx)
2232 /* Need to wind to before the old track's codec and our filesize */
2233 amount += tracks[old_track_ridx].codecsize;
2234 amount += tracks[new_track_ridx].filesize;
2236 /* Rewind the old track to its beginning */
2237 tracks[old_track_ridx].available =
2238 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2241 /* If the codec was ever buffered */
2242 if (tracks[new_track_ridx].codecsize)
2244 /* Add the codec to the needed size */
2245 amount += tracks[new_track_ridx].codecsize;
2246 tracks[new_track_ridx].has_codec = true;
2249 /* Then collect all data from tracks between new and old */
2250 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2252 /* Do we have space to make this skip? */
2253 if (amount > buf_back)
2254 return false;
2256 logf("bwb:%ldB",amount);
2258 /* Rewind the buffer to the beginning of the target track or its codec */
2259 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2261 /* Reset to the beginning of the new track */
2262 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2264 return true;
2267 static void audio_update_trackinfo(void)
2269 ci.filesize = CUR_TI->filesize;
2270 CUR_TI->id3.elapsed = 0;
2271 CUR_TI->id3.offset = 0;
2272 ci.id3 = &CUR_TI->id3;
2273 ci.curpos = 0;
2274 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2277 /* Yield to codecs for as long as possible if they are in need of data
2278 * return true if the caller should break to let the audio thread process
2279 * new events */
2280 static bool audio_yield_codecs(void)
2282 yield();
2284 if (!queue_empty(&audio_queue))
2285 return true;
2287 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2288 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2290 if (filling)
2291 yield();
2292 else
2293 sleep(2);
2295 if (!queue_empty(&audio_queue))
2296 return true;
2299 return false;
2302 static void audio_clear_track_entries(bool clear_unbuffered)
2304 int cur_idx = track_widx;
2305 int last_idx = -1;
2307 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2309 /* Loop over all tracks from write-to-read */
2310 while (1)
2312 cur_idx++;
2313 cur_idx &= MAX_TRACK_MASK;
2315 if (cur_idx == track_ridx)
2316 break;
2318 /* If the track is buffered, conditionally clear/notify,
2319 * otherwise clear the track if that option is selected */
2320 if (tracks[cur_idx].event_sent)
2322 if (last_idx >= 0)
2324 /* If there is an unbuffer callback, call it, otherwise,
2325 * just clear the track */
2326 if (track_unbuffer_callback)
2327 track_unbuffer_callback(&tracks[last_idx].id3, false);
2329 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2331 last_idx = cur_idx;
2333 else if (clear_unbuffered)
2334 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2337 /* We clear the previous instance of a buffered track throughout
2338 * the above loop to facilitate 'last' detection. Clear/notify
2339 * the last track here */
2340 if (last_idx >= 0)
2342 if (track_unbuffer_callback)
2343 track_unbuffer_callback(&tracks[last_idx].id3, true);
2344 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2348 /* FIXME: This code should be made more generic and move to metadata.c */
2349 static void audio_strip_tags(void)
2351 int i;
2352 static const unsigned char tag[] = "TAG";
2353 static const unsigned char apetag[] = "APETAGEX";
2354 size_t tag_idx;
2355 size_t cur_idx;
2356 size_t len, version;
2358 tag_idx = RINGBUF_SUB(buf_widx, 128);
2360 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2362 cur_idx = tag_idx;
2363 for(i = 0;i < 3;i++)
2365 if(filebuf[cur_idx] != tag[i])
2366 goto strip_ape_tag;
2368 cur_idx = RINGBUF_ADD(cur_idx, 1);
2371 /* Skip id3v1 tag */
2372 logf("Skipping ID3v1 tag");
2373 buf_widx = tag_idx;
2374 tracks[track_widx].available -= 128;
2375 tracks[track_widx].filesize -= 128;
2378 strip_ape_tag:
2379 /* Check for APE tag (look for the APE tag footer) */
2380 tag_idx = RINGBUF_SUB(buf_widx, 32);
2382 if (FILEBUFUSED > 32 && tag_idx > buf_ridx)
2384 cur_idx = tag_idx;
2385 for(i = 0;i < 8;i++)
2387 if(filebuf[cur_idx] != apetag[i])
2388 return;
2390 cur_idx = RINGBUF_ADD(cur_idx, 1);
2393 /* Read the version and length from the footer */
2394 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2395 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2396 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2397 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2398 if (version == 2000)
2399 len += 32; /* APEv2 has a 32 byte header */
2401 /* Skip APE tag */
2402 if (FILEBUFUSED > len)
2404 logf("Skipping APE tag (%ldB)", len);
2405 buf_widx = RINGBUF_SUB(buf_widx, len);
2406 tracks[track_widx].available -= len;
2407 tracks[track_widx].filesize -= len;
2412 /* Returns true if a whole file is read, false otherwise */
2413 static bool audio_read_file(size_t minimum)
2415 bool ret_val = false;
2417 /* If we're called and no file is open, this is an error */
2418 if (current_fd < 0)
2420 logf("Bad fd in arf");
2421 /* Give some hope of miraculous recovery by forcing a track reload */
2422 tracks[track_widx].filesize = 0;
2423 /* Stop this buffering run */
2424 return ret_val;
2427 trigger_cpu_boost();
2428 while (tracks[track_widx].filerem > 0)
2430 size_t copy_n;
2431 int overlap;
2432 int rc;
2434 /* copy_n is the largest chunk that is safe to read */
2435 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2437 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2438 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2439 break;
2441 /* rc is the actual amount read */
2442 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2444 if (rc < 0)
2446 logf("File ended %ldB early", tracks[track_widx].filerem);
2447 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2448 tracks[track_widx].filerem = 0;
2449 break;
2452 /* How much of the playing track did we overwrite */
2453 if (buf_widx == CUR_TI->buf_idx)
2455 /* Special handling; zero or full overlap? */
2456 if (track_widx == track_ridx && CUR_TI->available == 0)
2457 overlap = 0;
2458 else
2459 overlap = rc;
2461 else
2462 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2464 if ((unsigned)rc > tracks[track_widx].filerem)
2466 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2467 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2468 tracks[track_widx].filerem = rc;
2471 /* Advance buffer */
2472 buf_widx = RINGBUF_ADD(buf_widx, rc);
2473 tracks[track_widx].available += rc;
2474 tracks[track_widx].filerem -= rc;
2476 /* If we write into the playing track, adjust it's buffer info */
2477 if (overlap > 0)
2479 CUR_TI->buf_idx += overlap;
2480 CUR_TI->start_pos += overlap;
2483 /* For a rebuffer, fill at least this minimum */
2484 if (minimum > (unsigned)rc)
2485 minimum -= rc;
2486 /* Let the codec process up to the watermark */
2487 /* Break immediately if this is a quick buffer, or there is an event */
2488 else if (minimum || audio_yield_codecs())
2490 /* Exit quickly, but don't stop the overall buffering process */
2491 ret_val = true;
2492 break;
2496 if (tracks[track_widx].filerem == 0)
2498 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2499 close(current_fd);
2500 current_fd = -1;
2501 audio_strip_tags();
2503 track_widx++;
2504 track_widx &= MAX_TRACK_MASK;
2506 tracks[track_widx].filesize = 0;
2507 return true;
2509 else
2511 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2512 tracks[track_widx].filesize - tracks[track_widx].filerem);
2513 return ret_val;
2517 static bool audio_loadcodec(bool start_play)
2519 size_t size = 0;
2520 int fd;
2521 int rc;
2522 size_t copy_n;
2523 int prev_track;
2524 char codec_path[MAX_PATH]; /* Full path to codec */
2526 const char * codec_fn =
2527 get_codec_filename(tracks[track_widx].id3.codectype);
2528 if (codec_fn == NULL)
2529 return false;
2531 tracks[track_widx].has_codec = false;
2533 if (start_play)
2535 /* Load the codec directly from disk and save some memory. */
2536 track_ridx = track_widx;
2537 ci.filesize = CUR_TI->filesize;
2538 ci.id3 = &CUR_TI->id3;
2539 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2540 ci.curpos = 0;
2541 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2542 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2543 return true;
2545 else
2547 /* If we already have another track than this one buffered */
2548 if (track_widx != track_ridx)
2550 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2552 /* If the previous codec is the same as this one, there is no need
2553 * to put another copy of it on the file buffer */
2554 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2555 get_codec_base_type(tracks[prev_track].id3.codectype)
2556 && audio_codec_loaded)
2558 logf("Reusing prev. codec");
2559 return true;
2564 codec_get_full_path(codec_path, codec_fn);
2566 fd = open(codec_path, O_RDONLY);
2567 if (fd < 0)
2569 logf("Codec doesn't exist!");
2570 return false;
2573 tracks[track_widx].codecsize = filesize(fd);
2575 /* Never load a partial codec */
2576 if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0)
2578 logf("Not enough space");
2579 close(fd);
2580 return false;
2583 while (size < tracks[track_widx].codecsize)
2585 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2586 rc = read(fd, &filebuf[buf_widx], copy_n);
2587 if (rc < 0)
2589 close(fd);
2590 /* This is an error condition, likely the codec file is corrupt */
2591 logf("Partial codec loaded");
2592 /* Must undo the buffer write of the partial codec */
2593 buf_widx = RINGBUF_SUB(buf_widx, size);
2594 tracks[track_widx].codecsize = 0;
2595 return false;
2598 buf_widx = RINGBUF_ADD(buf_widx, rc);
2600 size += rc;
2603 tracks[track_widx].has_codec = true;
2605 close(fd);
2606 logf("Done: %ldB", size);
2608 return true;
2611 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2612 static void audio_set_elapsed(struct mp3entry* id3)
2614 unsigned long offset = id3->offset > id3->first_frame_offset ?
2615 id3->offset - id3->first_frame_offset : 0;
2617 if ( id3->vbr ) {
2618 if ( id3->has_toc ) {
2619 /* calculate elapsed time using TOC */
2620 int i;
2621 unsigned int remainder, plen, relpos, nextpos;
2623 /* find wich percent we're at */
2624 for (i=0; i<100; i++ )
2625 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2626 break;
2628 i--;
2629 if (i < 0)
2630 i = 0;
2632 relpos = id3->toc[i];
2634 if (i < 99)
2635 nextpos = id3->toc[i+1];
2636 else
2637 nextpos = 256;
2639 remainder = offset - (relpos * (id3->filesize / 256));
2641 /* set time for this percent (divide before multiply to prevent
2642 overflow on long files. loss of precision is negligible on
2643 short files) */
2644 id3->elapsed = i * (id3->length / 100);
2646 /* calculate remainder time */
2647 plen = (nextpos - relpos) * (id3->filesize / 256);
2648 id3->elapsed += (((remainder * 100) / plen) *
2649 (id3->length / 10000));
2651 else {
2652 /* no TOC exists. set a rough estimate using average bitrate */
2653 int tpk = id3->length /
2654 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2655 1024);
2656 id3->elapsed = offset / 1024 * tpk;
2659 else
2661 /* constant bitrate, use exact calculation */
2662 if (id3->bitrate != 0)
2663 id3->elapsed = offset / (id3->bitrate / 8);
2667 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2669 char *trackname;
2670 off_t size;
2671 char msgbuf[80];
2673 /* Stop buffer filling if there is no free track entries.
2674 Don't fill up the last track entry (we wan't to store next track
2675 metadata there). */
2676 if (!audio_have_free_tracks())
2678 logf("No free tracks");
2679 return false;
2682 if (current_fd >= 0)
2684 logf("Nonzero fd in alt");
2685 close(current_fd);
2686 current_fd = -1;
2689 last_peek_offset++;
2690 peek_again:
2691 logf("Buffering track:%d/%d", track_widx, track_ridx);
2692 /* Get track name from current playlist read position. */
2693 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2695 /* Handle broken playlists. */
2696 current_fd = open(trackname, O_RDONLY);
2697 if (current_fd < 0)
2699 logf("Open failed");
2700 /* Skip invalid entry from playlist. */
2701 playlist_skip_entry(NULL, last_peek_offset);
2703 else
2704 break;
2707 if (!trackname)
2709 logf("End-of-playlist");
2710 playlist_end = true;
2711 return false;
2714 /* Initialize track entry. */
2715 size = filesize(current_fd);
2716 tracks[track_widx].filerem = size;
2717 tracks[track_widx].filesize = size;
2718 tracks[track_widx].available = 0;
2720 /* Set default values */
2721 if (start_play)
2723 int last_codec = current_codec;
2725 set_current_codec(CODEC_IDX_AUDIO);
2726 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2727 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2728 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2729 dsp_configure(DSP_RESET, 0);
2730 set_current_codec(last_codec);
2733 /* Get track metadata if we don't already have it. */
2734 if (!tracks[track_widx].taginfo_ready)
2736 if (get_metadata(&tracks[track_widx],current_fd,trackname,v1first))
2738 if (start_play)
2740 track_changed = true;
2741 playlist_update_resume_info(audio_current_track());
2744 else
2746 logf("mde:%s!",trackname);
2748 /* Set filesize to zero to indicate no file was loaded. */
2749 tracks[track_widx].filesize = 0;
2750 tracks[track_widx].filerem = 0;
2751 close(current_fd);
2752 current_fd = -1;
2754 /* Skip invalid entry from playlist. */
2755 playlist_skip_entry(NULL, last_peek_offset);
2756 tracks[track_widx].taginfo_ready = false;
2757 goto peek_again;
2762 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2764 char cuepath[MAX_PATH];
2766 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2768 if (look_for_cuesheet_file(trackname, cuepath) &&
2769 parse_cuesheet(cuepath, cue))
2771 strcpy((cue)->audio_filename, trackname);
2772 if (start_play)
2773 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2777 /* Load the codec. */
2778 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2779 if (!audio_loadcodec(start_play))
2781 /* Set filesize to zero to indicate no file was loaded. */
2782 tracks[track_widx].filesize = 0;
2783 tracks[track_widx].filerem = 0;
2784 close(current_fd);
2785 current_fd = -1;
2787 if (tracks[track_widx].codecsize)
2789 /* No space for codec on buffer, not an error */
2790 tracks[track_widx].codecsize = 0;
2791 return false;
2794 /* This is an error condition, either no codec was found, or reading
2795 * the codec file failed part way through, either way, skip the track */
2796 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2797 /* We should not use gui_syncplash from audio thread! */
2798 gui_syncsplash(HZ*2, msgbuf);
2799 /* Skip invalid entry from playlist. */
2800 playlist_skip_entry(NULL, last_peek_offset);
2801 tracks[track_widx].taginfo_ready = false;
2802 goto peek_again;
2805 tracks[track_widx].start_pos = 0;
2806 set_filebuf_watermark(buffer_margin);
2807 tracks[track_widx].id3.elapsed = 0;
2809 if (offset > 0)
2811 switch (tracks[track_widx].id3.codectype) {
2812 case AFMT_MPA_L1:
2813 case AFMT_MPA_L2:
2814 case AFMT_MPA_L3:
2815 lseek(current_fd, offset, SEEK_SET);
2816 tracks[track_widx].id3.offset = offset;
2817 audio_set_elapsed(&tracks[track_widx].id3);
2818 tracks[track_widx].filerem = size - offset;
2819 ci.curpos = offset;
2820 tracks[track_widx].start_pos = offset;
2821 break;
2823 case AFMT_WAVPACK:
2824 lseek(current_fd, offset, SEEK_SET);
2825 tracks[track_widx].id3.offset = offset;
2826 tracks[track_widx].id3.elapsed =
2827 tracks[track_widx].id3.length / 2;
2828 tracks[track_widx].filerem = size - offset;
2829 ci.curpos = offset;
2830 tracks[track_widx].start_pos = offset;
2831 break;
2833 case AFMT_OGG_VORBIS:
2834 case AFMT_SPEEX:
2835 case AFMT_FLAC:
2836 case AFMT_PCM_WAV:
2837 case AFMT_A52:
2838 case AFMT_AAC:
2839 case AFMT_MPC:
2840 case AFMT_APE:
2841 tracks[track_widx].id3.offset = offset;
2842 break;
2846 logf("alt:%s", trackname);
2847 tracks[track_widx].buf_idx = buf_widx;
2849 return audio_read_file(rebuffer);
2852 static bool audio_read_next_metadata(void)
2854 int fd;
2855 char *trackname;
2856 int next_idx;
2857 int status;
2859 next_idx = track_widx;
2860 if (tracks[next_idx].taginfo_ready)
2862 next_idx++;
2863 next_idx &= MAX_TRACK_MASK;
2865 if (tracks[next_idx].taginfo_ready)
2866 return true;
2869 trackname = playlist_peek(last_peek_offset + 1);
2870 if (!trackname)
2871 return false;
2873 fd = open(trackname, O_RDONLY);
2874 if (fd < 0)
2875 return false;
2877 status = get_metadata(&tracks[next_idx],fd,trackname,v1first);
2878 /* Preload the glyphs in the tags */
2879 if (status)
2881 if (tracks[next_idx].id3.title)
2882 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2883 if (tracks[next_idx].id3.artist)
2884 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2885 if (tracks[next_idx].id3.album)
2886 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2888 close(fd);
2890 return status;
2893 /* Send callback events to notify about new tracks. */
2894 static void audio_generate_postbuffer_events(void)
2896 int cur_idx;
2897 int last_idx = -1;
2899 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2901 if (audio_have_tracks())
2903 cur_idx = track_ridx;
2905 while (1) {
2906 if (!tracks[cur_idx].event_sent)
2908 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2910 /* Mark the event 'sent' even if we don't really send one */
2911 tracks[last_idx].event_sent = true;
2912 if (track_buffer_callback)
2913 track_buffer_callback(&tracks[last_idx].id3, false);
2915 last_idx = cur_idx;
2917 if (cur_idx == track_widx)
2918 break;
2919 cur_idx++;
2920 cur_idx &= MAX_TRACK_MASK;
2923 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2925 tracks[last_idx].event_sent = true;
2926 if (track_buffer_callback)
2927 track_buffer_callback(&tracks[last_idx].id3, true);
2932 static bool audio_initialize_buffer_fill(bool clear_tracks)
2934 /* Don't initialize if we're already initialized */
2935 if (filling)
2936 return true;
2938 logf("Starting buffer fill");
2940 /* Set the filling flag true before calling audio_clear_tracks as that
2941 * function can yield and we start looping. */
2942 filling = true;
2944 if (clear_tracks)
2945 audio_clear_track_entries(false);
2947 /* Save the current resume position once. */
2948 playlist_update_resume_info(audio_current_track());
2950 return true;
2953 static void audio_fill_file_buffer(
2954 bool start_play, bool rebuffer, size_t offset)
2956 bool had_next_track = audio_next_track() != NULL;
2957 bool continue_buffering;
2959 /* Must reset the buffer before use if trashed or voice only - voice
2960 file size shouldn't have changed so we can go straight from
2961 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2962 if (buffer_state != BUFFER_STATE_INITIALIZED)
2963 audio_reset_buffer();
2965 if (!audio_initialize_buffer_fill(!start_play))
2966 return ;
2968 /* If we have a partially buffered track, continue loading,
2969 * otherwise load a new track */
2970 if (tracks[track_widx].filesize > 0)
2971 continue_buffering = audio_read_file(rebuffer);
2972 else
2973 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2975 if (!had_next_track && audio_next_track())
2976 track_changed = true;
2978 /* If we're done buffering */
2979 if (!continue_buffering)
2981 audio_read_next_metadata();
2983 audio_generate_postbuffer_events();
2984 filling = false;
2986 #ifndef SIMULATOR
2987 ata_sleep();
2988 #endif
2992 static void audio_rebuffer(void)
2994 logf("Forcing rebuffer");
2996 /* Stop in progress fill, and clear open file descriptor */
2997 if (current_fd >= 0)
2999 close(current_fd);
3000 current_fd = -1;
3002 filling = false;
3004 /* Reset buffer and track pointers */
3005 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3006 track_widx = track_ridx;
3007 audio_clear_track_entries(true);
3008 CUR_TI->available = 0;
3010 /* Fill the buffer */
3011 last_peek_offset = -1;
3012 CUR_TI->filesize = 0;
3013 CUR_TI->start_pos = 0;
3014 ci.curpos = 0;
3016 if (!CUR_TI->taginfo_ready)
3017 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
3019 audio_fill_file_buffer(false, true, 0);
3022 static int audio_check_new_track(void)
3024 int track_count = audio_track_count();
3025 int old_track_ridx = track_ridx;
3026 bool forward;
3028 if (dir_skip)
3030 dir_skip = false;
3031 if (playlist_next_dir(ci.new_track))
3033 ci.new_track = 0;
3034 CUR_TI->taginfo_ready = false;
3035 audio_rebuffer();
3036 goto skip_done;
3038 else
3040 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3041 return Q_CODEC_REQUEST_FAILED;
3045 if (new_playlist)
3046 ci.new_track = 0;
3048 /* If the playlist isn't that big */
3049 if (!playlist_check(ci.new_track))
3051 if (ci.new_track >= 0)
3053 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3054 return Q_CODEC_REQUEST_FAILED;
3056 /* Find the beginning backward if the user over-skips it */
3057 while (!playlist_check(++ci.new_track))
3058 if (ci.new_track >= 0)
3060 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3061 return Q_CODEC_REQUEST_FAILED;
3064 /* Update the playlist */
3065 last_peek_offset -= ci.new_track;
3067 if (playlist_next(ci.new_track) < 0)
3069 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3070 return Q_CODEC_REQUEST_FAILED;
3073 if (new_playlist)
3075 ci.new_track = 1;
3076 new_playlist = false;
3079 /* Save the old track */
3080 prev_ti = CUR_TI;
3082 /* Move to the new track */
3083 track_ridx += ci.new_track;
3084 track_ridx &= MAX_TRACK_MASK;
3086 if (automatic_skip)
3087 playlist_end = false;
3089 track_changed = !automatic_skip;
3091 /* If it is not safe to even skip this many track entries */
3092 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3094 ci.new_track = 0;
3095 CUR_TI->taginfo_ready = false;
3096 audio_rebuffer();
3097 goto skip_done;
3100 forward = ci.new_track > 0;
3101 ci.new_track = 0;
3103 /* If the target track is clearly not in memory */
3104 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3106 audio_rebuffer();
3107 goto skip_done;
3110 /* The track may be in memory, see if it really is */
3111 if (forward)
3113 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3114 audio_rebuffer();
3116 else
3118 int cur_idx = track_ridx;
3119 bool taginfo_ready = true;
3120 bool wrap = track_ridx > old_track_ridx;
3122 while (1)
3124 cur_idx++;
3125 cur_idx &= MAX_TRACK_MASK;
3126 if (!(wrap || cur_idx < old_track_ridx))
3127 break;
3129 /* If we hit a track in between without valid tag info, bail */
3130 if (!tracks[cur_idx].taginfo_ready)
3132 taginfo_ready = false;
3133 break;
3136 tracks[cur_idx].available = tracks[cur_idx].filesize;
3137 if (tracks[cur_idx].codecsize)
3138 tracks[cur_idx].has_codec = true;
3140 if (taginfo_ready)
3142 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3143 audio_rebuffer();
3145 else
3147 CUR_TI->taginfo_ready = false;
3148 audio_rebuffer();
3152 skip_done:
3153 audio_update_trackinfo();
3154 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3155 return Q_CODEC_REQUEST_COMPLETE;
3158 static int audio_rebuffer_and_seek(size_t newpos)
3160 size_t real_preseek;
3161 int fd;
3162 char *trackname;
3164 /* (Re-)open current track's file handle. */
3165 trackname = playlist_peek(0);
3166 fd = open(trackname, O_RDONLY);
3167 if (fd < 0)
3169 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3170 return Q_CODEC_REQUEST_FAILED;
3173 if (current_fd >= 0)
3174 close(current_fd);
3175 current_fd = fd;
3177 playlist_end = false;
3179 ci.curpos = newpos;
3181 /* Clear codec buffer. */
3182 track_widx = track_ridx;
3183 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3185 last_peek_offset = 0;
3186 filling = false;
3187 audio_initialize_buffer_fill(true);
3189 /* This may have been tweaked by the id3v1 code */
3190 CUR_TI->filesize=filesize(fd);
3191 if (newpos > conf_preseek)
3193 CUR_TI->start_pos = newpos - conf_preseek;
3194 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3195 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3196 real_preseek = conf_preseek;
3198 else
3200 CUR_TI->start_pos = 0;
3201 CUR_TI->filerem = CUR_TI->filesize;
3202 real_preseek = newpos;
3205 CUR_TI->available = 0;
3207 audio_read_file(real_preseek);
3209 /* Account for the data we just read that is 'behind' us now */
3210 CUR_TI->available -= real_preseek;
3212 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3214 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3215 return Q_CODEC_REQUEST_COMPLETE;
3218 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3219 bool last_track))
3221 track_buffer_callback = handler;
3224 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3225 bool last_track))
3227 track_unbuffer_callback = handler;
3230 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3232 track_changed_callback = handler;
3235 unsigned long audio_prev_elapsed(void)
3237 return prev_track_elapsed;
3240 static void audio_stop_codec_flush(void)
3242 ci.stop_codec = true;
3243 pcmbuf_pause(true);
3245 while (audio_codec_loaded)
3246 yield();
3248 /* If the audio codec is not loaded any more, and the audio is still
3249 * playing, it is now and _only_ now safe to call this function from the
3250 * audio thread */
3251 if (pcm_is_playing())
3252 pcmbuf_play_stop();
3253 pcmbuf_pause(paused);
3256 static void audio_stop_playback(void)
3258 /* If we were playing, save resume information */
3259 if (playing)
3261 struct mp3entry *id3 = NULL;
3263 if (!playlist_end || !ci.stop_codec)
3265 /* Set this early, the outside code yields and may allow the codec
3266 to try to wait for a reply on a buffer wait */
3267 ci.stop_codec = true;
3268 id3 = audio_current_track();
3271 /* Save the current playing spot, or NULL if the playlist has ended */
3272 playlist_update_resume_info(id3);
3274 prev_track_elapsed = CUR_TI->id3.elapsed;
3276 /* Increment index so runtime info is saved in audio_clear_track_entries().
3277 * Done here, as audio_stop_playback() may be called more than once.
3278 * Don't update runtime unless playback is stopped because of end of playlist.
3279 * Updating runtime when manually stopping a tracks, can destroy autoscores
3280 * and playcounts.
3282 if (playlist_end)
3284 track_ridx++;
3285 track_ridx &= MAX_TRACK_MASK;
3289 filling = false;
3290 paused = false;
3291 audio_stop_codec_flush();
3292 playing = false;
3294 if (current_fd >= 0)
3296 close(current_fd);
3297 current_fd = -1;
3300 /* Mark all entries null. */
3301 audio_clear_track_entries(false);
3304 static void audio_play_start(size_t offset)
3306 #if INPUT_SRC_CAPS != 0
3307 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3308 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3309 #endif
3311 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3312 paused = false;
3313 audio_stop_codec_flush();
3315 track_changed = true;
3316 playlist_end = false;
3318 playing = true;
3320 ci.new_track = 0;
3321 ci.seek_time = 0;
3322 wps_offset = 0;
3324 if (current_fd >= 0)
3326 close(current_fd);
3327 current_fd = -1;
3330 sound_set_volume(global_settings.volume);
3331 track_widx = track_ridx = 0;
3332 buf_ridx = buf_widx = 0;
3334 /* Mark all entries null. */
3335 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3337 last_peek_offset = -1;
3339 /* Officially playing */
3340 queue_reply(&audio_queue, 1);
3342 audio_fill_file_buffer(true, false, offset);
3346 /* Invalidates all but currently playing track. */
3347 static void audio_invalidate_tracks(void)
3349 if (audio_have_tracks()) {
3350 last_peek_offset = 0;
3352 playlist_end = false;
3353 track_widx = track_ridx;
3354 /* Mark all other entries null (also buffered wrong metadata). */
3355 audio_clear_track_entries(true);
3357 /* If the current track is fully buffered, advance the write pointer */
3358 if (tracks[track_widx].filerem == 0)
3359 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3361 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3363 audio_read_next_metadata();
3367 static void audio_new_playlist(void)
3369 /* Prepare to start a new fill from the beginning of the playlist */
3370 last_peek_offset = -1;
3371 if (audio_have_tracks()) {
3372 playlist_end = false;
3373 track_widx = track_ridx;
3374 audio_clear_track_entries(true);
3376 track_widx++;
3377 track_widx &= MAX_TRACK_MASK;
3379 /* Stop reading the current track */
3380 CUR_TI->filerem = 0;
3381 close(current_fd);
3382 current_fd = -1;
3384 /* Mark the current track as invalid to prevent skipping back to it */
3385 CUR_TI->taginfo_ready = false;
3387 /* Invalidate the buffer other than the playing track */
3388 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3391 /* Signal the codec to initiate a track change forward */
3392 new_playlist = true;
3393 ci.new_track = 1;
3395 /* Officially playing */
3396 queue_reply(&audio_queue, 1);
3398 audio_fill_file_buffer(false, true, 0);
3401 static void audio_initiate_track_change(long direction)
3403 playlist_end = false;
3404 ci.new_track += direction;
3405 wps_offset -= direction;
3408 static void audio_initiate_dir_change(long direction)
3410 playlist_end = false;
3411 dir_skip = true;
3412 ci.new_track = direction;
3416 * Layout audio buffer as follows - iram buffer depends on target:
3417 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3419 static void audio_reset_buffer(void)
3421 /* see audio_get_recording_buffer if this is modified */
3422 logf("audio_reset_buffer");
3424 /* If the setup of anything allocated before the file buffer is
3425 changed, do check the adjustments after the buffer_alloc call
3426 as it will likely be affected and need sliding over */
3428 /* Initially set up file buffer as all space available */
3429 malloc_buf = audiobuf + talk_get_bufsize();
3430 /* Align the malloc buf to line size. Especially important to cf
3431 targets that do line reads/writes. */
3432 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3433 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3434 filebuflen = audiobufend - filebuf;
3436 /* Allow for codec swap space at end of audio buffer */
3437 if (talk_voice_required())
3439 /* Layout of swap buffer:
3440 * #ifdef IRAM_STEAL (dedicated iram_buf):
3441 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3442 * #else:
3443 * audiobuf...|dram_buf|iram_buf|audiobufend
3445 #ifdef PLAYBACK_VOICE
3446 /* Check for an absolutely nasty situation which should never,
3447 ever happen - frankly should just panic */
3448 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3450 logf("buffer reset with voice swapped");
3452 /* line align length which line aligns the calculations below since
3453 all sizes are also at least line aligned - needed for memswap128 */
3454 filebuflen &= ~15;
3455 #ifdef IRAM_STEAL
3456 filebuflen -= CODEC_SIZE;
3457 #else
3458 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3459 #endif
3460 /* Allocate buffers for swapping voice <=> audio */
3461 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3462 and out of the way of buffer usage or else a call to audio_get_buffer
3463 and subsequent buffer use might trash the swap space. A plugin
3464 initializing IRAM after getting the full buffer would present similar
3465 problem. Options include: failing the request if the other buffer
3466 has been obtained already or never allowing use of the voice IRAM
3467 buffer within the audio buffer. Using buffer_alloc basically
3468 implements the second in a more convenient way. */
3469 dram_buf = filebuf + filebuflen;
3471 #ifdef IRAM_STEAL
3472 /* Allocate voice IRAM swap buffer once */
3473 if (iram_buf == NULL)
3475 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3476 /* buffer_alloc moves audiobuf; this is safe because only the end
3477 * has been touched so far in this function and the address of
3478 * filebuf + filebuflen is not changed */
3479 malloc_buf += CODEC_IRAM_SIZE;
3480 filebuf += CODEC_IRAM_SIZE;
3481 filebuflen -= CODEC_IRAM_SIZE;
3483 #else
3484 /* Allocate iram_buf after dram_buf */
3485 iram_buf = dram_buf + CODEC_SIZE;
3486 #endif /* IRAM_STEAL */
3487 #endif /* PLAYBACK_VOICE */
3489 else
3491 #ifdef PLAYBACK_VOICE
3492 /* No swap buffers needed */
3493 iram_buf = NULL;
3494 dram_buf = NULL;
3495 #endif
3498 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3499 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3501 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3502 will already be line aligned */
3503 filebuflen &= ~3;
3505 /* Set the high watermark as 75% full...or 25% empty :) */
3506 #if MEM > 8
3507 high_watermark = 3*filebuflen / 4;
3508 #endif
3510 /* Clear any references to the file buffer */
3511 buffer_state = BUFFER_STATE_INITIALIZED;
3513 #ifdef ROCKBOX_HAS_LOGF
3514 /* Make sure everything adds up - yes, some info is a bit redundant but
3515 aids viewing and the sumation of certain variables should add up to
3516 the location of others. */
3518 size_t pcmbufsize;
3519 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3520 logf("mabuf: %08X", (unsigned)malloc_buf);
3521 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3522 logf("fbuf: %08X", (unsigned)filebuf);
3523 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3524 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3525 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3526 logf("pcmb: %08X", (unsigned)pcmbuf);
3527 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3528 if (dram_buf)
3530 logf("dramb: %08X", (unsigned)dram_buf);
3531 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3533 if (iram_buf)
3535 logf("iramb: %08X", (unsigned)iram_buf);
3536 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3539 #endif
3542 #if MEM > 8
3543 /* we dont want this rebuffering on targets with little ram
3544 because the disk may never spin down */
3545 static bool ata_fillbuffer_callback(void)
3547 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3548 return true;
3550 #endif
3552 static void audio_thread(void)
3554 struct event ev;
3556 pcm_postinit();
3558 #ifdef PLAYBACK_VOICE
3559 /* Unlock mutex that init stage locks before creating this thread */
3560 mutex_unlock(&mutex_codecthread);
3562 /* Buffers must be set up by now - should panic - really */
3563 if (buffer_state != BUFFER_STATE_INITIALIZED)
3565 logf("audio_thread start: no buffer");
3568 /* Have to wait for voice to load up or else the codec swap will be
3569 invalid when an audio codec is loaded */
3570 wait_for_voice_swap_in();
3571 #endif
3573 while (1)
3575 intptr_t result = 0;
3577 if (filling)
3579 queue_wait_w_tmo(&audio_queue, &ev, 0);
3580 if (ev.id == SYS_TIMEOUT)
3581 ev.id = Q_AUDIO_FILL_BUFFER;
3583 else
3585 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3586 #if MEM > 8
3587 if (playing && (ev.id == SYS_TIMEOUT) &&
3588 (FILEBUFUSED < high_watermark))
3589 register_ata_idle_func(ata_fillbuffer_callback);
3590 #endif
3593 switch (ev.id) {
3594 #if MEM > 8
3595 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3596 /* only fill if the disk is still spining */
3597 #ifndef SIMULATOR
3598 if (!ata_disk_is_active())
3599 break;
3600 #endif
3601 #endif /* MEM > 8 */
3602 /* else fall through to Q_AUDIO_FILL_BUFFER */
3603 case Q_AUDIO_FILL_BUFFER:
3604 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3605 if (!filling)
3606 if (!playing || playlist_end || ci.stop_codec)
3607 break;
3608 audio_fill_file_buffer(false, false, 0);
3609 break;
3611 case Q_AUDIO_PLAY:
3612 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3613 if (playing && ev.data <= 0)
3614 audio_new_playlist();
3615 else
3617 audio_stop_playback();
3618 audio_play_start((size_t)ev.data);
3620 break ;
3622 case Q_AUDIO_STOP:
3623 LOGFQUEUE("audio < Q_AUDIO_STOP");
3624 if (playing)
3625 audio_stop_playback();
3626 if (ev.data != 0)
3627 queue_clear(&audio_queue);
3628 break ;
3630 case Q_AUDIO_PAUSE:
3631 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3632 if (!playing)
3633 break;
3634 pcmbuf_pause((bool)ev.data);
3635 paused = (bool)ev.data;
3636 break ;
3638 case Q_AUDIO_SKIP:
3639 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3640 audio_initiate_track_change((long)ev.data);
3641 break;
3643 case Q_AUDIO_PRE_FF_REWIND:
3644 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3645 if (!playing)
3646 break;
3647 pcmbuf_pause(true);
3648 break;
3650 case Q_AUDIO_FF_REWIND:
3651 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3652 if (!playing)
3653 break ;
3654 ci.seek_time = (long)ev.data+1;
3655 break ;
3657 case Q_AUDIO_REBUFFER_SEEK:
3658 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3659 result = audio_rebuffer_and_seek(ev.data);
3660 break;
3662 case Q_AUDIO_CHECK_NEW_TRACK:
3663 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3664 result = audio_check_new_track();
3665 break;
3667 case Q_AUDIO_DIR_SKIP:
3668 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3669 playlist_end = false;
3670 audio_initiate_dir_change(ev.data);
3671 break;
3673 case Q_AUDIO_FLUSH:
3674 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3675 audio_invalidate_tracks();
3676 break ;
3678 case Q_AUDIO_TRACK_CHANGED:
3679 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3680 if (track_changed_callback)
3681 track_changed_callback(&CUR_TI->id3);
3682 track_changed = true;
3683 playlist_update_resume_info(audio_current_track());
3684 break ;
3686 #ifndef SIMULATOR
3687 case SYS_USB_CONNECTED:
3688 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3689 if (playing)
3690 audio_stop_playback();
3691 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3692 usb_wait_for_disconnect(&audio_queue);
3693 break ;
3694 #endif
3696 case SYS_TIMEOUT:
3697 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3698 break;
3700 default:
3701 LOGFQUEUE("audio < default");
3702 } /* end switch */
3704 queue_reply(&audio_queue, result);
3705 } /* end while */
3708 #ifdef ROCKBOX_HAS_LOGF
3709 static void audio_test_track_changed_event(struct mp3entry *id3)
3711 (void)id3;
3713 logf("tce:%s", id3->path);
3715 #endif
3717 /* Initialize the audio system - called from init() in main.c.
3718 * Last function because of all the references to internal symbols
3720 void audio_init(void)
3722 #ifdef PLAYBACK_VOICE
3723 static bool voicetagtrue = true;
3724 static struct mp3entry id3_voice;
3725 #endif
3727 /* Can never do this twice */
3728 if (audio_is_initialized)
3730 logf("audio: already initialized");
3731 return;
3734 logf("audio: initializing");
3736 /* Initialize queues before giving control elsewhere in case it likes
3737 to send messages. Thread creation will be delayed however so nothing
3738 starts running until ready if something yields such as talk_init. */
3739 #ifdef PLAYBACK_VOICE
3740 mutex_init(&mutex_codecthread);
3741 /* Take ownership of lock to prevent playback of anything before audio
3742 hardware is initialized - audio thread unlocks it after final init
3743 stage */
3744 mutex_lock(&mutex_codecthread);
3745 #endif
3746 queue_init(&audio_queue, true);
3747 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3748 queue_init(&codec_queue, true);
3750 pcm_init();
3752 #ifdef ROCKBOX_HAS_LOGF
3753 audio_set_track_changed_event(audio_test_track_changed_event);
3754 #endif
3756 /* Initialize codec api. */
3757 ci.read_filebuf = codec_filebuf_callback;
3758 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3759 ci.get_codec_memory = codec_get_memory_callback;
3760 ci.request_buffer = codec_request_buffer_callback;
3761 ci.advance_buffer = codec_advance_buffer_callback;
3762 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3763 ci.request_next_track = codec_request_next_track_callback;
3764 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3765 ci.seek_buffer = codec_seek_buffer_callback;
3766 ci.seek_complete = codec_seek_complete_callback;
3767 ci.set_elapsed = codec_set_elapsed_callback;
3768 ci.set_offset = codec_set_offset_callback;
3769 ci.configure = codec_configure_callback;
3770 ci.discard_codec = codec_discard_codec_callback;
3772 /* Initialize voice codec api. */
3773 #ifdef PLAYBACK_VOICE
3774 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3775 memset(&id3_voice, 0, sizeof(id3_voice));
3776 ci_voice.read_filebuf = voice_filebuf_callback;
3777 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3778 ci_voice.get_codec_memory = voice_get_memory_callback;
3779 ci_voice.request_buffer = voice_request_buffer_callback;
3780 ci_voice.advance_buffer = voice_advance_buffer_callback;
3781 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3782 ci_voice.request_next_track = voice_request_next_track_callback;
3783 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3784 ci_voice.seek_buffer = voice_seek_buffer_callback;
3785 ci_voice.seek_complete = voice_do_nothing;
3786 ci_voice.set_elapsed = voice_set_elapsed_callback;
3787 ci_voice.set_offset = voice_set_offset_callback;
3788 ci_voice.configure = voice_configure_callback;
3789 ci_voice.discard_codec = voice_do_nothing;
3790 ci_voice.taginfo_ready = &voicetagtrue;
3791 ci_voice.id3 = &id3_voice;
3792 id3_voice.frequency = 11200;
3793 id3_voice.length = 1000000L;
3794 #endif
3796 /* initialize the buffer */
3797 filebuf = audiobuf;
3799 /* audio_reset_buffer must to know the size of voice buffer so init
3800 talk first */
3801 talk_init();
3803 /* Create the threads late now that we shouldn't be yielding again before
3804 returning */
3805 codec_thread_p = create_thread(
3806 codec_thread, codec_stack, sizeof(codec_stack),
3807 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3808 IF_COP(, CPU, true));
3810 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
3811 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3812 IF_COP(, CPU, false));
3814 #ifdef PLAYBACK_VOICE
3815 /* TODO: Change this around when various speech codecs can be used */
3816 if (talk_voice_required())
3818 logf("Starting voice codec");
3819 queue_init(&voice_queue, true);
3820 create_thread(voice_thread, voice_stack,
3821 sizeof(voice_stack), voice_thread_name
3822 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false));
3824 #endif
3826 /* Set crossfade setting for next buffer init which should be about... */
3827 pcmbuf_crossfade_enable(global_settings.crossfade);
3829 /* ...now! Set up the buffers */
3830 audio_reset_buffer();
3832 /* Probably safe to say */
3833 audio_is_initialized = true;
3835 sound_settings_apply();
3836 #ifdef HAVE_WM8758
3837 eq_hw_enable(global_settings.eq_hw_enabled);
3838 #endif
3839 audio_set_buffer_margin(global_settings.buffer_margin);
3840 } /* audio_init */