Change i2c config on e200. Seems to speed things up somewhat.
[kugel-rb.git] / apps / playback.c
blobe317c853fe454fa500c806d468108bc19dd1f1db
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 "main_menu.h"
54 #include "ata.h"
55 #include "screens.h"
56 #include "playlist.h"
57 #include "playback.h"
58 #include "pcmbuf.h"
59 #include "buffer.h"
60 #include "dsp.h"
61 #include "abrepeat.h"
62 #include "cuesheet.h"
63 #ifdef HAVE_TAGCACHE
64 #include "tagcache.h"
65 #endif
66 #ifdef HAVE_LCD_BITMAP
67 #include "icons.h"
68 #include "peakmeter.h"
69 #include "action.h"
70 #endif
71 #include "lang.h"
72 #include "bookmark.h"
73 #include "misc.h"
74 #include "sound.h"
75 #include "metadata.h"
76 #include "splash.h"
77 #include "talk.h"
78 #include "ata_idle_notify.h"
80 #ifdef HAVE_RECORDING
81 #include "recording.h"
82 #include "talk.h"
83 #endif
85 #ifdef HAVE_WM8758
86 #include "menus/eq_menu.h"
87 #endif
89 #define PLAYBACK_VOICE
92 /* default point to start buffer refill */
93 #define AUDIO_DEFAULT_WATERMARK (1024*512)
94 /* amount of data to read in one read() call */
95 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
96 /* point at which the file buffer will fight for CPU time */
97 #define AUDIO_FILEBUF_CRITICAL (1024*128)
98 /* amount of guess-space to allow for codecs that must hunt and peck
99 * for their correct seeek target, 32k seems a good size */
100 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
102 /* macros to enable logf for queues
103 logging on SYS_TIMEOUT can be disabled */
104 #ifdef SIMULATOR
105 /* Define this for logf output of all queuing except SYS_TIMEOUT */
106 #define PLAYBACK_LOGQUEUES
107 /* Define this to logf SYS_TIMEOUT messages */
108 #define PLAYBACK_LOGQUEUES_SYS_TIMEOUT
109 #endif
111 #ifdef PLAYBACK_LOGQUEUES
112 #define LOGFQUEUE logf
113 #else
114 #define LOGFQUEUE(...)
115 #endif
117 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
118 #define LOGFQUEUE_SYS_TIMEOUT logf
119 #else
120 #define LOGFQUEUE_SYS_TIMEOUT(...)
121 #endif
124 /* Define one constant that includes recording related functionality */
125 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
126 #define AUDIO_HAVE_RECORDING
127 #endif
129 enum {
130 Q_AUDIO_PLAY = 1,
131 Q_AUDIO_STOP,
132 Q_AUDIO_PAUSE,
133 Q_AUDIO_SKIP,
134 Q_AUDIO_PRE_FF_REWIND,
135 Q_AUDIO_FF_REWIND,
136 Q_AUDIO_REBUFFER_SEEK,
137 Q_AUDIO_CHECK_NEW_TRACK,
138 Q_AUDIO_FLUSH,
139 Q_AUDIO_TRACK_CHANGED,
140 Q_AUDIO_DIR_SKIP,
141 Q_AUDIO_POSTINIT,
142 Q_AUDIO_FILL_BUFFER,
143 #if MEM > 8
144 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
145 #endif
146 Q_CODEC_REQUEST_COMPLETE,
147 Q_CODEC_REQUEST_FAILED,
149 Q_VOICE_PLAY,
150 Q_VOICE_STOP,
152 Q_CODEC_LOAD,
153 Q_CODEC_LOAD_DISK,
155 #ifdef AUDIO_HAVE_RECORDING
156 Q_ENCODER_LOAD_DISK,
157 Q_ENCODER_RECORD,
158 #endif
161 /* As defined in plugins/lib/xxx2wav.h */
162 #if MEM > 1
163 #define MALLOC_BUFSIZE (512*1024)
164 #define GUARD_BUFSIZE (32*1024)
165 #else
166 #define MALLOC_BUFSIZE (100*1024)
167 #define GUARD_BUFSIZE (8*1024)
168 #endif
170 /* As defined in plugin.lds */
171 #if defined(CPU_PP)
172 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
173 #define CODEC_IRAM_SIZE ((size_t)0xc000)
174 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
175 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
176 #define CODEC_IRAM_SIZE ((size_t)0x10000)
177 #else
178 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
179 #define CODEC_IRAM_SIZE ((size_t)0xc000)
180 #endif
182 #ifndef IBSS_ATTR_VOICE_STACK
183 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
184 #endif
186 bool audio_is_initialized = false;
188 /* Variables are commented with the threads that use them: *
189 * A=audio, C=codec, V=voice. A suffix of - indicates that *
190 * the variable is read but not updated on that thread. */
191 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
193 /* Main state control */
194 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
195 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
196 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
197 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
199 /* Ring buffer where compressed audio and codecs are loaded */
200 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
201 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
202 /* FIXME: make filebuflen static */
203 size_t filebuflen = 0; /* Size of buffer (A/C-) */
204 /* FIXME: make buf_ridx (C/A-) */
205 static volatile size_t buf_ridx IDATA_ATTR = 0; /* Buffer read position (A/C)*/
206 static volatile size_t buf_widx IDATA_ATTR = 0; /* Buffer write position (A/C-) */
208 /* Possible arrangements of the buffer */
209 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
210 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
211 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
212 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
214 /* Compressed ring buffer helper macros */
215 /* Buffer pointer (p) plus value (v), wrapped if necessary */
216 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
217 /* Buffer pointer (p) minus value (v), wrapped if necessary */
218 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
219 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
220 #define RINGBUF_ADD_CROSS(p1,v,p2) \
221 ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
222 /* Bytes available in the buffer */
223 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
225 /* Track info structure about songs in the file buffer (A/C-) */
226 static struct track_info tracks[MAX_TRACK];
227 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
228 static int track_widx = 0; /* Track being buffered (A) */
230 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
231 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
233 /* Set by the audio thread when the current track information has updated
234 * and the WPS may need to update its cached information */
235 static bool track_changed = false;
237 /* Information used only for filling the buffer */
238 /* Playlist steps from playing track to next track to be buffered (A) */
239 static int last_peek_offset = 0;
240 /* Partially loaded track file handle to continue buffering (A) */
241 static int current_fd = -1;
243 /* Scrobbler support */
244 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
246 /* Track change controls */
247 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
248 static bool playlist_end = false; /* Has the current playlist ended? (A) */
249 static bool dir_skip = false; /* Is a directory skip pending? (A) */
250 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
251 /* Pending track change offset, to keep WPS responsive (A) */
252 static int wps_offset = 0;
254 /* Callbacks which applications or plugins may set */
255 /* When the playing track has changed from the user's perspective */
256 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
257 /* When a track has been buffered */
258 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
259 /* When a track's buffer has been overwritten or cleared */
260 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
262 /* Configuration */
263 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
264 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
265 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
266 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
267 static bool v1first = false; /* ID3 data control, true if V1 then V2 (A) */
268 #if MEM > 8
269 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
270 #endif
272 /* Multiple threads */
273 static void set_current_codec(int codec_idx);
274 /* Set the watermark to trigger buffer fill (A/C) FIXME */
275 static void set_filebuf_watermark(int seconds);
277 /* Audio thread */
278 static struct event_queue audio_queue;
279 static struct queue_sender_list audio_queue_sender_list;
280 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
281 static const char audio_thread_name[] = "audio";
283 static void audio_thread(void);
284 static void audio_initiate_track_change(long direction);
285 static bool audio_have_tracks(void);
286 static void audio_reset_buffer(void);
288 /* Codec thread */
289 extern struct codec_api ci;
290 static struct event_queue codec_queue NOCACHEBSS_ATTR;
291 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
292 IBSS_ATTR;
293 static const char codec_thread_name[] = "codec";
294 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
296 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
298 /* Voice thread */
299 #ifdef PLAYBACK_VOICE
301 extern struct codec_api ci_voice;
303 static struct thread_entry *voice_thread_p = NULL;
304 static struct event_queue voice_queue NOCACHEBSS_ATTR;
305 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
306 IBSS_ATTR_VOICE_STACK;
307 static const char voice_thread_name[] = "voice codec";
309 /* Voice codec swapping control */
310 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
312 #ifdef SIMULATOR
313 /* IRAM codec swap buffer for sim*/
314 static unsigned char sim_iram[CODEC_IRAM_SIZE];
315 #undef CODEC_IRAM_ORIGIN
316 #define CODEC_IRAM_ORIGIN sim_iram
317 #endif
319 /* iram_buf and dram_buf are either both NULL or both non-NULL */
320 /* Pointer to IRAM buffer for codec swapping */
321 static unsigned char *iram_buf = NULL;
322 /* Pointer to DRAM buffer for codec swapping */
323 static unsigned char *dram_buf = NULL;
324 /* Parity of swap_codec calls - needed because one codec swapping itself in
325 automatically swaps in the other and the swap when unlocking should not
326 happen if the parity is even.
328 static bool swap_codec_parity = false; /* true=odd, false=even */
329 /* Mutex to control which codec (normal/voice) is running */
330 static struct mutex mutex_codecthread NOCACHEBSS_ATTR;
332 /* Voice state */
333 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
334 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
335 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
336 static char *voicebuf = NULL;
337 static size_t voice_remaining = 0;
339 #ifdef IRAM_STEAL
340 /* Voice IRAM has been stolen for other use */
341 static bool voice_iram_stolen = false;
342 #endif
344 static void (*voice_getmore)(unsigned char** start, int* size) = NULL;
346 struct voice_info {
347 void (*callback)(unsigned char **start, int *size);
348 int size;
349 char *buf;
351 static void voice_thread(void);
352 static void voice_stop(void);
354 #endif /* PLAYBACK_VOICE */
356 /* --- External interfaces --- */
358 void mp3_play_data(const unsigned char* start, int size,
359 void (*get_more)(unsigned char** start, int* size))
361 #ifdef PLAYBACK_VOICE
362 static struct voice_info voice_clip;
363 voice_clip.callback = get_more;
364 voice_clip.buf = (char *)start;
365 voice_clip.size = size;
366 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
367 queue_post(&voice_queue, Q_VOICE_STOP, 0);
368 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
369 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
370 voice_thread_start = true;
371 trigger_cpu_boost();
372 #else
373 (void) start;
374 (void) size;
375 (void) get_more;
376 #endif
379 void mp3_play_stop(void)
381 #ifdef PLAYBACK_VOICE
382 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
383 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
384 queue_post(&voice_queue, Q_VOICE_STOP, 1);
385 #endif
388 void mp3_play_pause(bool play)
390 /* a dummy */
391 (void)play;
394 bool mp3_is_playing(void)
396 return voice_is_playing;
399 void mpeg_id3_options(bool _v1first)
401 v1first = _v1first;
404 /* If voice could be swapped out - wait for it to return
405 * Used by buffer claming functions.
407 static void wait_for_voice_swap_in(void)
409 #ifdef PLAYBACK_VOICE
410 if (NULL == iram_buf)
411 return;
413 while (current_codec != CODEC_IDX_VOICE)
414 yield();
415 #endif /* PLAYBACK_VOICE */
418 /* This sends a stop message and the audio thread will dump all it's
419 subsequenct messages */
420 static void audio_hard_stop(void)
422 /* Stop playback */
423 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
424 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
427 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
429 unsigned char *buf, *end;
431 if (audio_is_initialized)
433 audio_hard_stop();
434 wait_for_voice_swap_in();
435 voice_stop();
437 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
439 if (buffer_size == NULL)
441 /* Special case for talk_init to use since it already knows it's
442 trashed */
443 buffer_state = BUFFER_STATE_TRASHED;
444 return NULL;
447 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
448 || !talk_voice_required())
450 logf("get buffer: talk, audio");
451 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
452 the talk buffer is not needed because voice isn't being used, or
453 could be BUFFER_STATE_TRASHED already. If state is
454 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
455 without the caller knowing what's going on. Changing certain settings
456 may move it to a worse condition but the memory in use by something
457 else will remain undisturbed.
459 if (buffer_state != BUFFER_STATE_TRASHED)
461 talk_buffer_steal();
462 buffer_state = BUFFER_STATE_TRASHED;
465 buf = audiobuf;
466 end = audiobufend;
468 else
470 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
471 still BUFFER_STATE_INITIALIZED */
472 /* Skip talk buffer and move pcm buffer to end to maximize available
473 contiguous memory - no audio running means voice will not need the
474 swap space */
475 logf("get buffer: audio");
476 buf = audiobuf + talk_get_bufsize();
477 end = audiobufend - pcmbuf_init(audiobufend);
478 buffer_state = BUFFER_STATE_VOICED_ONLY;
481 *buffer_size = end - buf;
483 return buf;
486 #ifdef IRAM_STEAL
487 void audio_iram_steal(void)
489 /* We need to stop audio playback in order to use codec IRAM */
490 audio_hard_stop();
492 #ifdef PLAYBACK_VOICE
493 if (NULL != iram_buf)
495 /* Can't already be stolen */
496 if (voice_iram_stolen)
497 return;
499 /* Must wait for voice to be current again if it is swapped which
500 would cause the caller's buffer to get clobbered when voice locks
501 and runs - we'll wait for it to lock and yield again then make sure
502 the ride has come to a complete stop */
503 wait_for_voice_swap_in();
504 voice_stop();
506 /* Save voice IRAM but just memcpy - safe to do here since voice
507 is current and no audio codec is loaded */
508 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
509 voice_iram_stolen = true;
511 else
513 /* Nothing much to do if no voice */
514 voice_iram_stolen = false;
516 #endif
518 #endif /* IRAM_STEAL */
520 #ifdef HAVE_RECORDING
521 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
523 /* Don't allow overwrite of voice swap area or we'll trash the
524 swapped-out voice codec but can use whole thing if none */
525 unsigned char *end;
527 /* Stop audio and voice. Wait for voice to swap in and be clear
528 of pending events to ensure trouble-free operation of encoders */
529 audio_hard_stop();
530 wait_for_voice_swap_in();
531 voice_stop();
532 talk_buffer_steal();
534 #ifdef PLAYBACK_VOICE
535 /* If no dram_buf, swap space not used and recording gets more
536 memory. Codec swap areas will remain unaffected by the next init
537 since they're allocated at the end of the buffer and their sizes
538 don't change between calls */
539 end = dram_buf;
540 if (NULL == end)
541 #endif /* PLAYBACK_VOICE */
542 end = audiobufend;
544 buffer_state = BUFFER_STATE_TRASHED;
546 *buffer_size = end - audiobuf;
548 return (unsigned char *)audiobuf;
551 bool audio_load_encoder(int afmt)
553 #ifndef SIMULATOR
554 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
555 if (!enc_fn)
556 return false;
558 audio_remove_encoder();
559 ci.enc_codec_loaded = 0; /* clear any previous error condition */
561 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
562 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
564 while (ci.enc_codec_loaded == 0)
565 yield();
567 logf("codec loaded: %d", ci.enc_codec_loaded);
569 return ci.enc_codec_loaded > 0;
570 #else
571 (void)afmt;
572 return true;
573 #endif
574 } /* audio_load_encoder */
576 void audio_remove_encoder(void)
578 #ifndef SIMULATOR
579 /* force encoder codec unload (if currently loaded) */
580 if (ci.enc_codec_loaded <= 0)
581 return;
583 ci.stop_encoder = true;
584 while (ci.enc_codec_loaded > 0)
585 yield();
586 #endif
587 } /* audio_remove_encoder */
589 #endif /* HAVE_RECORDING */
591 struct mp3entry* audio_current_track(void)
593 const char *filename;
594 const char *p;
595 static struct mp3entry temp_id3;
596 int cur_idx;
597 int offset = ci.new_track + wps_offset;
599 cur_idx = track_ridx + offset;
600 cur_idx &= MAX_TRACK_MASK;
602 if (tracks[cur_idx].taginfo_ready)
603 return &tracks[cur_idx].id3;
605 memset(&temp_id3, 0, sizeof(struct mp3entry));
607 filename = playlist_peek(offset);
608 if (!filename)
609 filename = "No file!";
611 #ifdef HAVE_TC_RAMCACHE
612 if (tagcache_fill_tags(&temp_id3, filename))
613 return &temp_id3;
614 #endif
616 p = strrchr(filename, '/');
617 if (!p)
618 p = filename;
619 else
620 p++;
622 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
623 temp_id3.title = &temp_id3.path[0];
625 return &temp_id3;
628 struct mp3entry* audio_next_track(void)
630 int next_idx = track_ridx;
632 if (!audio_have_tracks())
633 return NULL;
635 next_idx++;
636 next_idx &= MAX_TRACK_MASK;
638 if (!tracks[next_idx].taginfo_ready)
639 return NULL;
641 return &tracks[next_idx].id3;
644 bool audio_has_changed_track(void)
646 if (track_changed)
648 track_changed = false;
649 return true;
652 return false;
655 void audio_play(long offset)
657 logf("audio_play");
659 #ifdef PLAYBACK_VOICE
660 /* Truncate any existing voice output so we don't have spelling
661 * etc. over the first part of the played track */
662 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
663 queue_post(&voice_queue, Q_VOICE_STOP, 1);
664 #endif
666 /* Start playback */
667 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
668 /* Don't return until playback has actually started */
669 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
672 void audio_stop(void)
674 /* Stop playback */
675 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
676 /* Don't return until playback has actually stopped */
677 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
680 void audio_pause(void)
682 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
683 /* Don't return until playback has actually paused */
684 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
687 void audio_resume(void)
689 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
690 /* Don't return until playback has actually resumed */
691 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
694 void audio_next(void)
696 if (playlist_check(ci.new_track + wps_offset + 1))
698 if (global_settings.beep)
699 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
701 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
702 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
703 /* Update wps while our message travels inside deep playback queues. */
704 wps_offset++;
705 track_changed = true;
707 else
709 /* No more tracks. */
710 if (global_settings.beep)
711 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
715 void audio_prev(void)
717 if (playlist_check(ci.new_track + wps_offset - 1))
719 if (global_settings.beep)
720 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
722 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
723 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
724 /* Update wps while our message travels inside deep playback queues. */
725 wps_offset--;
726 track_changed = true;
728 else
730 /* No more tracks. */
731 if (global_settings.beep)
732 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
736 void audio_next_dir(void)
738 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
739 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
742 void audio_prev_dir(void)
744 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
745 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
748 void audio_pre_ff_rewind(void)
750 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
751 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
754 void audio_ff_rewind(long newpos)
756 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
757 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
760 void audio_flush_and_reload_tracks(void)
762 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
763 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
766 void audio_error_clear(void)
768 #ifdef AUDIO_HAVE_RECORDING
769 pcm_rec_error_clear();
770 #endif
773 int audio_status(void)
775 int ret = 0;
777 if (playing)
778 ret |= AUDIO_STATUS_PLAY;
780 if (paused)
781 ret |= AUDIO_STATUS_PAUSE;
783 #ifdef HAVE_RECORDING
784 /* Do this here for constitency with mpeg.c version */
785 ret |= pcm_rec_status();
786 #endif
788 return ret;
791 int audio_get_file_pos(void)
793 return 0;
796 void audio_set_buffer_margin(int setting)
798 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
799 buffer_margin = lookup[setting];
800 logf("buffer margin: %ld", buffer_margin);
801 set_filebuf_watermark(buffer_margin);
804 /* Take nescessary steps to enable or disable the crossfade setting */
805 void audio_set_crossfade(int enable)
807 size_t offset;
808 bool was_playing;
809 size_t size;
811 /* Tell it the next setting to use */
812 pcmbuf_crossfade_enable(enable);
814 /* Return if size hasn't changed or this is too early to determine
815 which in the second case there's no way we could be playing
816 anything at all */
817 if (pcmbuf_is_same_size())
819 /* This function is a copout and just syncs some variables -
820 to be removed at a later date */
821 pcmbuf_crossfade_enable_finished();
822 return;
825 offset = 0;
826 was_playing = playing;
828 /* Playback has to be stopped before changing the buffer size */
829 if (was_playing)
831 /* Store the track resume position */
832 offset = CUR_TI->id3.offset;
833 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
836 /* Blast it - audio buffer will have to be setup again next time
837 something plays */
838 audio_get_buffer(true, &size);
840 /* Restart playback if audio was running previously */
841 if (was_playing)
842 audio_play(offset);
845 /* --- Routines called from multiple threads --- */
846 static void set_current_codec(int codec_idx)
848 current_codec = codec_idx;
849 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
852 #ifdef PLAYBACK_VOICE
853 static void swap_codec(void)
855 int my_codec;
857 /* Swap nothing if no swap buffers exist */
858 if (dram_buf == NULL)
860 logf("swap: no swap buffers");
861 return;
864 my_codec = current_codec;
866 logf("swapping out codec: %d", my_codec);
868 /* Invert this when a codec thread enters and leaves */
869 swap_codec_parity = !swap_codec_parity;
871 /* If this is true, an odd number of calls has occurred and there's
872 no codec thread waiting to swap us out when it locks and runs. This
873 occurs when playback is stopped or when just starting playback and
874 the audio thread is loading a codec; parities should always be even
875 on entry when a thread calls this during playback */
876 if (swap_codec_parity)
878 /* Save our current IRAM and DRAM */
879 #ifdef IRAM_STEAL
880 if (voice_iram_stolen)
882 logf("swap: iram restore");
883 voice_iram_stolen = false;
884 /* Don't swap trashed data into buffer as the voice IRAM will
885 already be swapped out - should _always_ be the case if
886 voice_iram_stolen is true since the voice has been swapped
887 in beforehand */
888 if (my_codec == CODEC_IDX_VOICE)
890 logf("voice iram already swapped");
891 goto skip_iram_swap;
894 #endif
896 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
898 #ifdef IRAM_STEAL
899 skip_iram_swap:
900 #endif
902 memswap128(dram_buf, codecbuf, CODEC_SIZE);
903 /* No cache invalidation needed; it will be done in codec_load_ram
904 or we won't be here otherwise */
907 /* Release my semaphore */
908 mutex_unlock(&mutex_codecthread);
909 logf("unlocked: %d", my_codec);
911 /* Loop until the other codec has locked and run */
912 do {
913 /* Release my semaphore and force a task switch. */
914 yield();
915 } while (my_codec == current_codec);
917 /* Wait for other codec to unlock */
918 /* FIXME: We need some sort of timed boost cancellation here or the CPU
919 doesn't unboost during playback when the voice codec goes back to
920 waiting - recall that mutex_lock calls block_thread which is an
921 indefinite wait that doesn't cancel the thread's CPU boost */
922 mutex_lock(&mutex_codecthread);
924 /* Take control */
925 logf("waiting for lock: %d", my_codec);
926 set_current_codec(my_codec);
928 /* Reload our IRAM and DRAM */
929 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
930 memswap128(dram_buf, codecbuf, CODEC_SIZE);
931 invalidate_icache();
933 /* Flip parity again */
934 swap_codec_parity = !swap_codec_parity;
936 logf("resuming codec: %d", my_codec);
939 /* This function is meant to be used by the buffer stealing functions to
940 ensure the codec is no longer active and so voice will be swapped-in
941 before it is called */
942 static void voice_stop(void)
944 #ifdef PLAYBACK_VOICE
945 /* Must have a voice codec loaded or we'll hang forever here */
946 if (!voice_codec_loaded)
947 return;
949 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
950 queue_post(&voice_queue, Q_VOICE_STOP, 0);
952 /* Loop until voice empties it's queue, stops and picks up on the new
953 track; the voice thread must be stopped and waiting for messages
954 outside the codec */
955 while (voice_is_playing || !queue_empty(&voice_queue) ||
956 ci_voice.new_track)
957 yield();
959 if (!playing)
960 pcmbuf_play_stop();
961 #endif
962 } /* voice_stop */
963 #endif /* PLAYBACK_VOICE */
965 static void set_filebuf_watermark(int seconds)
967 size_t bytes;
969 if (!filebuf)
970 return; /* Audio buffers not yet set up */
972 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
973 bytes = MIN(bytes, filebuflen / 2);
974 conf_watermark = bytes;
977 const char * get_codec_filename(int cod_spec)
979 const char *fname;
981 #ifdef HAVE_RECORDING
982 /* Can choose decoder or encoder if one available */
983 int type = cod_spec & CODEC_TYPE_MASK;
984 int afmt = cod_spec & CODEC_AFMT_MASK;
986 if ((unsigned)afmt >= AFMT_NUM_CODECS)
987 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
989 fname = (type == CODEC_TYPE_ENCODER) ?
990 audio_formats[afmt].codec_enc_root_fn :
991 audio_formats[afmt].codec_root_fn;
993 logf("%s: %d - %s",
994 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
995 afmt, fname ? fname : "<unknown>");
996 #else /* !HAVE_RECORDING */
997 /* Always decoder */
998 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
999 cod_spec = AFMT_UNKNOWN;
1000 fname = audio_formats[cod_spec].codec_root_fn;
1001 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1002 #endif /* HAVE_RECORDING */
1004 return fname;
1005 } /* get_codec_filename */
1008 /* --- Voice thread --- */
1010 #ifdef PLAYBACK_VOICE
1012 static bool voice_pcmbuf_insert_callback(
1013 const void *ch1, const void *ch2, int count)
1015 const char *src[2] = { ch1, ch2 };
1017 while (count > 0)
1019 int out_count = dsp_output_count(count);
1020 int inp_count;
1021 char *dest;
1023 while ((dest = pcmbuf_request_voice_buffer(
1024 &out_count, playing)) == NULL)
1026 if (playing && audio_codec_loaded)
1027 swap_codec();
1028 else
1029 yield();
1032 /* Get the real input_size for output_size bytes, guarding
1033 * against resampling buffer overflows. */
1034 inp_count = dsp_input_count(out_count);
1036 if (inp_count <= 0)
1037 return true;
1039 /* Input size has grown, no error, just don't write more than length */
1040 if (inp_count > count)
1041 inp_count = count;
1043 out_count = dsp_process(dest, src, inp_count);
1045 if (out_count <= 0)
1046 return true;
1048 if (playing)
1050 pcmbuf_mix_voice(out_count);
1051 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1052 audio_codec_loaded)
1053 swap_codec();
1055 else
1056 pcmbuf_write_complete(out_count);
1058 count -= inp_count;
1061 return true;
1062 } /* voice_pcmbuf_insert_callback */
1064 static void* voice_get_memory_callback(size_t *size)
1066 /* Voice should have no use for this. If it did, we'd have to
1067 swap the malloc buffer as well. */
1068 *size = 0;
1069 return NULL;
1072 static void voice_set_elapsed_callback(unsigned int value)
1074 (void)value;
1077 static void voice_set_offset_callback(size_t value)
1079 (void)value;
1082 static void voice_configure_callback(int setting, intptr_t value)
1084 if (!dsp_configure(setting, value))
1086 logf("Illegal key:%d", setting);
1090 static size_t voice_filebuf_callback(void *ptr, size_t size)
1092 (void)ptr;
1093 (void)size;
1095 return 0;
1098 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1099 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1101 if (aborting && !playing && pcm_is_playing())
1103 /* Aborting: Slight hack - flush PCM buffer if
1104 only being used for voice */
1105 pcmbuf_play_stop();
1108 if (voice_is_playing)
1110 /* Clear the current buffer */
1111 voice_is_playing = false;
1112 voice_getmore = NULL;
1113 voice_remaining = 0;
1114 voicebuf = NULL;
1116 /* Force the codec to think it's changing tracks */
1117 ci_voice.new_track = 1;
1119 *realsize = 0;
1120 return true; /* Yes, change tracks */
1123 return false;
1126 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1128 struct event ev;
1130 if (ci_voice.new_track)
1132 *realsize = 0;
1133 return NULL;
1136 while (1)
1138 if (voice_is_playing || playing)
1140 queue_wait_w_tmo(&voice_queue, &ev, 0);
1141 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1142 ev.id = Q_AUDIO_PLAY;
1144 else
1146 /* We must use queue_wait_w_tmo() because queue_wait() doesn't
1147 unboost the CPU */
1148 /* FIXME: when long timeouts work correctly max out the the timeout
1149 (we'll still need the timeout guard here) or an infinite timeout
1150 can unboost, use that */
1152 queue_wait_w_tmo(&voice_queue, &ev, HZ*5);
1153 while (ev.id == SYS_TIMEOUT); /* Fake infinite wait */
1156 switch (ev.id) {
1157 case Q_AUDIO_PLAY:
1158 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1159 if (playing)
1161 if (audio_codec_loaded)
1162 swap_codec();
1163 yield();
1165 break;
1167 #ifdef AUDIO_HAVE_RECORDING
1168 case Q_ENCODER_RECORD:
1169 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1170 swap_codec();
1171 break;
1172 #endif
1174 case Q_VOICE_STOP:
1175 LOGFQUEUE("voice < Q_VOICE_STOP");
1176 if (voice_on_voice_stop(ev.data, realsize))
1177 return NULL;
1178 break;
1180 case SYS_USB_CONNECTED:
1182 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1183 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1184 /* Voice is obviously current so let us swap ourselves away if
1185 playing so audio may stop itself - audio_codec_loaded can
1186 only be true in this case if we're here even if the codec
1187 is only about to load */
1188 if (audio_codec_loaded)
1189 swap_codec();
1190 /* Playback should be finished by now - ack and wait */
1191 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1192 usb_wait_for_disconnect(&voice_queue);
1193 if (change_tracks)
1194 return NULL;
1195 break;
1198 case Q_VOICE_PLAY:
1199 LOGFQUEUE("voice < Q_VOICE_PLAY");
1200 if (!voice_is_playing)
1202 /* Set up new voice data */
1203 struct voice_info *voice_data;
1204 #ifdef IRAM_STEAL
1205 if (voice_iram_stolen)
1207 /* Voice is the first to run again and is currently
1208 loaded */
1209 logf("voice: iram restore");
1210 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1211 voice_iram_stolen = false;
1213 #endif
1214 /* Must reset the buffer before any playback begins if
1215 needed */
1216 if (buffer_state == BUFFER_STATE_TRASHED)
1217 audio_reset_buffer();
1219 voice_is_playing = true;
1220 trigger_cpu_boost();
1221 voice_data = (struct voice_info *)ev.data;
1222 voice_remaining = voice_data->size;
1223 voicebuf = voice_data->buf;
1224 voice_getmore = voice_data->callback;
1226 goto voice_play_clip; /* To exit both switch and while */
1228 case SYS_TIMEOUT:
1229 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1230 goto voice_play_clip;
1232 default:
1233 LOGFQUEUE("voice < default");
1237 voice_play_clip:
1239 if (voice_remaining == 0 || voicebuf == NULL)
1241 if (voice_getmore)
1242 voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
1244 /* If this clip is done */
1245 if (voice_remaining == 0)
1247 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1248 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1249 /* Force pcm playback. */
1250 if (!pcm_is_playing())
1251 pcmbuf_play_start();
1255 *realsize = MIN(voice_remaining, reqsize);
1257 if (*realsize == 0)
1258 return NULL;
1260 return voicebuf;
1261 } /* voice_request_buffer_callback */
1263 static void voice_advance_buffer_callback(size_t amount)
1265 amount = MIN(amount, voice_remaining);
1266 voicebuf += amount;
1267 voice_remaining -= amount;
1270 static void voice_advance_buffer_loc_callback(void *ptr)
1272 size_t amount = (size_t)ptr - (size_t)voicebuf;
1274 voice_advance_buffer_callback(amount);
1277 static off_t voice_mp3_get_filepos_callback(int newtime)
1279 (void)newtime;
1281 return 0;
1284 static void voice_do_nothing(void)
1286 return;
1289 static bool voice_seek_buffer_callback(size_t newpos)
1291 (void)newpos;
1293 return false;
1296 static bool voice_request_next_track_callback(void)
1298 ci_voice.new_track = 0;
1299 return true;
1302 static void voice_thread(void)
1304 logf("Loading voice codec");
1305 voice_codec_loaded = true;
1306 mutex_lock(&mutex_codecthread);
1307 set_current_codec(CODEC_IDX_VOICE);
1308 dsp_configure(DSP_RESET, 0);
1309 voice_remaining = 0;
1310 voice_getmore = NULL;
1312 /* FIXME: If we being starting the voice thread without reboot, the
1313 voice_queue could be full of old stuff and we must flush it. */
1314 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1316 logf("Voice codec finished");
1317 voice_codec_loaded = false;
1318 mutex_unlock(&mutex_codecthread);
1319 voice_thread_p = NULL;
1320 remove_thread(NULL);
1321 } /* voice_thread */
1323 #endif /* PLAYBACK_VOICE */
1325 /* --- Codec thread --- */
1326 static bool codec_pcmbuf_insert_callback(
1327 const void *ch1, const void *ch2, int count)
1329 const char *src[2] = { ch1, ch2 };
1331 while (count > 0)
1333 int out_count = dsp_output_count(count);
1334 int inp_count;
1335 char *dest;
1337 /* Prevent audio from a previous track from playing */
1338 if (ci.new_track || ci.stop_codec)
1339 return true;
1341 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1343 sleep(1);
1344 if (ci.seek_time || ci.new_track || ci.stop_codec)
1345 return true;
1348 /* Get the real input_size for output_size bytes, guarding
1349 * against resampling buffer overflows. */
1350 inp_count = dsp_input_count(out_count);
1352 if (inp_count <= 0)
1353 return true;
1355 /* Input size has grown, no error, just don't write more than length */
1356 if (inp_count > count)
1357 inp_count = count;
1359 out_count = dsp_process(dest, src, inp_count);
1361 if (out_count <= 0)
1362 return true;
1364 pcmbuf_write_complete(out_count);
1366 #ifdef PLAYBACK_VOICE
1367 if ((voice_is_playing || voice_thread_start)
1368 && pcm_is_playing() && voice_codec_loaded &&
1369 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1371 voice_thread_start = false;
1372 swap_codec();
1374 #endif
1376 count -= inp_count;
1379 return true;
1380 } /* codec_pcmbuf_insert_callback */
1382 static void* codec_get_memory_callback(size_t *size)
1384 *size = MALLOC_BUFSIZE;
1385 return malloc_buf;
1388 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1389 static void codec_pcmbuf_position_callback(size_t size)
1391 /* This is called from an ISR, so be quick */
1392 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1393 prev_ti->id3.elapsed;
1395 if (time >= prev_ti->id3.length)
1397 pcmbuf_set_position_callback(NULL);
1398 prev_ti->id3.elapsed = prev_ti->id3.length;
1400 else
1401 prev_ti->id3.elapsed = time;
1404 static void codec_set_elapsed_callback(unsigned int value)
1406 unsigned int latency;
1407 if (ci.seek_time)
1408 return;
1410 #ifdef AB_REPEAT_ENABLE
1411 ab_position_report(value);
1412 #endif
1414 latency = pcmbuf_get_latency();
1415 if (value < latency)
1416 CUR_TI->id3.elapsed = 0;
1417 else if (value - latency > CUR_TI->id3.elapsed ||
1418 value - latency < CUR_TI->id3.elapsed - 2)
1420 CUR_TI->id3.elapsed = value - latency;
1424 static void codec_set_offset_callback(size_t value)
1426 unsigned int latency;
1428 if (ci.seek_time)
1429 return;
1431 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1432 if (value < latency)
1433 CUR_TI->id3.offset = 0;
1434 else
1435 CUR_TI->id3.offset = value - latency;
1438 static void codec_advance_buffer_counters(size_t amount)
1440 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1441 ci.curpos += amount;
1442 CUR_TI->available -= amount;
1444 /* Start buffer filling as necessary. */
1445 if (!pcmbuf_is_lowdata() && !filling)
1447 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1449 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1450 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1455 /* copy up-to size bytes into ptr and return the actual size copied */
1456 static size_t codec_filebuf_callback(void *ptr, size_t size)
1458 char *buf = (char *)ptr;
1459 size_t copy_n;
1460 size_t part_n;
1462 if (ci.stop_codec || !playing)
1463 return 0;
1465 /* The ammount to copy is the lesser of the requested amount and the
1466 * amount left of the current track (both on disk and already loaded) */
1467 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1469 /* Nothing requested OR nothing left */
1470 if (copy_n == 0)
1471 return 0;
1473 /* Let the disk buffer catch fill until enough data is available */
1474 while (copy_n > CUR_TI->available)
1476 if (!filling)
1478 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1479 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1482 sleep(1);
1483 if (ci.stop_codec || ci.new_track)
1484 return 0;
1487 /* Copy as much as possible without wrapping */
1488 part_n = MIN(copy_n, filebuflen - buf_ridx);
1489 memcpy(buf, &filebuf[buf_ridx], part_n);
1490 /* Copy the rest in the case of a wrap */
1491 if (part_n < copy_n) {
1492 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1495 /* Update read and other position pointers */
1496 codec_advance_buffer_counters(copy_n);
1498 /* Return the actual amount of data copied to the buffer */
1499 return copy_n;
1500 } /* codec_filebuf_callback */
1502 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1504 size_t short_n, copy_n, buf_rem;
1506 if (!playing)
1508 *realsize = 0;
1509 return NULL;
1512 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1513 if (copy_n == 0)
1515 *realsize = 0;
1516 return NULL;
1519 while (copy_n > CUR_TI->available)
1521 if (!filling)
1523 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1524 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1527 sleep(1);
1528 if (ci.stop_codec || ci.new_track)
1530 *realsize = 0;
1531 return NULL;
1535 /* How much is left at the end of the file buffer before wrap? */
1536 buf_rem = filebuflen - buf_ridx;
1538 /* If we can't satisfy the request without wrapping */
1539 if (buf_rem < copy_n)
1541 /* How short are we? */
1542 short_n = copy_n - buf_rem;
1544 /* If we can fudge it with the guardbuf */
1545 if (short_n < GUARD_BUFSIZE)
1546 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1547 else
1548 copy_n = buf_rem;
1551 *realsize = copy_n;
1553 return (char *)&filebuf[buf_ridx];
1554 } /* codec_request_buffer_callback */
1556 static int get_codec_base_type(int type)
1558 switch (type) {
1559 case AFMT_MPA_L1:
1560 case AFMT_MPA_L2:
1561 case AFMT_MPA_L3:
1562 return AFMT_MPA_L3;
1565 return type;
1568 static void codec_advance_buffer_callback(size_t amount)
1570 if (amount > CUR_TI->available + CUR_TI->filerem)
1571 amount = CUR_TI->available + CUR_TI->filerem;
1573 while (amount > CUR_TI->available && filling)
1574 sleep(1);
1576 if (amount > CUR_TI->available)
1578 intptr_t result = Q_CODEC_REQUEST_FAILED;
1580 if (!ci.stop_codec)
1582 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1583 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1584 ci.curpos + amount);
1587 switch (result)
1589 case Q_CODEC_REQUEST_FAILED:
1590 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1591 ci.stop_codec = true;
1592 return;
1594 case Q_CODEC_REQUEST_COMPLETE:
1595 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1596 return;
1598 default:
1599 LOGFQUEUE("codec |< default");
1600 ci.stop_codec = true;
1601 return;
1605 codec_advance_buffer_counters(amount);
1607 codec_set_offset_callback(ci.curpos);
1610 static void codec_advance_buffer_loc_callback(void *ptr)
1612 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1614 codec_advance_buffer_callback(amount);
1617 /* Copied from mpeg.c. Should be moved somewhere else. */
1618 static int codec_get_file_pos(void)
1620 int pos = -1;
1621 struct mp3entry *id3 = audio_current_track();
1623 if (id3->vbr)
1625 if (id3->has_toc)
1627 /* Use the TOC to find the new position */
1628 unsigned int percent, remainder;
1629 int curtoc, nexttoc, plen;
1631 percent = (id3->elapsed*100)/id3->length;
1632 if (percent > 99)
1633 percent = 99;
1635 curtoc = id3->toc[percent];
1637 if (percent < 99)
1638 nexttoc = id3->toc[percent+1];
1639 else
1640 nexttoc = 256;
1642 pos = (id3->filesize/256)*curtoc;
1644 /* Use the remainder to get a more accurate position */
1645 remainder = (id3->elapsed*100)%id3->length;
1646 remainder = (remainder*100)/id3->length;
1647 plen = (nexttoc - curtoc)*(id3->filesize/256);
1648 pos += (plen/100)*remainder;
1650 else
1652 /* No TOC exists, estimate the new position */
1653 pos = (id3->filesize / (id3->length / 1000)) *
1654 (id3->elapsed / 1000);
1657 else if (id3->bitrate)
1658 pos = id3->elapsed * (id3->bitrate / 8);
1659 else
1660 return -1;
1662 pos += id3->first_frame_offset;
1664 /* Don't seek right to the end of the file so that we can
1665 transition properly to the next song */
1666 if (pos >= (int)(id3->filesize - id3->id3v1len))
1667 pos = id3->filesize - id3->id3v1len - 1;
1669 return pos;
1672 static off_t codec_mp3_get_filepos_callback(int newtime)
1674 off_t newpos;
1676 CUR_TI->id3.elapsed = newtime;
1677 newpos = codec_get_file_pos();
1679 return newpos;
1682 static void codec_seek_complete_callback(void)
1684 logf("seek_complete");
1685 if (pcm_is_paused())
1687 /* If this is not a seamless seek, clear the buffer */
1688 pcmbuf_play_stop();
1689 dsp_configure(DSP_FLUSH, 0);
1691 /* If playback was not 'deliberately' paused, unpause now */
1692 if (!paused)
1693 pcmbuf_pause(false);
1695 ci.seek_time = 0;
1698 static bool codec_seek_buffer_callback(size_t newpos)
1700 int difference;
1702 logf("codec_seek_buffer_callback");
1704 if (newpos >= CUR_TI->filesize)
1705 newpos = CUR_TI->filesize - 1;
1707 difference = newpos - ci.curpos;
1708 if (difference >= 0)
1710 /* Seeking forward */
1711 logf("seek: +%d", difference);
1712 codec_advance_buffer_callback(difference);
1713 return true;
1716 /* Seeking backward */
1717 difference = -difference;
1718 if (ci.curpos - difference < 0)
1719 difference = ci.curpos;
1721 /* We need to reload the song. */
1722 if (newpos < CUR_TI->start_pos)
1724 intptr_t result = Q_CODEC_REQUEST_FAILED;
1726 if (!ci.stop_codec)
1728 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1729 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1730 newpos);
1733 switch (result)
1735 case Q_CODEC_REQUEST_COMPLETE:
1736 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1737 return true;
1739 case Q_CODEC_REQUEST_FAILED:
1740 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1741 ci.stop_codec = true;
1742 return false;
1744 default:
1745 LOGFQUEUE("codec |< default");
1746 return false;
1750 /* Seeking inside buffer space. */
1751 logf("seek: -%d", difference);
1752 CUR_TI->available += difference;
1753 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1754 ci.curpos -= difference;
1756 return true;
1759 static void codec_configure_callback(int setting, intptr_t value)
1761 switch (setting) {
1762 case CODEC_SET_FILEBUF_WATERMARK:
1763 conf_watermark = value;
1764 set_filebuf_watermark(buffer_margin);
1765 break;
1767 case CODEC_SET_FILEBUF_CHUNKSIZE:
1768 conf_filechunk = value;
1769 break;
1771 case CODEC_SET_FILEBUF_PRESEEK:
1772 conf_preseek = value;
1773 break;
1775 default:
1776 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1780 static void codec_track_changed(void)
1782 automatic_skip = false;
1783 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1784 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1787 static void codec_pcmbuf_track_changed_callback(void)
1789 pcmbuf_set_position_callback(NULL);
1790 codec_track_changed();
1793 static void codec_discard_codec_callback(void)
1795 if (CUR_TI->has_codec)
1797 CUR_TI->has_codec = false;
1798 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1801 #if 0
1802 /* Check if a buffer desync has happened, log it and stop playback. */
1803 if (buf_ridx != CUR_TI->buf_idx)
1805 int offset = CUR_TI->buf_idx - buf_ridx;
1806 size_t new_used = FILEBUFUSED - offset;
1808 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1809 logf("Used off:%d",FILEBUFUSED - new_used);
1811 /* This is a fatal internal error and it's not safe to
1812 * continue playback. */
1813 ci.stop_codec = true;
1814 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1816 #endif
1819 static inline void codec_gapless_track_change(void) {
1820 /* callback keeps the progress bar moving while the pcmbuf empties */
1821 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1822 /* set the pcmbuf callback for when the track really changes */
1823 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1826 static inline void codec_crossfade_track_change(void) {
1827 /* Initiate automatic crossfade mode */
1828 pcmbuf_crossfade_init(false);
1829 /* Notify the wps that the track change starts now */
1830 codec_track_changed();
1833 static void codec_track_skip_done(bool was_manual)
1835 int crossfade_mode = global_settings.crossfade;
1837 /* Manual track change (always crossfade or flush audio). */
1838 if (was_manual)
1840 pcmbuf_crossfade_init(true);
1841 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1842 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1844 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1845 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1846 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1848 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1850 if (global_settings.playlist_shuffle)
1851 /* shuffle mode is on, so crossfade: */
1852 codec_crossfade_track_change();
1853 else
1854 /* shuffle mode is off, so do a gapless track change */
1855 codec_gapless_track_change();
1857 else
1858 /* normal crossfade: */
1859 codec_crossfade_track_change();
1861 else
1862 /* normal gapless playback. */
1863 codec_gapless_track_change();
1866 static bool codec_load_next_track(void)
1868 intptr_t result = Q_CODEC_REQUEST_FAILED;
1870 prev_track_elapsed = CUR_TI->id3.elapsed;
1872 if (ci.seek_time)
1873 codec_seek_complete_callback();
1875 #ifdef AB_REPEAT_ENABLE
1876 ab_end_of_track_report();
1877 #endif
1879 logf("Request new track");
1881 if (ci.new_track == 0)
1883 ci.new_track++;
1884 automatic_skip = true;
1887 if (!ci.stop_codec)
1889 trigger_cpu_boost();
1890 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1891 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1894 switch (result)
1896 case Q_CODEC_REQUEST_COMPLETE:
1897 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1898 codec_track_skip_done(!automatic_skip);
1899 return true;
1901 case Q_CODEC_REQUEST_FAILED:
1902 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1903 ci.new_track = 0;
1904 ci.stop_codec = true;
1905 return false;
1907 default:
1908 LOGFQUEUE("codec |< default");
1909 ci.stop_codec = true;
1910 return false;
1914 static bool codec_request_next_track_callback(void)
1916 int prev_codectype;
1918 if (ci.stop_codec || !playing)
1919 return false;
1921 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1923 if (!codec_load_next_track())
1924 return false;
1926 /* Check if the next codec is the same file. */
1927 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1929 logf("New track loaded");
1930 codec_discard_codec_callback();
1931 return true;
1933 else
1935 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1936 return false;
1940 static void codec_thread(void)
1942 struct event ev;
1943 int status;
1944 size_t wrap;
1946 while (1) {
1947 status = 0;
1948 queue_wait(&codec_queue, &ev);
1950 switch (ev.id) {
1951 case Q_CODEC_LOAD_DISK:
1952 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1953 audio_codec_loaded = true;
1954 #ifdef PLAYBACK_VOICE
1955 /* Don't sent messages to voice codec if it's already swapped
1956 out or it will never get this */
1957 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1959 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1960 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1962 mutex_lock(&mutex_codecthread);
1963 #endif
1964 set_current_codec(CODEC_IDX_AUDIO);
1965 ci.stop_codec = false;
1966 status = codec_load_file((const char *)ev.data, &ci);
1967 #ifdef PLAYBACK_VOICE
1968 mutex_unlock(&mutex_codecthread);
1969 #endif
1970 break ;
1972 case Q_CODEC_LOAD:
1973 LOGFQUEUE("codec < Q_CODEC_LOAD");
1974 if (!CUR_TI->has_codec) {
1975 logf("Codec slot is empty!");
1976 /* Wait for the pcm buffer to go empty */
1977 while (pcm_is_playing())
1978 yield();
1979 /* This must be set to prevent an infinite loop */
1980 ci.stop_codec = true;
1981 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1982 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1983 break ;
1986 audio_codec_loaded = true;
1987 #ifdef PLAYBACK_VOICE
1988 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1990 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1991 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1993 mutex_lock(&mutex_codecthread);
1994 #endif
1995 set_current_codec(CODEC_IDX_AUDIO);
1996 ci.stop_codec = false;
1997 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
1998 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
1999 &filebuf[0], wrap, &ci);
2000 #ifdef PLAYBACK_VOICE
2001 mutex_unlock(&mutex_codecthread);
2002 #endif
2003 break ;
2005 #ifdef AUDIO_HAVE_RECORDING
2006 case Q_ENCODER_LOAD_DISK:
2007 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2008 audio_codec_loaded = false; /* Not audio codec! */
2009 #ifdef PLAYBACK_VOICE
2010 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2012 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2013 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2015 mutex_lock(&mutex_codecthread);
2016 #endif
2017 logf("loading encoder");
2018 set_current_codec(CODEC_IDX_AUDIO);
2019 ci.stop_encoder = false;
2020 status = codec_load_file((const char *)ev.data, &ci);
2021 #ifdef PLAYBACK_VOICE
2022 mutex_unlock(&mutex_codecthread);
2023 #endif
2024 logf("encoder stopped");
2025 break;
2026 #endif /* AUDIO_HAVE_RECORDING */
2028 #ifndef SIMULATOR
2029 case SYS_USB_CONNECTED:
2030 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2031 queue_clear(&codec_queue);
2032 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2033 usb_wait_for_disconnect(&codec_queue);
2034 break;
2035 #endif
2037 default:
2038 LOGFQUEUE("codec < default");
2041 if (audio_codec_loaded)
2043 if (ci.stop_codec)
2045 status = CODEC_OK;
2046 if (!playing)
2047 pcmbuf_play_stop();
2050 audio_codec_loaded = false;
2053 switch (ev.id) {
2054 case Q_CODEC_LOAD_DISK:
2055 case Q_CODEC_LOAD:
2056 LOGFQUEUE("codec < Q_CODEC_LOAD");
2057 if (playing)
2059 if (ci.new_track || status != CODEC_OK)
2061 if (!ci.new_track)
2063 logf("Codec failure");
2064 gui_syncsplash(HZ*2, "Codec failure");
2067 if (!codec_load_next_track())
2069 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2070 /* End of playlist */
2071 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2072 break;
2075 else
2077 logf("Codec finished");
2078 if (ci.stop_codec)
2080 /* Wait for the audio to stop playing before
2081 * triggering the WPS exit */
2082 while(pcm_is_playing())
2084 CUR_TI->id3.elapsed =
2085 CUR_TI->id3.length - pcmbuf_get_latency();
2086 sleep(1);
2088 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2089 /* End of playlist */
2090 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2091 break;
2095 if (CUR_TI->has_codec)
2097 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2098 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2100 else
2102 const char *codec_fn =
2103 get_codec_filename(CUR_TI->id3.codectype);
2104 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2105 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2106 (intptr_t)codec_fn);
2109 break;
2111 #ifdef AUDIO_HAVE_RECORDING
2112 case Q_ENCODER_LOAD_DISK:
2113 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2115 if (status == CODEC_OK)
2116 break;
2118 logf("Encoder failure");
2119 gui_syncsplash(HZ*2, "Encoder failure");
2121 if (ci.enc_codec_loaded < 0)
2122 break;
2124 logf("Encoder failed to load");
2125 ci.enc_codec_loaded = -1;
2126 break;
2127 #endif /* AUDIO_HAVE_RECORDING */
2129 default:
2130 LOGFQUEUE("codec < default");
2132 } /* end switch */
2137 /* --- Audio thread --- */
2139 static bool audio_filebuf_is_lowdata(void)
2141 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
2144 static bool audio_have_tracks(void)
2146 return track_ridx != track_widx || CUR_TI->filesize;
2149 static bool audio_have_free_tracks(void)
2151 if (track_widx < track_ridx)
2152 return track_widx + 1 < track_ridx;
2153 else if (track_ridx == 0)
2154 return track_widx < MAX_TRACK - 1;
2156 return true;
2159 int audio_track_count(void)
2161 if (audio_have_tracks())
2163 int relative_track_widx = track_widx;
2165 if (track_ridx > track_widx)
2166 relative_track_widx += MAX_TRACK;
2168 return relative_track_widx - track_ridx + 1;
2171 return 0;
2174 long audio_filebufused(void)
2176 return (long) FILEBUFUSED;
2179 /* Count the data BETWEEN the selected tracks */
2180 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2182 size_t amount = 0;
2183 bool need_wrap = to_track < from_track;
2185 while (1)
2187 if (++from_track >= MAX_TRACK)
2189 from_track -= MAX_TRACK;
2190 need_wrap = false;
2193 if (from_track >= to_track && !need_wrap)
2194 break;
2196 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2198 return amount;
2201 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2203 size_t amount;
2205 /* Start with the remainder of the previously playing track */
2206 amount = tracks[old_track_ridx].filesize - ci.curpos;
2207 /* Then collect all data from tracks in between them */
2208 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2209 logf("bwf:%ldB", (long) amount);
2211 if (amount > FILEBUFUSED)
2212 return false;
2214 /* Wind the buffer to the beginning of the target track or its codec */
2215 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2217 return true;
2220 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2222 /* Available buffer data */
2223 size_t buf_back;
2224 /* Start with the previously playing track's data and our data */
2225 size_t amount;
2227 amount = ci.curpos;
2228 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2230 /* If we're not just resetting the current track */
2231 if (new_track_ridx != old_track_ridx)
2233 /* Need to wind to before the old track's codec and our filesize */
2234 amount += tracks[old_track_ridx].codecsize;
2235 amount += tracks[new_track_ridx].filesize;
2237 /* Rewind the old track to its beginning */
2238 tracks[old_track_ridx].available =
2239 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2242 /* If the codec was ever buffered */
2243 if (tracks[new_track_ridx].codecsize)
2245 /* Add the codec to the needed size */
2246 amount += tracks[new_track_ridx].codecsize;
2247 tracks[new_track_ridx].has_codec = true;
2250 /* Then collect all data from tracks between new and old */
2251 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2253 /* Do we have space to make this skip? */
2254 if (amount > buf_back)
2255 return false;
2257 logf("bwb:%ldB",amount);
2259 /* Rewind the buffer to the beginning of the target track or its codec */
2260 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2262 /* Reset to the beginning of the new track */
2263 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2265 return true;
2268 static void audio_update_trackinfo(void)
2270 ci.filesize = CUR_TI->filesize;
2271 CUR_TI->id3.elapsed = 0;
2272 CUR_TI->id3.offset = 0;
2273 ci.id3 = &CUR_TI->id3;
2274 ci.curpos = 0;
2275 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2278 /* Yield to codecs for as long as possible if they are in need of data
2279 * return true if the caller should break to let the audio thread process
2280 * new events */
2281 static bool audio_yield_codecs(void)
2283 yield();
2285 if (!queue_empty(&audio_queue))
2286 return true;
2288 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2289 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2291 if (filling)
2292 yield();
2293 else
2294 sleep(2);
2296 if (!queue_empty(&audio_queue))
2297 return true;
2300 return false;
2303 static void audio_clear_track_entries(bool clear_unbuffered)
2305 int cur_idx = track_widx;
2306 int last_idx = -1;
2308 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2310 /* Loop over all tracks from write-to-read */
2311 while (1)
2313 cur_idx++;
2314 cur_idx &= MAX_TRACK_MASK;
2316 if (cur_idx == track_ridx)
2317 break;
2319 /* If the track is buffered, conditionally clear/notify,
2320 * otherwise clear the track if that option is selected */
2321 if (tracks[cur_idx].event_sent)
2323 if (last_idx >= 0)
2325 /* If there is an unbuffer callback, call it, otherwise,
2326 * just clear the track */
2327 if (track_unbuffer_callback)
2328 track_unbuffer_callback(&tracks[last_idx].id3, false);
2330 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2332 last_idx = cur_idx;
2334 else if (clear_unbuffered)
2335 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2338 /* We clear the previous instance of a buffered track throughout
2339 * the above loop to facilitate 'last' detection. Clear/notify
2340 * the last track here */
2341 if (last_idx >= 0)
2343 if (track_unbuffer_callback)
2344 track_unbuffer_callback(&tracks[last_idx].id3, true);
2345 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2349 /* FIXME: This code should be made more generic and move to metadata.c */
2350 static void audio_strip_tags(void)
2352 int i;
2353 static const unsigned char tag[] = "TAG";
2354 static const unsigned char apetag[] = "APETAGEX";
2355 size_t tag_idx;
2356 size_t cur_idx;
2357 size_t len, version;
2359 tag_idx = RINGBUF_SUB(buf_widx, 128);
2361 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2363 cur_idx = tag_idx;
2364 for(i = 0;i < 3;i++)
2366 if(filebuf[cur_idx] != tag[i])
2367 goto strip_ape_tag;
2369 cur_idx = RINGBUF_ADD(cur_idx, 1);
2372 /* Skip id3v1 tag */
2373 logf("Skipping ID3v1 tag");
2374 buf_widx = tag_idx;
2375 tracks[track_widx].available -= 128;
2376 tracks[track_widx].filesize -= 128;
2379 strip_ape_tag:
2380 /* Check for APE tag (look for the APE tag footer) */
2381 tag_idx = RINGBUF_SUB(buf_widx, 32);
2383 if (FILEBUFUSED > 32 && tag_idx > buf_ridx)
2385 cur_idx = tag_idx;
2386 for(i = 0;i < 8;i++)
2388 if(filebuf[cur_idx] != apetag[i])
2389 return;
2391 cur_idx = RINGBUF_ADD(cur_idx, 1);
2394 /* Read the version and length from the footer */
2395 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2396 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2397 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2398 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2399 if (version == 2000)
2400 len += 32; /* APEv2 has a 32 byte header */
2402 /* Skip APE tag */
2403 if (FILEBUFUSED > len)
2405 logf("Skipping APE tag (%ldB)", len);
2406 buf_widx = RINGBUF_SUB(buf_widx, len);
2407 tracks[track_widx].available -= len;
2408 tracks[track_widx].filesize -= len;
2413 /* Returns true if a whole file is read, false otherwise */
2414 static bool audio_read_file(size_t minimum)
2416 bool ret_val = false;
2418 /* If we're called and no file is open, this is an error */
2419 if (current_fd < 0)
2421 logf("Bad fd in arf");
2422 /* Give some hope of miraculous recovery by forcing a track reload */
2423 tracks[track_widx].filesize = 0;
2424 /* Stop this buffering run */
2425 return ret_val;
2428 trigger_cpu_boost();
2429 while (tracks[track_widx].filerem > 0)
2431 size_t copy_n;
2432 int overlap;
2433 int rc;
2435 /* copy_n is the largest chunk that is safe to read */
2436 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2438 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2439 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2440 break;
2442 /* rc is the actual amount read */
2443 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2445 if (rc < 0)
2447 logf("File ended %ldB early", tracks[track_widx].filerem);
2448 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2449 tracks[track_widx].filerem = 0;
2450 break;
2453 /* How much of the playing track did we overwrite */
2454 if (buf_widx == CUR_TI->buf_idx)
2456 /* Special handling; zero or full overlap? */
2457 if (track_widx == track_ridx && CUR_TI->available == 0)
2458 overlap = 0;
2459 else
2460 overlap = rc;
2462 else
2463 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2465 if ((unsigned)rc > tracks[track_widx].filerem)
2467 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2468 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2469 tracks[track_widx].filerem = rc;
2472 /* Advance buffer */
2473 buf_widx = RINGBUF_ADD(buf_widx, rc);
2474 tracks[track_widx].available += rc;
2475 tracks[track_widx].filerem -= rc;
2477 /* If we write into the playing track, adjust it's buffer info */
2478 if (overlap > 0)
2480 CUR_TI->buf_idx += overlap;
2481 CUR_TI->start_pos += overlap;
2484 /* For a rebuffer, fill at least this minimum */
2485 if (minimum > (unsigned)rc)
2486 minimum -= rc;
2487 /* Let the codec process up to the watermark */
2488 /* Break immediately if this is a quick buffer, or there is an event */
2489 else if (minimum || audio_yield_codecs())
2491 /* Exit quickly, but don't stop the overall buffering process */
2492 ret_val = true;
2493 break;
2497 if (tracks[track_widx].filerem == 0)
2499 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2500 close(current_fd);
2501 current_fd = -1;
2502 audio_strip_tags();
2504 track_widx++;
2505 track_widx &= MAX_TRACK_MASK;
2507 tracks[track_widx].filesize = 0;
2508 return true;
2510 else
2512 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2513 tracks[track_widx].filesize - tracks[track_widx].filerem);
2514 return ret_val;
2518 static bool audio_loadcodec(bool start_play)
2520 size_t size = 0;
2521 int fd;
2522 int rc;
2523 size_t copy_n;
2524 int prev_track;
2525 char codec_path[MAX_PATH]; /* Full path to codec */
2527 const char * codec_fn =
2528 get_codec_filename(tracks[track_widx].id3.codectype);
2529 if (codec_fn == NULL)
2530 return false;
2532 tracks[track_widx].has_codec = false;
2534 if (start_play)
2536 /* Load the codec directly from disk and save some memory. */
2537 track_ridx = track_widx;
2538 ci.filesize = CUR_TI->filesize;
2539 ci.id3 = &CUR_TI->id3;
2540 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2541 ci.curpos = 0;
2542 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2543 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2544 return true;
2546 else
2548 /* If we already have another track than this one buffered */
2549 if (track_widx != track_ridx)
2551 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2553 /* If the previous codec is the same as this one, there is no need
2554 * to put another copy of it on the file buffer */
2555 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2556 get_codec_base_type(tracks[prev_track].id3.codectype)
2557 && audio_codec_loaded)
2559 logf("Reusing prev. codec");
2560 return true;
2565 codec_get_full_path(codec_path, codec_fn);
2567 fd = open(codec_path, O_RDONLY);
2568 if (fd < 0)
2570 logf("Codec doesn't exist!");
2571 return false;
2574 tracks[track_widx].codecsize = filesize(fd);
2576 /* Never load a partial codec */
2577 if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0)
2579 logf("Not enough space");
2580 close(fd);
2581 return false;
2584 while (size < tracks[track_widx].codecsize)
2586 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2587 rc = read(fd, &filebuf[buf_widx], copy_n);
2588 if (rc < 0)
2590 close(fd);
2591 /* This is an error condition, likely the codec file is corrupt */
2592 logf("Partial codec loaded");
2593 /* Must undo the buffer write of the partial codec */
2594 buf_widx = RINGBUF_SUB(buf_widx, size);
2595 tracks[track_widx].codecsize = 0;
2596 return false;
2599 buf_widx = RINGBUF_ADD(buf_widx, rc);
2601 size += rc;
2604 tracks[track_widx].has_codec = true;
2606 close(fd);
2607 logf("Done: %ldB", size);
2609 return true;
2612 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2613 static void audio_set_elapsed(struct mp3entry* id3)
2615 unsigned long offset = id3->offset > id3->first_frame_offset ?
2616 id3->offset - id3->first_frame_offset : 0;
2618 if ( id3->vbr ) {
2619 if ( id3->has_toc ) {
2620 /* calculate elapsed time using TOC */
2621 int i;
2622 unsigned int remainder, plen, relpos, nextpos;
2624 /* find wich percent we're at */
2625 for (i=0; i<100; i++ )
2626 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2627 break;
2629 i--;
2630 if (i < 0)
2631 i = 0;
2633 relpos = id3->toc[i];
2635 if (i < 99)
2636 nextpos = id3->toc[i+1];
2637 else
2638 nextpos = 256;
2640 remainder = offset - (relpos * (id3->filesize / 256));
2642 /* set time for this percent (divide before multiply to prevent
2643 overflow on long files. loss of precision is negligible on
2644 short files) */
2645 id3->elapsed = i * (id3->length / 100);
2647 /* calculate remainder time */
2648 plen = (nextpos - relpos) * (id3->filesize / 256);
2649 id3->elapsed += (((remainder * 100) / plen) *
2650 (id3->length / 10000));
2652 else {
2653 /* no TOC exists. set a rough estimate using average bitrate */
2654 int tpk = id3->length /
2655 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2656 1024);
2657 id3->elapsed = offset / 1024 * tpk;
2660 else
2662 /* constant bitrate, use exact calculation */
2663 if (id3->bitrate != 0)
2664 id3->elapsed = offset / (id3->bitrate / 8);
2668 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2670 char *trackname;
2671 off_t size;
2672 char msgbuf[80];
2674 /* Stop buffer filling if there is no free track entries.
2675 Don't fill up the last track entry (we wan't to store next track
2676 metadata there). */
2677 if (!audio_have_free_tracks())
2679 logf("No free tracks");
2680 return false;
2683 if (current_fd >= 0)
2685 logf("Nonzero fd in alt");
2686 close(current_fd);
2687 current_fd = -1;
2690 last_peek_offset++;
2691 peek_again:
2692 logf("Buffering track:%d/%d", track_widx, track_ridx);
2693 /* Get track name from current playlist read position. */
2694 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2696 /* Handle broken playlists. */
2697 current_fd = open(trackname, O_RDONLY);
2698 if (current_fd < 0)
2700 logf("Open failed");
2701 /* Skip invalid entry from playlist. */
2702 playlist_skip_entry(NULL, last_peek_offset);
2704 else
2705 break;
2708 if (!trackname)
2710 logf("End-of-playlist");
2711 playlist_end = true;
2712 return false;
2715 /* Initialize track entry. */
2716 size = filesize(current_fd);
2717 tracks[track_widx].filerem = size;
2718 tracks[track_widx].filesize = size;
2719 tracks[track_widx].available = 0;
2721 /* Set default values */
2722 if (start_play)
2724 int last_codec = current_codec;
2726 set_current_codec(CODEC_IDX_AUDIO);
2727 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2728 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2729 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2730 dsp_configure(DSP_RESET, 0);
2731 set_current_codec(last_codec);
2734 /* Get track metadata if we don't already have it. */
2735 if (!tracks[track_widx].taginfo_ready)
2737 if (get_metadata(&tracks[track_widx],current_fd,trackname,v1first))
2739 if (start_play)
2741 track_changed = true;
2742 playlist_update_resume_info(audio_current_track());
2745 else
2747 logf("mde:%s!",trackname);
2749 /* Set filesize to zero to indicate no file was loaded. */
2750 tracks[track_widx].filesize = 0;
2751 tracks[track_widx].filerem = 0;
2752 close(current_fd);
2753 current_fd = -1;
2755 /* Skip invalid entry from playlist. */
2756 playlist_skip_entry(NULL, last_peek_offset);
2757 tracks[track_widx].taginfo_ready = false;
2758 goto peek_again;
2763 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2765 char cuepath[MAX_PATH];
2766 strncpy(cuepath, trackname, MAX_PATH);
2767 char *dot = strrchr(cuepath, '.');
2768 strcpy(dot, ".cue");
2770 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2772 if (parse_cuesheet(cuepath, cue))
2774 strcpy((cue)->audio_filename, trackname);
2775 if (start_play)
2776 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2780 /* Load the codec. */
2781 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2782 if (!audio_loadcodec(start_play))
2784 /* Set filesize to zero to indicate no file was loaded. */
2785 tracks[track_widx].filesize = 0;
2786 tracks[track_widx].filerem = 0;
2787 close(current_fd);
2788 current_fd = -1;
2790 if (tracks[track_widx].codecsize)
2792 /* No space for codec on buffer, not an error */
2793 tracks[track_widx].codecsize = 0;
2794 return false;
2797 /* This is an error condition, either no codec was found, or reading
2798 * the codec file failed part way through, either way, skip the track */
2799 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2800 /* We should not use gui_syncplash from audio thread! */
2801 gui_syncsplash(HZ*2, msgbuf);
2802 /* Skip invalid entry from playlist. */
2803 playlist_skip_entry(NULL, last_peek_offset);
2804 tracks[track_widx].taginfo_ready = false;
2805 goto peek_again;
2808 tracks[track_widx].start_pos = 0;
2809 set_filebuf_watermark(buffer_margin);
2810 tracks[track_widx].id3.elapsed = 0;
2812 if (offset > 0)
2814 switch (tracks[track_widx].id3.codectype) {
2815 case AFMT_MPA_L1:
2816 case AFMT_MPA_L2:
2817 case AFMT_MPA_L3:
2818 lseek(current_fd, offset, SEEK_SET);
2819 tracks[track_widx].id3.offset = offset;
2820 audio_set_elapsed(&tracks[track_widx].id3);
2821 tracks[track_widx].filerem = size - offset;
2822 ci.curpos = offset;
2823 tracks[track_widx].start_pos = offset;
2824 break;
2826 case AFMT_WAVPACK:
2827 lseek(current_fd, offset, SEEK_SET);
2828 tracks[track_widx].id3.offset = offset;
2829 tracks[track_widx].id3.elapsed =
2830 tracks[track_widx].id3.length / 2;
2831 tracks[track_widx].filerem = size - offset;
2832 ci.curpos = offset;
2833 tracks[track_widx].start_pos = offset;
2834 break;
2836 case AFMT_OGG_VORBIS:
2837 case AFMT_SPEEX:
2838 case AFMT_FLAC:
2839 case AFMT_PCM_WAV:
2840 case AFMT_A52:
2841 case AFMT_AAC:
2842 case AFMT_MPC:
2843 tracks[track_widx].id3.offset = offset;
2844 break;
2848 logf("alt:%s", trackname);
2849 tracks[track_widx].buf_idx = buf_widx;
2851 return audio_read_file(rebuffer);
2854 static bool audio_read_next_metadata(void)
2856 int fd;
2857 char *trackname;
2858 int next_idx;
2859 int status;
2861 next_idx = track_widx;
2862 if (tracks[next_idx].taginfo_ready)
2864 next_idx++;
2865 next_idx &= MAX_TRACK_MASK;
2867 if (tracks[next_idx].taginfo_ready)
2868 return true;
2871 trackname = playlist_peek(last_peek_offset + 1);
2872 if (!trackname)
2873 return false;
2875 fd = open(trackname, O_RDONLY);
2876 if (fd < 0)
2877 return false;
2879 status = get_metadata(&tracks[next_idx],fd,trackname,v1first);
2880 /* Preload the glyphs in the tags */
2881 if (status)
2883 if (tracks[next_idx].id3.title)
2884 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2885 if (tracks[next_idx].id3.artist)
2886 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2887 if (tracks[next_idx].id3.album)
2888 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2890 close(fd);
2892 return status;
2895 /* Send callback events to notify about new tracks. */
2896 static void audio_generate_postbuffer_events(void)
2898 int cur_idx;
2899 int last_idx = -1;
2901 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2903 if (audio_have_tracks())
2905 cur_idx = track_ridx;
2907 while (1) {
2908 if (!tracks[cur_idx].event_sent)
2910 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2912 /* Mark the event 'sent' even if we don't really send one */
2913 tracks[last_idx].event_sent = true;
2914 if (track_buffer_callback)
2915 track_buffer_callback(&tracks[last_idx].id3, false);
2917 last_idx = cur_idx;
2919 if (cur_idx == track_widx)
2920 break;
2921 cur_idx++;
2922 cur_idx &= MAX_TRACK_MASK;
2925 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2927 tracks[last_idx].event_sent = true;
2928 if (track_buffer_callback)
2929 track_buffer_callback(&tracks[last_idx].id3, true);
2934 static bool audio_initialize_buffer_fill(bool clear_tracks)
2936 /* Don't initialize if we're already initialized */
2937 if (filling)
2938 return true;
2940 logf("Starting buffer fill");
2942 /* Set the filling flag true before calling audio_clear_tracks as that
2943 * function can yield and we start looping. */
2944 filling = true;
2946 if (clear_tracks)
2947 audio_clear_track_entries(false);
2949 /* Save the current resume position once. */
2950 playlist_update_resume_info(audio_current_track());
2952 return true;
2955 static void audio_fill_file_buffer(
2956 bool start_play, bool rebuffer, size_t offset)
2958 bool had_next_track = audio_next_track() != NULL;
2959 bool continue_buffering;
2961 /* Must reset the buffer before use if trashed or voice only - voice
2962 file size shouldn't have changed so we can go straight from
2963 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2964 if (buffer_state != BUFFER_STATE_INITIALIZED)
2965 audio_reset_buffer();
2967 if (!audio_initialize_buffer_fill(!start_play))
2968 return ;
2970 /* If we have a partially buffered track, continue loading,
2971 * otherwise load a new track */
2972 if (tracks[track_widx].filesize > 0)
2973 continue_buffering = audio_read_file(rebuffer);
2974 else
2975 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2977 if (!had_next_track && audio_next_track())
2978 track_changed = true;
2980 /* If we're done buffering */
2981 if (!continue_buffering)
2983 audio_read_next_metadata();
2985 audio_generate_postbuffer_events();
2986 filling = false;
2988 #ifndef SIMULATOR
2989 ata_sleep();
2990 #endif
2994 static void audio_rebuffer(void)
2996 logf("Forcing rebuffer");
2998 /* Stop in progress fill, and clear open file descriptor */
2999 if (current_fd >= 0)
3001 close(current_fd);
3002 current_fd = -1;
3004 filling = false;
3006 /* Reset buffer and track pointers */
3007 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3008 track_widx = track_ridx;
3009 audio_clear_track_entries(true);
3010 CUR_TI->available = 0;
3012 /* Fill the buffer */
3013 last_peek_offset = -1;
3014 CUR_TI->filesize = 0;
3015 CUR_TI->start_pos = 0;
3016 ci.curpos = 0;
3018 if (!CUR_TI->taginfo_ready)
3019 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
3021 audio_fill_file_buffer(false, true, 0);
3024 static int audio_check_new_track(void)
3026 int track_count = audio_track_count();
3027 int old_track_ridx = track_ridx;
3028 bool forward;
3030 if (dir_skip)
3032 dir_skip = false;
3033 if (playlist_next_dir(ci.new_track))
3035 ci.new_track = 0;
3036 CUR_TI->taginfo_ready = false;
3037 audio_rebuffer();
3038 goto skip_done;
3040 else
3042 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3043 return Q_CODEC_REQUEST_FAILED;
3047 if (new_playlist)
3048 ci.new_track = 0;
3050 /* If the playlist isn't that big */
3051 if (!playlist_check(ci.new_track))
3053 if (ci.new_track >= 0)
3055 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3056 return Q_CODEC_REQUEST_FAILED;
3058 /* Find the beginning backward if the user over-skips it */
3059 while (!playlist_check(++ci.new_track))
3060 if (ci.new_track >= 0)
3062 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3063 return Q_CODEC_REQUEST_FAILED;
3066 /* Update the playlist */
3067 last_peek_offset -= ci.new_track;
3069 if (playlist_next(ci.new_track) < 0)
3071 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3072 return Q_CODEC_REQUEST_FAILED;
3075 if (new_playlist)
3077 ci.new_track = 1;
3078 new_playlist = false;
3081 /* Save the old track */
3082 prev_ti = CUR_TI;
3084 /* Move to the new track */
3085 track_ridx += ci.new_track;
3086 track_ridx &= MAX_TRACK_MASK;
3088 if (automatic_skip)
3089 playlist_end = false;
3091 track_changed = !automatic_skip;
3093 /* If it is not safe to even skip this many track entries */
3094 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3096 ci.new_track = 0;
3097 CUR_TI->taginfo_ready = false;
3098 audio_rebuffer();
3099 goto skip_done;
3102 forward = ci.new_track > 0;
3103 ci.new_track = 0;
3105 /* If the target track is clearly not in memory */
3106 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3108 audio_rebuffer();
3109 goto skip_done;
3112 /* The track may be in memory, see if it really is */
3113 if (forward)
3115 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3116 audio_rebuffer();
3118 else
3120 int cur_idx = track_ridx;
3121 bool taginfo_ready = true;
3122 bool wrap = track_ridx > old_track_ridx;
3124 while (1)
3126 cur_idx++;
3127 cur_idx &= MAX_TRACK_MASK;
3128 if (!(wrap || cur_idx < old_track_ridx))
3129 break;
3131 /* If we hit a track in between without valid tag info, bail */
3132 if (!tracks[cur_idx].taginfo_ready)
3134 taginfo_ready = false;
3135 break;
3138 tracks[cur_idx].available = tracks[cur_idx].filesize;
3139 if (tracks[cur_idx].codecsize)
3140 tracks[cur_idx].has_codec = true;
3142 if (taginfo_ready)
3144 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3145 audio_rebuffer();
3147 else
3149 CUR_TI->taginfo_ready = false;
3150 audio_rebuffer();
3154 skip_done:
3155 audio_update_trackinfo();
3156 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3157 return Q_CODEC_REQUEST_COMPLETE;
3160 static int audio_rebuffer_and_seek(size_t newpos)
3162 size_t real_preseek;
3163 int fd;
3164 char *trackname;
3166 /* (Re-)open current track's file handle. */
3167 trackname = playlist_peek(0);
3168 fd = open(trackname, O_RDONLY);
3169 if (fd < 0)
3171 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3172 return Q_CODEC_REQUEST_FAILED;
3175 if (current_fd >= 0)
3176 close(current_fd);
3177 current_fd = fd;
3179 playlist_end = false;
3181 ci.curpos = newpos;
3183 /* Clear codec buffer. */
3184 track_widx = track_ridx;
3185 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3187 last_peek_offset = 0;
3188 filling = false;
3189 audio_initialize_buffer_fill(true);
3191 /* This may have been tweaked by the id3v1 code */
3192 CUR_TI->filesize=filesize(fd);
3193 if (newpos > conf_preseek)
3195 CUR_TI->start_pos = newpos - conf_preseek;
3196 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3197 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3198 real_preseek = conf_preseek;
3200 else
3202 CUR_TI->start_pos = 0;
3203 CUR_TI->filerem = CUR_TI->filesize;
3204 real_preseek = newpos;
3207 CUR_TI->available = 0;
3209 audio_read_file(real_preseek);
3211 /* Account for the data we just read that is 'behind' us now */
3212 CUR_TI->available -= real_preseek;
3214 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3216 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3217 return Q_CODEC_REQUEST_COMPLETE;
3220 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3221 bool last_track))
3223 track_buffer_callback = handler;
3226 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3227 bool last_track))
3229 track_unbuffer_callback = handler;
3232 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3234 track_changed_callback = handler;
3237 unsigned long audio_prev_elapsed(void)
3239 return prev_track_elapsed;
3242 static void audio_stop_codec_flush(void)
3244 ci.stop_codec = true;
3245 pcmbuf_pause(true);
3247 while (audio_codec_loaded)
3248 yield();
3250 /* If the audio codec is not loaded any more, and the audio is still
3251 * playing, it is now and _only_ now safe to call this function from the
3252 * audio thread */
3253 if (pcm_is_playing())
3254 pcmbuf_play_stop();
3255 pcmbuf_pause(paused);
3258 static void audio_stop_playback(void)
3260 /* If we were playing, save resume information */
3261 if (playing)
3263 struct mp3entry *id3 = NULL;
3265 if (!playlist_end || !ci.stop_codec)
3267 /* Set this early, the outside code yields and may allow the codec
3268 to try to wait for a reply on a buffer wait */
3269 ci.stop_codec = true;
3270 id3 = audio_current_track();
3273 /* Save the current playing spot, or NULL if the playlist has ended */
3274 playlist_update_resume_info(id3);
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 defined(HAVE_RECORDING) || CONFIG_TUNER
3307 rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3308 #endif
3310 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3311 paused = false;
3312 audio_stop_codec_flush();
3314 track_changed = true;
3315 playlist_end = false;
3317 playing = true;
3319 ci.new_track = 0;
3320 ci.seek_time = 0;
3321 wps_offset = 0;
3323 if (current_fd >= 0)
3325 close(current_fd);
3326 current_fd = -1;
3329 sound_set_volume(global_settings.volume);
3330 track_widx = track_ridx = 0;
3331 buf_ridx = buf_widx = 0;
3333 /* Mark all entries null. */
3334 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3336 last_peek_offset = -1;
3338 /* Officially playing */
3339 queue_reply(&audio_queue, 1);
3341 audio_fill_file_buffer(true, false, offset);
3345 /* Invalidates all but currently playing track. */
3346 static void audio_invalidate_tracks(void)
3348 if (audio_have_tracks()) {
3349 last_peek_offset = 0;
3351 playlist_end = false;
3352 track_widx = track_ridx;
3353 /* Mark all other entries null (also buffered wrong metadata). */
3354 audio_clear_track_entries(true);
3356 /* If the current track is fully buffered, advance the write pointer */
3357 if (tracks[track_widx].filerem == 0)
3358 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3360 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3362 audio_read_next_metadata();
3366 static void audio_new_playlist(void)
3368 /* Prepare to start a new fill from the beginning of the playlist */
3369 last_peek_offset = -1;
3370 if (audio_have_tracks()) {
3371 playlist_end = false;
3372 track_widx = track_ridx;
3373 audio_clear_track_entries(true);
3375 track_widx++;
3376 track_widx &= MAX_TRACK_MASK;
3378 /* Stop reading the current track */
3379 CUR_TI->filerem = 0;
3380 close(current_fd);
3381 current_fd = -1;
3383 /* Mark the current track as invalid to prevent skipping back to it */
3384 CUR_TI->taginfo_ready = false;
3386 /* Invalidate the buffer other than the playing track */
3387 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3390 /* Signal the codec to initiate a track change forward */
3391 new_playlist = true;
3392 ci.new_track = 1;
3394 /* Officially playing */
3395 queue_reply(&audio_queue, 1);
3397 audio_fill_file_buffer(false, true, 0);
3400 static void audio_initiate_track_change(long direction)
3402 playlist_end = false;
3403 ci.new_track += direction;
3404 wps_offset -= direction;
3407 static void audio_initiate_dir_change(long direction)
3409 playlist_end = false;
3410 dir_skip = true;
3411 ci.new_track = direction;
3415 * Layout audio buffer as follows - iram buffer depends on target:
3416 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3418 static void audio_reset_buffer(void)
3420 /* see audio_get_recording_buffer if this is modified */
3421 logf("audio_reset_buffer");
3423 /* If the setup of anything allocated before the file buffer is
3424 changed, do check the adjustments after the buffer_alloc call
3425 as it will likely be affected and need sliding over */
3427 /* Initially set up file buffer as all space available */
3428 malloc_buf = audiobuf + talk_get_bufsize();
3429 /* Align the malloc buf to line size. Especially important to cf
3430 targets that do line reads/writes. */
3431 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3432 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3433 filebuflen = audiobufend - filebuf;
3435 /* Allow for codec swap space at end of audio buffer */
3436 if (talk_voice_required())
3438 /* Layout of swap buffer:
3439 * #ifdef IRAM_STEAL (dedicated iram_buf):
3440 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3441 * #else:
3442 * audiobuf...|dram_buf|iram_buf|audiobufend
3444 #ifdef PLAYBACK_VOICE
3445 /* Check for an absolutely nasty situation which should never,
3446 ever happen - frankly should just panic */
3447 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3449 logf("buffer reset with voice swapped");
3451 /* line align length which line aligns the calculations below since
3452 all sizes are also at least line aligned - needed for memswap128 */
3453 filebuflen &= ~15;
3454 #ifdef IRAM_STEAL
3455 filebuflen -= CODEC_SIZE;
3456 #else
3457 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3458 #endif
3459 /* Allocate buffers for swapping voice <=> audio */
3460 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3461 and out of the way of buffer usage or else a call to audio_get_buffer
3462 and subsequent buffer use might trash the swap space. A plugin
3463 initializing IRAM after getting the full buffer would present similar
3464 problem. Options include: failing the request if the other buffer
3465 has been obtained already or never allowing use of the voice IRAM
3466 buffer within the audio buffer. Using buffer_alloc basically
3467 implements the second in a more convenient way. */
3468 dram_buf = filebuf + filebuflen;
3470 #ifdef IRAM_STEAL
3471 /* Allocate voice IRAM swap buffer once */
3472 if (iram_buf == NULL)
3474 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3475 /* buffer_alloc moves audiobuf; this is safe because only the end
3476 * has been touched so far in this function and the address of
3477 * filebuf + filebuflen is not changed */
3478 malloc_buf += CODEC_IRAM_SIZE;
3479 filebuf += CODEC_IRAM_SIZE;
3480 filebuflen -= CODEC_IRAM_SIZE;
3482 #else
3483 /* Allocate iram_buf after dram_buf */
3484 iram_buf = dram_buf + CODEC_SIZE;
3485 #endif /* IRAM_STEAL */
3486 #endif /* PLAYBACK_VOICE */
3488 else
3490 #ifdef PLAYBACK_VOICE
3491 /* No swap buffers needed */
3492 iram_buf = NULL;
3493 dram_buf = NULL;
3494 #endif
3497 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3498 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3500 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3501 will already be line aligned */
3502 filebuflen &= ~3;
3504 /* Set the high watermark as 75% full...or 25% empty :) */
3505 #if MEM > 8
3506 high_watermark = 3*filebuflen / 4;
3507 #endif
3509 /* Clear any references to the file buffer */
3510 buffer_state = BUFFER_STATE_INITIALIZED;
3512 #ifdef ROCKBOX_HAS_LOGF
3513 /* Make sure everything adds up - yes, some info is a bit redundant but
3514 aids viewing and the sumation of certain variables should add up to
3515 the location of others. */
3517 size_t pcmbufsize;
3518 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3519 logf("mabuf: %08X", (unsigned)malloc_buf);
3520 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3521 logf("fbuf: %08X", (unsigned)filebuf);
3522 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3523 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3524 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3525 logf("pcmb: %08X", (unsigned)pcmbuf);
3526 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3527 if (dram_buf)
3529 logf("dramb: %08X", (unsigned)dram_buf);
3530 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3532 if (iram_buf)
3534 logf("iramb: %08X", (unsigned)iram_buf);
3535 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3538 #endif
3541 #if MEM > 8
3542 /* we dont want this rebuffering on targets with little ram
3543 because the disk may never spin down */
3544 static bool ata_fillbuffer_callback(void)
3546 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3547 return true;
3549 #endif
3551 static void audio_thread(void)
3553 struct event ev;
3555 pcm_postinit();
3557 #ifdef PLAYBACK_VOICE
3558 /* Unlock mutex that init stage locks before creating this thread */
3559 mutex_unlock(&mutex_codecthread);
3561 /* Buffers must be set up by now - should panic - really */
3562 if (buffer_state != BUFFER_STATE_INITIALIZED)
3564 logf("audio_thread start: no buffer");
3567 /* Have to wait for voice to load up or else the codec swap will be
3568 invalid when an audio codec is loaded */
3569 wait_for_voice_swap_in();
3570 #endif
3572 while (1)
3574 intptr_t result = 0;
3576 if (filling)
3578 queue_wait_w_tmo(&audio_queue, &ev, 0);
3579 if (ev.id == SYS_TIMEOUT)
3580 ev.id = Q_AUDIO_FILL_BUFFER;
3582 else
3584 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3585 #if MEM > 8
3586 if (playing && (ev.id == SYS_TIMEOUT) &&
3587 (FILEBUFUSED < high_watermark))
3588 register_ata_idle_func(ata_fillbuffer_callback);
3589 #endif
3592 switch (ev.id) {
3593 #if MEM > 8
3594 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3595 /* only fill if the disk is still spining */
3596 #ifndef SIMULATOR
3597 if (!ata_disk_is_active())
3598 break;
3599 #endif
3600 #endif /* MEM > 8 */
3601 /* else fall through to Q_AUDIO_FILL_BUFFER */
3602 case Q_AUDIO_FILL_BUFFER:
3603 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3604 if (!filling)
3605 if (!playing || playlist_end || ci.stop_codec)
3606 break;
3607 audio_fill_file_buffer(false, false, 0);
3608 break;
3610 case Q_AUDIO_PLAY:
3611 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3612 if (playing && ev.data <= 0)
3613 audio_new_playlist();
3614 else
3616 audio_stop_playback();
3617 audio_play_start((size_t)ev.data);
3619 break ;
3621 case Q_AUDIO_STOP:
3622 LOGFQUEUE("audio < Q_AUDIO_STOP");
3623 if (playing)
3624 audio_stop_playback();
3625 if (ev.data != 0)
3626 queue_clear(&audio_queue);
3627 break ;
3629 case Q_AUDIO_PAUSE:
3630 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3631 if (!playing)
3632 break;
3633 pcmbuf_pause((bool)ev.data);
3634 paused = (bool)ev.data;
3635 break ;
3637 case Q_AUDIO_SKIP:
3638 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3639 audio_initiate_track_change((long)ev.data);
3640 break;
3642 case Q_AUDIO_PRE_FF_REWIND:
3643 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3644 if (!playing)
3645 break;
3646 pcmbuf_pause(true);
3647 break;
3649 case Q_AUDIO_FF_REWIND:
3650 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3651 if (!playing)
3652 break ;
3653 ci.seek_time = (long)ev.data+1;
3654 break ;
3656 case Q_AUDIO_REBUFFER_SEEK:
3657 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3658 result = audio_rebuffer_and_seek(ev.data);
3659 break;
3661 case Q_AUDIO_CHECK_NEW_TRACK:
3662 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3663 result = audio_check_new_track();
3664 break;
3666 case Q_AUDIO_DIR_SKIP:
3667 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3668 playlist_end = false;
3669 audio_initiate_dir_change(ev.data);
3670 break;
3672 case Q_AUDIO_FLUSH:
3673 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3674 audio_invalidate_tracks();
3675 break ;
3677 case Q_AUDIO_TRACK_CHANGED:
3678 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3679 if (track_changed_callback)
3680 track_changed_callback(&CUR_TI->id3);
3681 track_changed = true;
3682 playlist_update_resume_info(audio_current_track());
3683 break ;
3685 #ifndef SIMULATOR
3686 case SYS_USB_CONNECTED:
3687 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3688 if (playing)
3689 audio_stop_playback();
3690 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3691 usb_wait_for_disconnect(&audio_queue);
3692 break ;
3693 #endif
3695 case SYS_TIMEOUT:
3696 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3697 break;
3699 default:
3700 LOGFQUEUE("audio < default");
3701 } /* end switch */
3703 queue_reply(&audio_queue, result);
3704 } /* end while */
3707 #ifdef ROCKBOX_HAS_LOGF
3708 static void audio_test_track_changed_event(struct mp3entry *id3)
3710 (void)id3;
3712 logf("tce:%s", id3->path);
3714 #endif
3716 /* Initialize the audio system - called from init() in main.c.
3717 * Last function because of all the references to internal symbols
3719 void audio_init(void)
3721 #ifdef PLAYBACK_VOICE
3722 static bool voicetagtrue = true;
3723 static struct mp3entry id3_voice;
3724 #endif
3726 /* Can never do this twice */
3727 if (audio_is_initialized)
3729 logf("audio: already initialized");
3730 return;
3733 logf("audio: initializing");
3735 /* Initialize queues before giving control elsewhere in case it likes
3736 to send messages. Thread creation will be delayed however so nothing
3737 starts running until ready if something yields such as talk_init. */
3738 #ifdef PLAYBACK_VOICE
3739 mutex_init(&mutex_codecthread);
3740 /* Take ownership of lock to prevent playback of anything before audio
3741 hardware is initialized - audio thread unlocks it after final init
3742 stage */
3743 mutex_lock(&mutex_codecthread);
3744 #endif
3745 queue_init(&audio_queue, true);
3746 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3747 queue_init(&codec_queue, true);
3749 pcm_init();
3751 #ifdef ROCKBOX_HAS_LOGF
3752 audio_set_track_changed_event(audio_test_track_changed_event);
3753 #endif
3755 /* Initialize codec api. */
3756 ci.read_filebuf = codec_filebuf_callback;
3757 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3758 ci.get_codec_memory = codec_get_memory_callback;
3759 ci.request_buffer = codec_request_buffer_callback;
3760 ci.advance_buffer = codec_advance_buffer_callback;
3761 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3762 ci.request_next_track = codec_request_next_track_callback;
3763 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3764 ci.seek_buffer = codec_seek_buffer_callback;
3765 ci.seek_complete = codec_seek_complete_callback;
3766 ci.set_elapsed = codec_set_elapsed_callback;
3767 ci.set_offset = codec_set_offset_callback;
3768 ci.configure = codec_configure_callback;
3769 ci.discard_codec = codec_discard_codec_callback;
3771 /* Initialize voice codec api. */
3772 #ifdef PLAYBACK_VOICE
3773 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3774 memset(&id3_voice, 0, sizeof(id3_voice));
3775 ci_voice.read_filebuf = voice_filebuf_callback;
3776 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3777 ci_voice.get_codec_memory = voice_get_memory_callback;
3778 ci_voice.request_buffer = voice_request_buffer_callback;
3779 ci_voice.advance_buffer = voice_advance_buffer_callback;
3780 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3781 ci_voice.request_next_track = voice_request_next_track_callback;
3782 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3783 ci_voice.seek_buffer = voice_seek_buffer_callback;
3784 ci_voice.seek_complete = voice_do_nothing;
3785 ci_voice.set_elapsed = voice_set_elapsed_callback;
3786 ci_voice.set_offset = voice_set_offset_callback;
3787 ci_voice.configure = voice_configure_callback;
3788 ci_voice.discard_codec = voice_do_nothing;
3789 ci_voice.taginfo_ready = &voicetagtrue;
3790 ci_voice.id3 = &id3_voice;
3791 id3_voice.frequency = 11200;
3792 id3_voice.length = 1000000L;
3793 #endif
3795 /* initialize the buffer */
3796 filebuf = audiobuf;
3798 /* audio_reset_buffer must to know the size of voice buffer so init
3799 talk first */
3800 talk_init();
3802 /* Create the threads late now that we shouldn't be yielding again before
3803 returning */
3804 codec_thread_p = create_thread(
3805 codec_thread, codec_stack, sizeof(codec_stack),
3806 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3807 IF_COP(, CPU, true));
3809 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
3810 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3811 IF_COP(, CPU, false));
3813 #ifdef PLAYBACK_VOICE
3814 /* TODO: Change this around when various speech codecs can be used */
3815 if (talk_voice_required())
3817 logf("Starting voice codec");
3818 queue_init(&voice_queue, true);
3819 create_thread(voice_thread, voice_stack,
3820 sizeof(voice_stack), voice_thread_name
3821 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false));
3823 #endif
3825 /* Set crossfade setting for next buffer init which should be about... */
3826 pcmbuf_crossfade_enable(global_settings.crossfade);
3828 /* ...now! Set up the buffers */
3829 audio_reset_buffer();
3831 /* Probably safe to say */
3832 audio_is_initialized = true;
3834 sound_settings_apply();
3835 #ifdef HAVE_WM8758
3836 eq_hw_enable(global_settings.eq_hw_enabled);
3837 #endif
3838 audio_set_buffer_margin(global_settings.buffer_margin);
3839 } /* audio_init */