Pong: small improvement in the c200 buttonmap; the left paddle is now controlled...
[Rockbox.git] / apps / playback.c
blob0fd1c21dafff3086a94addc73f6aabf9c0d5ba84
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
34 #include "system.h"
35 #include "thread.h"
36 #include "file.h"
37 #include "panic.h"
38 #include "memory.h"
39 #include "lcd.h"
40 #include "font.h"
41 #include "button.h"
42 #include "kernel.h"
43 #include "tree.h"
44 #include "debug.h"
45 #include "sprintf.h"
46 #include "settings.h"
47 #include "codecs.h"
48 #include "audio.h"
49 #include "logf.h"
50 #include "mp3_playback.h"
51 #include "usb.h"
52 #include "status.h"
53 #include "ata.h"
54 #include "screens.h"
55 #include "playlist.h"
56 #include "playback.h"
57 #include "pcmbuf.h"
58 #include "buffer.h"
59 #include "dsp.h"
60 #include "abrepeat.h"
61 #include "cuesheet.h"
62 #ifdef HAVE_TAGCACHE
63 #include "tagcache.h"
64 #endif
65 #ifdef HAVE_LCD_BITMAP
66 #include "icons.h"
67 #include "peakmeter.h"
68 #include "action.h"
69 #endif
70 #include "lang.h"
71 #include "bookmark.h"
72 #include "misc.h"
73 #include "sound.h"
74 #include "metadata.h"
75 #include "splash.h"
76 #include "talk.h"
77 #include "ata_idle_notify.h"
79 #ifdef HAVE_RECORDING
80 #include "recording.h"
81 #include "talk.h"
82 #endif
84 #ifdef HAVE_WM8758
85 #include "menus/eq_menu.h"
86 #endif
88 #define PLAYBACK_VOICE
91 /* default point to start buffer refill */
92 #define AUDIO_DEFAULT_WATERMARK (1024*512)
93 /* amount of data to read in one read() call */
94 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
95 /* point at which the file buffer will fight for CPU time */
96 #define AUDIO_FILEBUF_CRITICAL (1024*128)
97 /* amount of guess-space to allow for codecs that must hunt and peck
98 * for their correct seeek target, 32k seems a good size */
99 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
101 /* macros to enable logf for queues
102 logging on SYS_TIMEOUT can be disabled */
103 #ifdef SIMULATOR
104 /* Define this for logf output of all queuing except SYS_TIMEOUT */
105 #define PLAYBACK_LOGQUEUES
106 /* Define this to logf SYS_TIMEOUT messages */
107 #define PLAYBACK_LOGQUEUES_SYS_TIMEOUT
108 #endif
110 #ifdef PLAYBACK_LOGQUEUES
111 #define LOGFQUEUE logf
112 #else
113 #define LOGFQUEUE(...)
114 #endif
116 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
117 #define LOGFQUEUE_SYS_TIMEOUT logf
118 #else
119 #define LOGFQUEUE_SYS_TIMEOUT(...)
120 #endif
123 /* Define one constant that includes recording related functionality */
124 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
125 #define AUDIO_HAVE_RECORDING
126 #endif
128 enum {
129 Q_AUDIO_PLAY = 1,
130 Q_AUDIO_STOP,
131 Q_AUDIO_PAUSE,
132 Q_AUDIO_SKIP,
133 Q_AUDIO_PRE_FF_REWIND,
134 Q_AUDIO_FF_REWIND,
135 Q_AUDIO_REBUFFER_SEEK,
136 Q_AUDIO_CHECK_NEW_TRACK,
137 Q_AUDIO_FLUSH,
138 Q_AUDIO_TRACK_CHANGED,
139 Q_AUDIO_DIR_SKIP,
140 Q_AUDIO_POSTINIT,
141 Q_AUDIO_FILL_BUFFER,
142 #if MEM > 8
143 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
144 #endif
145 Q_CODEC_REQUEST_COMPLETE,
146 Q_CODEC_REQUEST_FAILED,
148 Q_VOICE_PLAY,
149 Q_VOICE_STOP,
151 Q_CODEC_LOAD,
152 Q_CODEC_LOAD_DISK,
154 #ifdef AUDIO_HAVE_RECORDING
155 Q_ENCODER_LOAD_DISK,
156 Q_ENCODER_RECORD,
157 #endif
160 /* As defined in plugins/lib/xxx2wav.h */
161 #if MEM > 1
162 #define MALLOC_BUFSIZE (512*1024)
163 #define GUARD_BUFSIZE (32*1024)
164 #else
165 #define MALLOC_BUFSIZE (100*1024)
166 #define GUARD_BUFSIZE (8*1024)
167 #endif
169 /* As defined in plugin.lds */
170 #if defined(CPU_PP)
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
174 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
175 #define CODEC_IRAM_SIZE ((size_t)0x10000)
176 #else
177 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
178 #define CODEC_IRAM_SIZE ((size_t)0xc000)
179 #endif
181 #ifndef IBSS_ATTR_VOICE_STACK
182 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
183 #endif
185 bool audio_is_initialized = false;
187 /* Variables are commented with the threads that use them: *
188 * A=audio, C=codec, V=voice. A suffix of - indicates that *
189 * the variable is read but not updated on that thread. */
190 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
192 /* Main state control */
193 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
194 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
195 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
196 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
198 /* Ring buffer where compressed audio and codecs are loaded */
199 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
200 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
201 /* FIXME: make filebuflen static */
202 size_t filebuflen = 0; /* Size of buffer (A/C-) */
203 /* FIXME: make buf_ridx (C/A-) */
204 static volatile size_t buf_ridx IDATA_ATTR = 0; /* Buffer read position (A/C)*/
205 static volatile size_t buf_widx IDATA_ATTR = 0; /* Buffer write position (A/C-) */
207 /* Possible arrangements of the buffer */
208 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
209 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
210 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
211 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
213 /* Compressed ring buffer helper macros */
214 /* Buffer pointer (p) plus value (v), wrapped if necessary */
215 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
216 /* Buffer pointer (p) minus value (v), wrapped if necessary */
217 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
218 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
219 #define RINGBUF_ADD_CROSS(p1,v,p2) \
220 ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
221 /* Bytes available in the buffer */
222 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
224 /* Track info structure about songs in the file buffer (A/C-) */
225 struct track_info {
226 struct mp3entry id3; /* TAG metadata */
227 char *codecbuf; /* Pointer to codec buffer */
228 size_t codecsize; /* Codec length in bytes */
229 bool has_codec; /* Does this track have a codec on the buffer */
231 size_t buf_idx; /* Pointer to the track's buffer */
232 size_t filerem; /* Remaining bytes of file NOT in buffer */
233 size_t filesize; /* File total length */
234 size_t start_pos; /* Position to first bytes of file in buffer */
235 volatile size_t available; /* Available bytes to read from buffer */
237 bool taginfo_ready; /* Is metadata read */
239 bool event_sent; /* Was this track's buffered event sent */
242 static struct track_info tracks[MAX_TRACK];
243 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
244 static int track_widx = 0; /* Track being buffered (A) */
246 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
247 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
249 /* Set by the audio thread when the current track information has updated
250 * and the WPS may need to update its cached information */
251 static bool track_changed = false;
253 /* Information used only for filling the buffer */
254 /* Playlist steps from playing track to next track to be buffered (A) */
255 static int last_peek_offset = 0;
256 /* Partially loaded track file handle to continue buffering (A) */
257 static int current_fd = -1;
259 /* Scrobbler support */
260 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
262 /* Track change controls */
263 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
264 static bool playlist_end = false; /* Has the current playlist ended? (A) */
265 static bool dir_skip = false; /* Is a directory skip pending? (A) */
266 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
267 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
268 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
270 /* Callbacks which applications or plugins may set */
271 /* When the playing track has changed from the user's perspective */
272 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
273 /* When a track has been buffered */
274 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
275 /* When a track's buffer has been overwritten or cleared */
276 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
278 /* Configuration */
279 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
280 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
281 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
282 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
283 #if MEM > 8
284 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
285 #endif
287 /* Multiple threads */
288 static void set_current_codec(int codec_idx);
289 /* Set the watermark to trigger buffer fill (A/C) FIXME */
290 static void set_filebuf_watermark(int seconds);
292 /* Audio thread */
293 static struct event_queue audio_queue NOCACHEBSS_ATTR;
294 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
295 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
296 static const char audio_thread_name[] = "audio";
298 static void audio_thread(void);
299 static void audio_initiate_track_change(long direction);
300 static bool audio_have_tracks(void);
301 static void audio_reset_buffer(void);
303 /* Codec thread */
304 extern struct codec_api ci;
305 static struct event_queue codec_queue NOCACHEBSS_ATTR;
306 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
307 IBSS_ATTR;
308 static const char codec_thread_name[] = "codec";
309 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
311 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
313 /* Voice thread */
314 #ifdef PLAYBACK_VOICE
316 extern struct codec_api ci_voice;
318 static struct thread_entry *voice_thread_p = NULL;
319 static struct event_queue voice_queue NOCACHEBSS_ATTR;
320 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
321 IBSS_ATTR_VOICE_STACK;
322 static const char voice_thread_name[] = "voice codec";
324 /* Voice codec swapping control */
325 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
327 #ifdef SIMULATOR
328 /* IRAM codec swap buffer for sim*/
329 static unsigned char sim_iram[CODEC_IRAM_SIZE];
330 #undef CODEC_IRAM_ORIGIN
331 #define CODEC_IRAM_ORIGIN sim_iram
332 #endif
334 /* iram_buf and dram_buf are either both NULL or both non-NULL */
335 /* Pointer to IRAM buffer for codec swapping */
336 static unsigned char *iram_buf = NULL;
337 /* Pointer to DRAM buffer for codec swapping */
338 static unsigned char *dram_buf = NULL;
339 /* Parity of swap_codec calls - needed because one codec swapping itself in
340 automatically swaps in the other and the swap when unlocking should not
341 happen if the parity is even.
343 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
344 /* Locking to control which codec (normal/voice) is running */
345 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
346 static struct event event_codecthread NOCACHEBSS_ATTR;
348 /* Voice state */
349 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
350 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
351 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
352 static unsigned char *voicebuf = NULL;
353 static size_t voice_remaining = 0;
355 #ifdef IRAM_STEAL
356 /* Voice IRAM has been stolen for other use */
357 static bool voice_iram_stolen = false;
358 #endif
360 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
362 struct voice_info {
363 void (*callback)(unsigned char **start, size_t* size);
364 size_t size;
365 unsigned char *buf;
367 static void voice_thread(void);
368 static void voice_stop(void);
370 #endif /* PLAYBACK_VOICE */
372 /* --- External interfaces --- */
374 void mp3_play_data(const unsigned char* start, int size,
375 void (*get_more)(unsigned char** start, size_t* size))
377 #ifdef PLAYBACK_VOICE
378 static struct voice_info voice_clip;
379 voice_clip.callback = get_more;
380 voice_clip.buf = (unsigned char*)start;
381 voice_clip.size = size;
382 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
383 queue_post(&voice_queue, Q_VOICE_STOP, 0);
384 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
385 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
386 voice_thread_start = true;
387 trigger_cpu_boost();
388 #else
389 (void) start;
390 (void) size;
391 (void) get_more;
392 #endif
395 void mp3_play_stop(void)
397 #ifdef PLAYBACK_VOICE
398 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
399 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
400 queue_post(&voice_queue, Q_VOICE_STOP, 1);
401 #endif
404 void mp3_play_pause(bool play)
406 /* a dummy */
407 (void)play;
410 bool mp3_is_playing(void)
412 #ifdef PLAYBACK_VOICE
413 return voice_is_playing;
414 #else
415 return false;
416 #endif
419 /* If voice could be swapped out - wait for it to return
420 * Used by buffer claming functions.
422 static void wait_for_voice_swap_in(void)
424 #ifdef PLAYBACK_VOICE
425 if (NULL == iram_buf)
426 return;
428 event_wait(&event_codecthread, STATE_NONSIGNALED);
429 #endif /* PLAYBACK_VOICE */
432 /* This sends a stop message and the audio thread will dump all it's
433 subsequenct messages */
434 static void audio_hard_stop(void)
436 /* Stop playback */
437 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
438 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
441 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
443 unsigned char *buf, *end;
445 if (audio_is_initialized)
447 audio_hard_stop();
448 wait_for_voice_swap_in();
449 #ifdef PLAYBACK_VOICE
450 voice_stop();
451 #endif
453 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
455 if (buffer_size == NULL)
457 /* Special case for talk_init to use since it already knows it's
458 trashed */
459 buffer_state = BUFFER_STATE_TRASHED;
460 return NULL;
463 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
464 || !talk_voice_required())
466 logf("get buffer: talk, audio");
467 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
468 the talk buffer is not needed because voice isn't being used, or
469 could be BUFFER_STATE_TRASHED already. If state is
470 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
471 without the caller knowing what's going on. Changing certain settings
472 may move it to a worse condition but the memory in use by something
473 else will remain undisturbed.
475 if (buffer_state != BUFFER_STATE_TRASHED)
477 talk_buffer_steal();
478 buffer_state = BUFFER_STATE_TRASHED;
481 buf = audiobuf;
482 end = audiobufend;
484 else
486 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
487 still BUFFER_STATE_INITIALIZED */
488 /* Skip talk buffer and move pcm buffer to end to maximize available
489 contiguous memory - no audio running means voice will not need the
490 swap space */
491 logf("get buffer: audio");
492 buf = audiobuf + talk_get_bufsize();
493 end = audiobufend - pcmbuf_init(audiobufend);
494 buffer_state = BUFFER_STATE_VOICED_ONLY;
497 *buffer_size = end - buf;
499 return buf;
502 #ifdef IRAM_STEAL
503 void audio_iram_steal(void)
505 /* We need to stop audio playback in order to use codec IRAM */
506 audio_hard_stop();
508 #ifdef PLAYBACK_VOICE
509 if (NULL != iram_buf)
511 /* Can't already be stolen */
512 if (voice_iram_stolen)
513 return;
515 /* Must wait for voice to be current again if it is swapped which
516 would cause the caller's buffer to get clobbered when voice locks
517 and runs - we'll wait for it to lock and yield again then make sure
518 the ride has come to a complete stop */
519 wait_for_voice_swap_in();
520 voice_stop();
522 /* Save voice IRAM but just memcpy - safe to do here since voice
523 is current and no audio codec is loaded */
524 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
525 voice_iram_stolen = true;
527 else
529 /* Nothing much to do if no voice */
530 voice_iram_stolen = false;
532 #endif
534 #endif /* IRAM_STEAL */
536 #ifdef HAVE_RECORDING
537 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
539 /* Don't allow overwrite of voice swap area or we'll trash the
540 swapped-out voice codec but can use whole thing if none */
541 unsigned char *end;
543 /* Stop audio and voice. Wait for voice to swap in and be clear
544 of pending events to ensure trouble-free operation of encoders */
545 audio_hard_stop();
546 wait_for_voice_swap_in();
547 #ifdef PLAYBACK_VOICE
548 voice_stop();
549 #endif
550 talk_buffer_steal();
552 #ifdef PLAYBACK_VOICE
553 /* If no dram_buf, swap space not used and recording gets more
554 memory. Codec swap areas will remain unaffected by the next init
555 since they're allocated at the end of the buffer and their sizes
556 don't change between calls */
557 end = dram_buf;
558 if (NULL == end)
559 #endif /* PLAYBACK_VOICE */
560 end = audiobufend;
562 buffer_state = BUFFER_STATE_TRASHED;
564 *buffer_size = end - audiobuf;
566 return (unsigned char *)audiobuf;
569 bool audio_load_encoder(int afmt)
571 #ifndef SIMULATOR
572 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
573 if (!enc_fn)
574 return false;
576 audio_remove_encoder();
577 ci.enc_codec_loaded = 0; /* clear any previous error condition */
579 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
580 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
582 while (ci.enc_codec_loaded == 0)
583 yield();
585 logf("codec loaded: %d", ci.enc_codec_loaded);
587 return ci.enc_codec_loaded > 0;
588 #else
589 (void)afmt;
590 return true;
591 #endif
592 } /* audio_load_encoder */
594 void audio_remove_encoder(void)
596 #ifndef SIMULATOR
597 /* force encoder codec unload (if currently loaded) */
598 if (ci.enc_codec_loaded <= 0)
599 return;
601 ci.stop_encoder = true;
602 while (ci.enc_codec_loaded > 0)
603 yield();
604 #endif
605 } /* audio_remove_encoder */
607 #endif /* HAVE_RECORDING */
609 struct mp3entry* audio_current_track(void)
611 const char *filename;
612 const char *p;
613 static struct mp3entry temp_id3;
614 int cur_idx;
615 int offset = ci.new_track + wps_offset;
617 cur_idx = track_ridx + offset;
618 cur_idx &= MAX_TRACK_MASK;
620 if (tracks[cur_idx].taginfo_ready)
621 return &tracks[cur_idx].id3;
623 memset(&temp_id3, 0, sizeof(struct mp3entry));
625 filename = playlist_peek(0);
626 if (!filename)
627 filename = "No file!";
629 #ifdef HAVE_TC_RAMCACHE
630 if (tagcache_fill_tags(&temp_id3, filename))
631 return &temp_id3;
632 #endif
634 p = strrchr(filename, '/');
635 if (!p)
636 p = filename;
637 else
638 p++;
640 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
641 temp_id3.title = &temp_id3.path[0];
643 return &temp_id3;
646 struct mp3entry* audio_next_track(void)
648 int next_idx = track_ridx;
650 if (!audio_have_tracks())
651 return NULL;
653 next_idx++;
654 next_idx &= MAX_TRACK_MASK;
656 if (!tracks[next_idx].taginfo_ready)
657 return NULL;
659 return &tracks[next_idx].id3;
662 bool audio_has_changed_track(void)
664 if (track_changed)
666 track_changed = false;
667 return true;
670 return false;
673 void audio_play(long offset)
675 logf("audio_play");
677 #ifdef PLAYBACK_VOICE
678 /* Truncate any existing voice output so we don't have spelling
679 * etc. over the first part of the played track */
680 do_shutup();
681 #endif
683 /* Start playback */
684 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
685 /* Don't return until playback has actually started */
686 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
689 void audio_stop(void)
691 /* Stop playback */
692 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
693 /* Don't return until playback has actually stopped */
694 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
697 void audio_pause(void)
699 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
700 /* Don't return until playback has actually paused */
701 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
704 void audio_resume(void)
706 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
707 /* Don't return until playback has actually resumed */
708 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
711 void audio_next(void)
713 if (playlist_check(ci.new_track + wps_offset + 1))
715 if (global_settings.beep)
716 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
718 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
719 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
720 /* Update wps while our message travels inside deep playback queues. */
721 wps_offset++;
722 track_changed = true;
724 else
726 /* No more tracks. */
727 if (global_settings.beep)
728 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
732 void audio_prev(void)
734 if (playlist_check(ci.new_track + wps_offset - 1))
736 if (global_settings.beep)
737 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
739 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
740 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
741 /* Update wps while our message travels inside deep playback queues. */
742 wps_offset--;
743 track_changed = true;
745 else
747 /* No more tracks. */
748 if (global_settings.beep)
749 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
753 void audio_next_dir(void)
755 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
756 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
759 void audio_prev_dir(void)
761 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
762 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
765 void audio_pre_ff_rewind(void)
767 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
768 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
771 void audio_ff_rewind(long newpos)
773 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
774 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
777 void audio_flush_and_reload_tracks(void)
779 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
780 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
783 void audio_error_clear(void)
785 #ifdef AUDIO_HAVE_RECORDING
786 pcm_rec_error_clear();
787 #endif
790 int audio_status(void)
792 int ret = 0;
794 if (playing)
795 ret |= AUDIO_STATUS_PLAY;
797 if (paused)
798 ret |= AUDIO_STATUS_PAUSE;
800 #ifdef HAVE_RECORDING
801 /* Do this here for constitency with mpeg.c version */
802 ret |= pcm_rec_status();
803 #endif
805 return ret;
808 int audio_get_file_pos(void)
810 return 0;
813 #ifndef HAVE_FLASH_STORAGE
814 void audio_set_buffer_margin(int setting)
816 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
817 buffer_margin = lookup[setting];
818 logf("buffer margin: %ld", buffer_margin);
819 set_filebuf_watermark(buffer_margin);
821 #endif
823 /* Take nescessary steps to enable or disable the crossfade setting */
824 void audio_set_crossfade(int enable)
826 size_t offset;
827 bool was_playing;
828 size_t size;
830 /* Tell it the next setting to use */
831 pcmbuf_crossfade_enable(enable);
833 /* Return if size hasn't changed or this is too early to determine
834 which in the second case there's no way we could be playing
835 anything at all */
836 if (pcmbuf_is_same_size())
838 /* This function is a copout and just syncs some variables -
839 to be removed at a later date */
840 pcmbuf_crossfade_enable_finished();
841 return;
844 offset = 0;
845 was_playing = playing;
847 /* Playback has to be stopped before changing the buffer size */
848 if (was_playing)
850 /* Store the track resume position */
851 offset = CUR_TI->id3.offset;
852 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
855 /* Blast it - audio buffer will have to be setup again next time
856 something plays */
857 audio_get_buffer(true, &size);
859 /* Restart playback if audio was running previously */
860 if (was_playing)
861 audio_play(offset);
864 /* --- Routines called from multiple threads --- */
865 static void set_current_codec(int codec_idx)
867 current_codec = codec_idx;
868 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
871 #ifdef PLAYBACK_VOICE
872 static void swap_codec(void)
874 int my_codec;
876 /* Swap nothing if no swap buffers exist */
877 if (dram_buf == NULL)
879 logf("swap: no swap buffers");
880 return;
883 my_codec = current_codec;
885 logf("swapping out codec: %d", my_codec);
887 /* Invert this when a codec thread enters and leaves */
888 swap_codec_parity = !swap_codec_parity;
890 /* If this is true, an odd number of calls has occurred and there's
891 no codec thread waiting to swap us out when it locks and runs. This
892 occurs when playback is stopped or when just starting playback and
893 the audio thread is loading a codec; parities should always be even
894 on entry when a thread calls this during playback */
895 if (swap_codec_parity)
897 /* Save our current IRAM and DRAM */
898 #ifdef IRAM_STEAL
899 if (voice_iram_stolen)
901 logf("swap: iram restore");
902 voice_iram_stolen = false;
903 /* Don't swap trashed data into buffer as the voice IRAM will
904 already be swapped out - should _always_ be the case if
905 voice_iram_stolen is true since the voice has been swapped
906 in beforehand */
907 if (my_codec == CODEC_IDX_VOICE)
909 logf("voice iram already swapped");
910 goto skip_iram_swap;
913 #endif
915 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
917 #ifdef IRAM_STEAL
918 skip_iram_swap:
919 #endif
921 memswap128(dram_buf, codecbuf, CODEC_SIZE);
922 /* No cache invalidation needed; it will be done in codec_load_ram
923 or we won't be here otherwise */
926 /* Release my semaphore */
927 semaphore_release(&sem_codecthread);
928 logf("unlocked: %d", my_codec);
930 /* Wait for other codec */
931 event_wait(&event_codecthread,
932 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
934 /* Wait for other codec to unlock */
935 logf("waiting for lock: %d", my_codec);
936 semaphore_wait(&sem_codecthread);
938 /* Take control */
939 set_current_codec(my_codec);
940 event_set_state(&event_codecthread,
941 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
943 /* Reload our IRAM and DRAM */
944 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
945 memswap128(dram_buf, codecbuf, CODEC_SIZE);
946 invalidate_icache();
948 /* Flip parity again */
949 swap_codec_parity = !swap_codec_parity;
951 logf("resuming codec: %d", my_codec);
954 /* This function is meant to be used by the buffer stealing functions to
955 ensure the codec is no longer active and so voice will be swapped-in
956 before it is called */
957 static void voice_stop(void)
959 /* Must have a voice codec loaded or we'll hang forever here */
960 if (!voice_codec_loaded)
961 return;
963 do_shutup();
965 /* Loop until voice empties it's queue, stops and picks up on the new
966 track; the voice thread must be stopped and waiting for messages
967 outside the codec */
968 while (voice_is_playing || !queue_empty(&voice_queue) ||
969 ci_voice.new_track)
970 yield();
972 if (!playing)
973 pcmbuf_play_stop();
974 } /* voice_stop */
976 /* Is voice still speaking */
977 /* Unfortunately only reliable when music is not also playing. */
978 static bool is_voice_speaking(void)
980 return is_voice_queued()
981 || voice_is_playing
982 || (!playing && pcm_is_playing());
985 #endif /* PLAYBACK_VOICE */
987 /* Wait for voice to finish speaking. */
988 /* Also only reliable when music is not also playing. */
989 void voice_wait(void)
991 #ifdef PLAYBACK_VOICE
992 while (is_voice_speaking())
993 sleep(HZ/10);
994 #endif
997 static void set_filebuf_watermark(int seconds)
999 size_t bytes;
1001 if (!filebuf)
1002 return; /* Audio buffers not yet set up */
1004 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
1005 bytes = MIN(bytes, filebuflen / 2);
1006 conf_watermark = bytes;
1009 const char * get_codec_filename(int cod_spec)
1011 const char *fname;
1013 #ifdef HAVE_RECORDING
1014 /* Can choose decoder or encoder if one available */
1015 int type = cod_spec & CODEC_TYPE_MASK;
1016 int afmt = cod_spec & CODEC_AFMT_MASK;
1018 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1019 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1021 fname = (type == CODEC_TYPE_ENCODER) ?
1022 audio_formats[afmt].codec_enc_root_fn :
1023 audio_formats[afmt].codec_root_fn;
1025 logf("%s: %d - %s",
1026 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1027 afmt, fname ? fname : "<unknown>");
1028 #else /* !HAVE_RECORDING */
1029 /* Always decoder */
1030 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1031 cod_spec = AFMT_UNKNOWN;
1032 fname = audio_formats[cod_spec].codec_root_fn;
1033 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1034 #endif /* HAVE_RECORDING */
1036 return fname;
1037 } /* get_codec_filename */
1040 /* --- Voice thread --- */
1042 #ifdef PLAYBACK_VOICE
1044 static bool voice_pcmbuf_insert_callback(
1045 const void *ch1, const void *ch2, int count)
1047 const char *src[2] = { ch1, ch2 };
1049 while (count > 0)
1051 int out_count = dsp_output_count(count);
1052 int inp_count;
1053 char *dest;
1055 while ((dest = pcmbuf_request_voice_buffer(
1056 &out_count, playing)) == NULL)
1058 if (playing && audio_codec_loaded)
1059 swap_codec();
1060 else
1061 yield();
1064 /* Get the real input_size for output_size bytes, guarding
1065 * against resampling buffer overflows. */
1066 inp_count = dsp_input_count(out_count);
1068 if (inp_count <= 0)
1069 return true;
1071 /* Input size has grown, no error, just don't write more than length */
1072 if (inp_count > count)
1073 inp_count = count;
1075 out_count = dsp_process(dest, src, inp_count);
1077 if (out_count <= 0)
1078 return true;
1080 if (playing)
1082 pcmbuf_mix_voice(out_count);
1083 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1084 audio_codec_loaded)
1085 swap_codec();
1087 else
1088 pcmbuf_write_complete(out_count);
1090 count -= inp_count;
1093 return true;
1094 } /* voice_pcmbuf_insert_callback */
1096 static void* voice_get_memory_callback(size_t *size)
1098 /* Voice should have no use for this. If it did, we'd have to
1099 swap the malloc buffer as well. */
1100 *size = 0;
1101 return NULL;
1104 static void voice_set_elapsed_callback(unsigned int value)
1106 (void)value;
1109 static void voice_set_offset_callback(size_t value)
1111 (void)value;
1114 static void voice_configure_callback(int setting, intptr_t value)
1116 if (!dsp_configure(setting, value))
1118 logf("Illegal key:%d", setting);
1122 static size_t voice_filebuf_callback(void *ptr, size_t size)
1124 (void)ptr;
1125 (void)size;
1127 return 0;
1130 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1131 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1133 if (aborting && !playing && pcm_is_playing())
1135 /* Aborting: Slight hack - flush PCM buffer if
1136 only being used for voice */
1137 pcmbuf_play_stop();
1140 if (voice_is_playing)
1142 /* Clear the current buffer */
1143 voice_is_playing = false;
1144 voice_getmore = NULL;
1145 voice_remaining = 0;
1146 voicebuf = NULL;
1148 /* Cancel any automatic boost if no more clips requested. */
1149 if (!playing || !voice_thread_start)
1150 sleep(0);
1152 /* Force the codec to think it's changing tracks */
1153 ci_voice.new_track = 1;
1155 *realsize = 0;
1156 return true; /* Yes, change tracks */
1159 return false;
1162 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1164 struct queue_event ev;
1166 if (ci_voice.new_track)
1168 *realsize = 0;
1169 return NULL;
1172 while (1)
1174 if (voice_is_playing || playing)
1176 queue_wait_w_tmo(&voice_queue, &ev, 0);
1177 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1178 ev.id = Q_AUDIO_PLAY;
1180 else
1182 queue_wait(&voice_queue, &ev);
1185 switch (ev.id) {
1186 case Q_AUDIO_PLAY:
1187 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1188 if (playing)
1190 if (audio_codec_loaded)
1191 swap_codec();
1192 yield();
1194 break;
1196 #ifdef AUDIO_HAVE_RECORDING
1197 case Q_ENCODER_RECORD:
1198 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1199 swap_codec();
1200 break;
1201 #endif
1203 case Q_VOICE_STOP:
1204 LOGFQUEUE("voice < Q_VOICE_STOP");
1205 if (voice_on_voice_stop(ev.data, realsize))
1206 return NULL;
1207 break;
1209 case SYS_USB_CONNECTED:
1211 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1212 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1213 /* Voice is obviously current so let us swap ourselves away if
1214 playing so audio may stop itself - audio_codec_loaded can
1215 only be true in this case if we're here even if the codec
1216 is only about to load */
1217 if (audio_codec_loaded)
1218 swap_codec();
1219 /* Playback should be finished by now - ack and wait */
1220 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1221 usb_wait_for_disconnect(&voice_queue);
1222 if (change_tracks)
1223 return NULL;
1224 break;
1227 case Q_VOICE_PLAY:
1228 LOGFQUEUE("voice < Q_VOICE_PLAY");
1229 if (!voice_is_playing)
1231 /* Set up new voice data */
1232 struct voice_info *voice_data;
1233 #ifdef IRAM_STEAL
1234 if (voice_iram_stolen)
1236 /* Voice is the first to run again and is currently
1237 loaded */
1238 logf("voice: iram restore");
1239 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1240 voice_iram_stolen = false;
1242 #endif
1243 /* Must reset the buffer before any playback begins if
1244 needed */
1245 if (buffer_state == BUFFER_STATE_TRASHED)
1246 audio_reset_buffer();
1248 voice_is_playing = true;
1249 trigger_cpu_boost();
1250 voice_data = (struct voice_info *)ev.data;
1251 voice_remaining = voice_data->size;
1252 voicebuf = voice_data->buf;
1253 voice_getmore = voice_data->callback;
1255 goto voice_play_clip; /* To exit both switch and while */
1257 case SYS_TIMEOUT:
1258 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1259 goto voice_play_clip;
1261 default:
1262 LOGFQUEUE("voice < default");
1266 voice_play_clip:
1268 if (voice_remaining == 0 || voicebuf == NULL)
1270 if (voice_getmore)
1271 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1273 /* If this clip is done */
1274 if (voice_remaining == 0)
1276 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1277 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1278 /* Force pcm playback. */
1279 if (!pcm_is_playing())
1280 pcmbuf_play_start();
1284 *realsize = MIN(voice_remaining, reqsize);
1286 if (*realsize == 0)
1287 return NULL;
1289 return voicebuf;
1290 } /* voice_request_buffer_callback */
1292 static void voice_advance_buffer_callback(size_t amount)
1294 amount = MIN(amount, voice_remaining);
1295 voicebuf += amount;
1296 voice_remaining -= amount;
1299 static void voice_advance_buffer_loc_callback(void *ptr)
1301 size_t amount = (size_t)ptr - (size_t)voicebuf;
1303 voice_advance_buffer_callback(amount);
1306 static off_t voice_mp3_get_filepos_callback(int newtime)
1308 (void)newtime;
1310 return 0;
1313 static void voice_do_nothing(void)
1315 return;
1318 static bool voice_seek_buffer_callback(size_t newpos)
1320 (void)newpos;
1322 return false;
1325 static bool voice_request_next_track_callback(void)
1327 ci_voice.new_track = 0;
1328 return true;
1331 static void voice_thread(void)
1333 logf("Loading voice codec");
1334 voice_codec_loaded = true;
1335 semaphore_wait(&sem_codecthread);
1336 event_set_state(&event_codecthread, false);
1337 set_current_codec(CODEC_IDX_VOICE);
1338 dsp_configure(DSP_RESET, 0);
1339 voice_remaining = 0;
1340 voice_getmore = NULL;
1342 /* FIXME: If we being starting the voice thread without reboot, the
1343 voice_queue could be full of old stuff and we must flush it. */
1344 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1346 logf("Voice codec finished");
1347 voice_codec_loaded = false;
1348 voice_thread_p = NULL;
1349 semaphore_release(&sem_codecthread);
1350 } /* voice_thread */
1352 #endif /* PLAYBACK_VOICE */
1354 /* --- Codec thread --- */
1355 static bool codec_pcmbuf_insert_callback(
1356 const void *ch1, const void *ch2, int count)
1358 const char *src[2] = { ch1, ch2 };
1360 while (count > 0)
1362 int out_count = dsp_output_count(count);
1363 int inp_count;
1364 char *dest;
1366 /* Prevent audio from a previous track from playing */
1367 if (ci.new_track || ci.stop_codec)
1368 return true;
1370 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1372 sleep(1);
1373 if (ci.seek_time || ci.new_track || ci.stop_codec)
1374 return true;
1377 /* Get the real input_size for output_size bytes, guarding
1378 * against resampling buffer overflows. */
1379 inp_count = dsp_input_count(out_count);
1381 if (inp_count <= 0)
1382 return true;
1384 /* Input size has grown, no error, just don't write more than length */
1385 if (inp_count > count)
1386 inp_count = count;
1388 out_count = dsp_process(dest, src, inp_count);
1390 if (out_count <= 0)
1391 return true;
1393 pcmbuf_write_complete(out_count);
1395 #ifdef PLAYBACK_VOICE
1396 if ((voice_is_playing || voice_thread_start)
1397 && pcm_is_playing() && voice_codec_loaded &&
1398 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1400 voice_thread_start = false;
1401 swap_codec();
1403 #endif
1405 count -= inp_count;
1408 return true;
1409 } /* codec_pcmbuf_insert_callback */
1411 static void* codec_get_memory_callback(size_t *size)
1413 *size = MALLOC_BUFSIZE;
1414 return malloc_buf;
1417 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1418 static void codec_pcmbuf_position_callback(size_t size)
1420 /* This is called from an ISR, so be quick */
1421 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1422 prev_ti->id3.elapsed;
1424 if (time >= prev_ti->id3.length)
1426 pcmbuf_set_position_callback(NULL);
1427 prev_ti->id3.elapsed = prev_ti->id3.length;
1429 else
1430 prev_ti->id3.elapsed = time;
1433 static void codec_set_elapsed_callback(unsigned int value)
1435 unsigned int latency;
1436 if (ci.seek_time)
1437 return;
1439 #ifdef AB_REPEAT_ENABLE
1440 ab_position_report(value);
1441 #endif
1443 latency = pcmbuf_get_latency();
1444 if (value < latency)
1445 CUR_TI->id3.elapsed = 0;
1446 else if (value - latency > CUR_TI->id3.elapsed ||
1447 value - latency < CUR_TI->id3.elapsed - 2)
1449 CUR_TI->id3.elapsed = value - latency;
1453 static void codec_set_offset_callback(size_t value)
1455 unsigned int latency;
1457 if (ci.seek_time)
1458 return;
1460 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1461 if (value < latency)
1462 CUR_TI->id3.offset = 0;
1463 else
1464 CUR_TI->id3.offset = value - latency;
1467 static void codec_advance_buffer_counters(size_t amount)
1469 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1470 ci.curpos += amount;
1471 CUR_TI->available -= amount;
1473 /* Start buffer filling as necessary. */
1474 if (!pcmbuf_is_lowdata() && !filling)
1476 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1478 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1479 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1484 /* copy up-to size bytes into ptr and return the actual size copied */
1485 static size_t codec_filebuf_callback(void *ptr, size_t size)
1487 char *buf = (char *)ptr;
1488 size_t copy_n;
1489 size_t part_n;
1491 if (ci.stop_codec || !playing)
1492 return 0;
1494 /* The ammount to copy is the lesser of the requested amount and the
1495 * amount left of the current track (both on disk and already loaded) */
1496 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1498 /* Nothing requested OR nothing left */
1499 if (copy_n == 0)
1500 return 0;
1502 /* Let the disk buffer catch fill until enough data is available */
1503 while (copy_n > CUR_TI->available)
1505 if (!filling)
1507 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1508 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1511 sleep(1);
1512 if (ci.stop_codec || ci.new_track)
1513 return 0;
1516 /* Copy as much as possible without wrapping */
1517 part_n = MIN(copy_n, filebuflen - buf_ridx);
1518 memcpy(buf, &filebuf[buf_ridx], part_n);
1519 /* Copy the rest in the case of a wrap */
1520 if (part_n < copy_n) {
1521 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1524 /* Update read and other position pointers */
1525 codec_advance_buffer_counters(copy_n);
1527 /* Return the actual amount of data copied to the buffer */
1528 return copy_n;
1529 } /* codec_filebuf_callback */
1531 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1533 size_t short_n, copy_n, buf_rem;
1535 if (!playing)
1537 *realsize = 0;
1538 return NULL;
1541 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1542 if (copy_n == 0)
1544 *realsize = 0;
1545 return NULL;
1548 while (copy_n > CUR_TI->available)
1550 if (!filling)
1552 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1553 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1556 sleep(1);
1557 if (ci.stop_codec || ci.new_track)
1559 *realsize = 0;
1560 return NULL;
1564 /* How much is left at the end of the file buffer before wrap? */
1565 buf_rem = filebuflen - buf_ridx;
1567 /* If we can't satisfy the request without wrapping */
1568 if (buf_rem < copy_n)
1570 /* How short are we? */
1571 short_n = copy_n - buf_rem;
1573 /* If we can fudge it with the guardbuf */
1574 if (short_n < GUARD_BUFSIZE)
1575 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1576 else
1577 copy_n = buf_rem;
1580 *realsize = copy_n;
1582 return (char *)&filebuf[buf_ridx];
1583 } /* codec_request_buffer_callback */
1585 static int get_codec_base_type(int type)
1587 switch (type) {
1588 case AFMT_MPA_L1:
1589 case AFMT_MPA_L2:
1590 case AFMT_MPA_L3:
1591 return AFMT_MPA_L3;
1594 return type;
1597 static void codec_advance_buffer_callback(size_t amount)
1599 if (amount > CUR_TI->available + CUR_TI->filerem)
1600 amount = CUR_TI->available + CUR_TI->filerem;
1602 while (amount > CUR_TI->available && filling)
1603 sleep(1);
1605 if (amount > CUR_TI->available)
1607 intptr_t result = Q_CODEC_REQUEST_FAILED;
1609 if (!ci.stop_codec)
1611 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1612 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1613 ci.curpos + amount);
1616 switch (result)
1618 case Q_CODEC_REQUEST_FAILED:
1619 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1620 ci.stop_codec = true;
1621 return;
1623 case Q_CODEC_REQUEST_COMPLETE:
1624 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1625 return;
1627 default:
1628 LOGFQUEUE("codec |< default");
1629 ci.stop_codec = true;
1630 return;
1634 codec_advance_buffer_counters(amount);
1636 codec_set_offset_callback(ci.curpos);
1639 static void codec_advance_buffer_loc_callback(void *ptr)
1641 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1643 codec_advance_buffer_callback(amount);
1646 /* Copied from mpeg.c. Should be moved somewhere else. */
1647 static int codec_get_file_pos(void)
1649 int pos = -1;
1650 struct mp3entry *id3 = audio_current_track();
1652 if (id3->vbr)
1654 if (id3->has_toc)
1656 /* Use the TOC to find the new position */
1657 unsigned int percent, remainder;
1658 int curtoc, nexttoc, plen;
1660 percent = (id3->elapsed*100)/id3->length;
1661 if (percent > 99)
1662 percent = 99;
1664 curtoc = id3->toc[percent];
1666 if (percent < 99)
1667 nexttoc = id3->toc[percent+1];
1668 else
1669 nexttoc = 256;
1671 pos = (id3->filesize/256)*curtoc;
1673 /* Use the remainder to get a more accurate position */
1674 remainder = (id3->elapsed*100)%id3->length;
1675 remainder = (remainder*100)/id3->length;
1676 plen = (nexttoc - curtoc)*(id3->filesize/256);
1677 pos += (plen/100)*remainder;
1679 else
1681 /* No TOC exists, estimate the new position */
1682 pos = (id3->filesize / (id3->length / 1000)) *
1683 (id3->elapsed / 1000);
1686 else if (id3->bitrate)
1687 pos = id3->elapsed * (id3->bitrate / 8);
1688 else
1689 return -1;
1691 pos += id3->first_frame_offset;
1693 /* Don't seek right to the end of the file so that we can
1694 transition properly to the next song */
1695 if (pos >= (int)(id3->filesize - id3->id3v1len))
1696 pos = id3->filesize - id3->id3v1len - 1;
1698 return pos;
1701 static off_t codec_mp3_get_filepos_callback(int newtime)
1703 off_t newpos;
1705 CUR_TI->id3.elapsed = newtime;
1706 newpos = codec_get_file_pos();
1708 return newpos;
1711 static void codec_seek_complete_callback(void)
1713 logf("seek_complete");
1714 if (pcm_is_paused())
1716 /* If this is not a seamless seek, clear the buffer */
1717 pcmbuf_play_stop();
1718 dsp_configure(DSP_FLUSH, 0);
1720 /* If playback was not 'deliberately' paused, unpause now */
1721 if (!paused)
1722 pcmbuf_pause(false);
1724 ci.seek_time = 0;
1727 static bool codec_seek_buffer_callback(size_t newpos)
1729 int difference;
1731 logf("codec_seek_buffer_callback");
1733 if (newpos >= CUR_TI->filesize)
1734 newpos = CUR_TI->filesize - 1;
1736 difference = newpos - ci.curpos;
1737 if (difference >= 0)
1739 /* Seeking forward */
1740 logf("seek: +%d", difference);
1741 codec_advance_buffer_callback(difference);
1742 return true;
1745 /* Seeking backward */
1746 difference = -difference;
1747 if (ci.curpos - difference < 0)
1748 difference = ci.curpos;
1750 /* We need to reload the song. */
1751 if (newpos < CUR_TI->start_pos)
1753 intptr_t result = Q_CODEC_REQUEST_FAILED;
1755 if (!ci.stop_codec)
1757 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1758 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1759 newpos);
1762 switch (result)
1764 case Q_CODEC_REQUEST_COMPLETE:
1765 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1766 return true;
1768 case Q_CODEC_REQUEST_FAILED:
1769 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1770 ci.stop_codec = true;
1771 return false;
1773 default:
1774 LOGFQUEUE("codec |< default");
1775 return false;
1779 /* Seeking inside buffer space. */
1780 logf("seek: -%d", difference);
1781 CUR_TI->available += difference;
1782 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1783 ci.curpos -= difference;
1785 return true;
1788 static void codec_configure_callback(int setting, intptr_t value)
1790 switch (setting) {
1791 case CODEC_SET_FILEBUF_WATERMARK:
1792 conf_watermark = value;
1793 set_filebuf_watermark(buffer_margin);
1794 break;
1796 case CODEC_SET_FILEBUF_CHUNKSIZE:
1797 conf_filechunk = value;
1798 break;
1800 case CODEC_SET_FILEBUF_PRESEEK:
1801 conf_preseek = value;
1802 break;
1804 default:
1805 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1809 static void codec_track_changed(void)
1811 automatic_skip = false;
1812 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1813 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1816 static void codec_pcmbuf_track_changed_callback(void)
1818 pcmbuf_set_position_callback(NULL);
1819 codec_track_changed();
1822 static void codec_discard_codec_callback(void)
1824 if (CUR_TI->has_codec)
1826 CUR_TI->has_codec = false;
1827 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1830 #if 0
1831 /* Check if a buffer desync has happened, log it and stop playback. */
1832 if (buf_ridx != CUR_TI->buf_idx)
1834 int offset = CUR_TI->buf_idx - buf_ridx;
1835 size_t new_used = FILEBUFUSED - offset;
1837 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1838 logf("Used off:%d",FILEBUFUSED - new_used);
1840 /* This is a fatal internal error and it's not safe to
1841 * continue playback. */
1842 ci.stop_codec = true;
1843 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1845 #endif
1848 static inline void codec_gapless_track_change(void) {
1849 /* callback keeps the progress bar moving while the pcmbuf empties */
1850 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1851 /* set the pcmbuf callback for when the track really changes */
1852 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1855 static inline void codec_crossfade_track_change(void) {
1856 /* Initiate automatic crossfade mode */
1857 pcmbuf_crossfade_init(false);
1858 /* Notify the wps that the track change starts now */
1859 codec_track_changed();
1862 static void codec_track_skip_done(bool was_manual)
1864 int crossfade_mode = global_settings.crossfade;
1866 /* Manual track change (always crossfade or flush audio). */
1867 if (was_manual)
1869 pcmbuf_crossfade_init(true);
1870 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1871 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1873 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1874 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1875 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1877 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1879 if (global_settings.playlist_shuffle)
1880 /* shuffle mode is on, so crossfade: */
1881 codec_crossfade_track_change();
1882 else
1883 /* shuffle mode is off, so do a gapless track change */
1884 codec_gapless_track_change();
1886 else
1887 /* normal crossfade: */
1888 codec_crossfade_track_change();
1890 else
1891 /* normal gapless playback. */
1892 codec_gapless_track_change();
1895 static bool codec_load_next_track(void)
1897 intptr_t result = Q_CODEC_REQUEST_FAILED;
1899 prev_track_elapsed = CUR_TI->id3.elapsed;
1901 if (ci.seek_time)
1902 codec_seek_complete_callback();
1904 #ifdef AB_REPEAT_ENABLE
1905 ab_end_of_track_report();
1906 #endif
1908 logf("Request new track");
1910 if (ci.new_track == 0)
1912 ci.new_track++;
1913 automatic_skip = true;
1916 if (!ci.stop_codec)
1918 trigger_cpu_boost();
1919 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1920 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1923 switch (result)
1925 case Q_CODEC_REQUEST_COMPLETE:
1926 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1927 codec_track_skip_done(!automatic_skip);
1928 return true;
1930 case Q_CODEC_REQUEST_FAILED:
1931 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1932 ci.new_track = 0;
1933 ci.stop_codec = true;
1934 return false;
1936 default:
1937 LOGFQUEUE("codec |< default");
1938 ci.stop_codec = true;
1939 return false;
1943 static bool codec_request_next_track_callback(void)
1945 int prev_codectype;
1947 if (ci.stop_codec || !playing)
1948 return false;
1950 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1952 if (!codec_load_next_track())
1953 return false;
1955 /* Check if the next codec is the same file. */
1956 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1958 logf("New track loaded");
1959 codec_discard_codec_callback();
1960 return true;
1962 else
1964 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1965 return false;
1969 static void codec_thread(void)
1971 struct queue_event ev;
1972 int status;
1973 size_t wrap;
1975 while (1) {
1976 status = 0;
1977 queue_wait(&codec_queue, &ev);
1979 switch (ev.id) {
1980 case Q_CODEC_LOAD_DISK:
1981 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1982 audio_codec_loaded = true;
1983 #ifdef PLAYBACK_VOICE
1984 /* Don't sent messages to voice codec if it's already swapped
1985 out or it will never get this */
1986 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1988 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1989 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1991 semaphore_wait(&sem_codecthread);
1992 event_set_state(&event_codecthread, true);
1993 #endif
1994 set_current_codec(CODEC_IDX_AUDIO);
1995 ci.stop_codec = false;
1996 status = codec_load_file((const char *)ev.data, &ci);
1997 #ifdef PLAYBACK_VOICE
1998 semaphore_release(&sem_codecthread);
1999 #endif
2000 break;
2002 case Q_CODEC_LOAD:
2003 LOGFQUEUE("codec < Q_CODEC_LOAD");
2004 if (!CUR_TI->has_codec) {
2005 logf("Codec slot is empty!");
2006 /* Wait for the pcm buffer to go empty */
2007 while (pcm_is_playing())
2008 yield();
2009 /* This must be set to prevent an infinite loop */
2010 ci.stop_codec = true;
2011 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
2012 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
2013 break;
2016 audio_codec_loaded = true;
2017 #ifdef PLAYBACK_VOICE
2018 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2020 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2021 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2023 semaphore_wait(&sem_codecthread);
2024 event_set_state(&event_codecthread, true);
2025 #endif
2026 set_current_codec(CODEC_IDX_AUDIO);
2027 ci.stop_codec = false;
2028 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
2029 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
2030 &filebuf[0], wrap, &ci);
2031 #ifdef PLAYBACK_VOICE
2032 semaphore_release(&sem_codecthread);
2033 #endif
2034 break;
2036 #ifdef AUDIO_HAVE_RECORDING
2037 case Q_ENCODER_LOAD_DISK:
2038 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2039 audio_codec_loaded = false; /* Not audio codec! */
2040 #ifdef PLAYBACK_VOICE
2041 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2043 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2044 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2046 semaphore_wait(&sem_codecthread);
2047 event_set_state(&event_codecthread, true);
2048 #endif
2049 logf("loading encoder");
2050 set_current_codec(CODEC_IDX_AUDIO);
2051 ci.stop_encoder = false;
2052 status = codec_load_file((const char *)ev.data, &ci);
2053 #ifdef PLAYBACK_VOICE
2054 semaphore_release(&sem_codecthread);
2055 #endif
2056 logf("encoder stopped");
2057 break;
2058 #endif /* AUDIO_HAVE_RECORDING */
2060 #ifndef SIMULATOR
2061 case SYS_USB_CONNECTED:
2062 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2063 queue_clear(&codec_queue);
2064 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2065 usb_wait_for_disconnect(&codec_queue);
2066 break;
2067 #endif
2069 default:
2070 LOGFQUEUE("codec < default");
2073 if (audio_codec_loaded)
2075 if (ci.stop_codec)
2077 status = CODEC_OK;
2078 if (!playing)
2079 pcmbuf_play_stop();
2082 audio_codec_loaded = false;
2085 switch (ev.id) {
2086 case Q_CODEC_LOAD_DISK:
2087 case Q_CODEC_LOAD:
2088 LOGFQUEUE("codec < Q_CODEC_LOAD");
2089 if (playing)
2091 if (ci.new_track || status != CODEC_OK)
2093 if (!ci.new_track)
2095 logf("Codec failure");
2096 gui_syncsplash(HZ*2, "Codec failure");
2099 if (!codec_load_next_track())
2101 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2102 /* End of playlist */
2103 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2104 break;
2107 else
2109 logf("Codec finished");
2110 if (ci.stop_codec)
2112 /* Wait for the audio to stop playing before
2113 * triggering the WPS exit */
2114 while(pcm_is_playing())
2116 CUR_TI->id3.elapsed =
2117 CUR_TI->id3.length - pcmbuf_get_latency();
2118 sleep(1);
2120 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2121 /* End of playlist */
2122 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2123 break;
2127 if (CUR_TI->has_codec)
2129 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2130 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2132 else
2134 const char *codec_fn =
2135 get_codec_filename(CUR_TI->id3.codectype);
2136 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2137 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2138 (intptr_t)codec_fn);
2141 break;
2143 #ifdef AUDIO_HAVE_RECORDING
2144 case Q_ENCODER_LOAD_DISK:
2145 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2147 if (status == CODEC_OK)
2148 break;
2150 logf("Encoder failure");
2151 gui_syncsplash(HZ*2, "Encoder failure");
2153 if (ci.enc_codec_loaded < 0)
2154 break;
2156 logf("Encoder failed to load");
2157 ci.enc_codec_loaded = -1;
2158 break;
2159 #endif /* AUDIO_HAVE_RECORDING */
2161 default:
2162 LOGFQUEUE("codec < default");
2164 } /* end switch */
2169 /* --- Audio thread --- */
2171 static bool audio_filebuf_is_lowdata(void)
2173 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
2176 static bool audio_have_tracks(void)
2178 return track_ridx != track_widx || CUR_TI->filesize;
2181 static bool audio_have_free_tracks(void)
2183 if (track_widx < track_ridx)
2184 return track_widx + 1 < track_ridx;
2185 else if (track_ridx == 0)
2186 return track_widx < MAX_TRACK - 1;
2188 return true;
2191 int audio_track_count(void)
2193 if (audio_have_tracks())
2195 int relative_track_widx = track_widx;
2197 if (track_ridx > track_widx)
2198 relative_track_widx += MAX_TRACK;
2200 return relative_track_widx - track_ridx + 1;
2203 return 0;
2206 long audio_filebufused(void)
2208 return (long) FILEBUFUSED;
2211 /* Count the data BETWEEN the selected tracks */
2212 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2214 size_t amount = 0;
2215 bool need_wrap = to_track < from_track;
2217 while (1)
2219 if (++from_track >= MAX_TRACK)
2221 from_track -= MAX_TRACK;
2222 need_wrap = false;
2225 if (from_track >= to_track && !need_wrap)
2226 break;
2228 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2230 return amount;
2233 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2235 size_t amount;
2237 /* Start with the remainder of the previously playing track */
2238 amount = tracks[old_track_ridx].filesize - ci.curpos;
2239 /* Then collect all data from tracks in between them */
2240 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2241 logf("bwf:%ldB", (long) amount);
2243 if (amount > FILEBUFUSED)
2244 return false;
2246 /* Wind the buffer to the beginning of the target track or its codec */
2247 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2249 return true;
2252 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2254 /* Available buffer data */
2255 size_t buf_back;
2256 /* Start with the previously playing track's data and our data */
2257 size_t amount;
2259 amount = ci.curpos;
2260 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2262 /* If we're not just resetting the current track */
2263 if (new_track_ridx != old_track_ridx)
2265 /* Need to wind to before the old track's codec and our filesize */
2266 amount += tracks[old_track_ridx].codecsize;
2267 amount += tracks[new_track_ridx].filesize;
2269 /* Rewind the old track to its beginning */
2270 tracks[old_track_ridx].available =
2271 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2274 /* If the codec was ever buffered */
2275 if (tracks[new_track_ridx].codecsize)
2277 /* Add the codec to the needed size */
2278 amount += tracks[new_track_ridx].codecsize;
2279 tracks[new_track_ridx].has_codec = true;
2282 /* Then collect all data from tracks between new and old */
2283 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2285 /* Do we have space to make this skip? */
2286 if (amount > buf_back)
2287 return false;
2289 logf("bwb:%ldB",amount);
2291 /* Rewind the buffer to the beginning of the target track or its codec */
2292 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2294 /* Reset to the beginning of the new track */
2295 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2297 return true;
2300 static void audio_update_trackinfo(void)
2302 ci.filesize = CUR_TI->filesize;
2303 CUR_TI->id3.elapsed = 0;
2304 CUR_TI->id3.offset = 0;
2305 ci.id3 = &CUR_TI->id3;
2306 ci.curpos = 0;
2307 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2310 /* Yield to codecs for as long as possible if they are in need of data
2311 * return true if the caller should break to let the audio thread process
2312 * new events */
2313 static bool audio_yield_codecs(void)
2315 yield();
2317 if (!queue_empty(&audio_queue))
2318 return true;
2320 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2321 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2323 if (filling)
2324 yield();
2325 else
2326 sleep(2);
2328 if (!queue_empty(&audio_queue))
2329 return true;
2332 return false;
2335 static void audio_clear_track_entries(bool clear_unbuffered)
2337 int cur_idx = track_widx;
2338 int last_idx = -1;
2340 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2342 /* Loop over all tracks from write-to-read */
2343 while (1)
2345 cur_idx++;
2346 cur_idx &= MAX_TRACK_MASK;
2348 if (cur_idx == track_ridx)
2349 break;
2351 /* If the track is buffered, conditionally clear/notify,
2352 * otherwise clear the track if that option is selected */
2353 if (tracks[cur_idx].event_sent)
2355 if (last_idx >= 0)
2357 /* If there is an unbuffer callback, call it, otherwise,
2358 * just clear the track */
2359 if (track_unbuffer_callback)
2360 track_unbuffer_callback(&tracks[last_idx].id3, false);
2362 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2364 last_idx = cur_idx;
2366 else if (clear_unbuffered)
2367 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2370 /* We clear the previous instance of a buffered track throughout
2371 * the above loop to facilitate 'last' detection. Clear/notify
2372 * the last track here */
2373 if (last_idx >= 0)
2375 if (track_unbuffer_callback)
2376 track_unbuffer_callback(&tracks[last_idx].id3, true);
2377 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2381 /* FIXME: This code should be made more generic and move to metadata.c */
2382 static void audio_strip_tags(void)
2384 int i;
2385 static const unsigned char tag[] = "TAG";
2386 static const unsigned char apetag[] = "APETAGEX";
2387 size_t tag_idx;
2388 size_t cur_idx;
2389 size_t len, version;
2391 tag_idx = RINGBUF_SUB(buf_widx, 128);
2393 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2395 cur_idx = tag_idx;
2396 for(i = 0;i < 3;i++)
2398 if(filebuf[cur_idx] != tag[i])
2399 goto strip_ape_tag;
2401 cur_idx = RINGBUF_ADD(cur_idx, 1);
2404 /* Skip id3v1 tag */
2405 logf("Skipping ID3v1 tag");
2406 buf_widx = tag_idx;
2407 tracks[track_widx].available -= 128;
2408 tracks[track_widx].filesize -= 128;
2411 strip_ape_tag:
2412 /* Check for APE tag (look for the APE tag footer) */
2413 tag_idx = RINGBUF_SUB(buf_widx, 32);
2415 if (FILEBUFUSED > 32 && tag_idx > buf_ridx)
2417 cur_idx = tag_idx;
2418 for(i = 0;i < 8;i++)
2420 if(filebuf[cur_idx] != apetag[i])
2421 return;
2423 cur_idx = RINGBUF_ADD(cur_idx, 1);
2426 /* Read the version and length from the footer */
2427 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2428 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2429 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2430 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2431 if (version == 2000)
2432 len += 32; /* APEv2 has a 32 byte header */
2434 /* Skip APE tag */
2435 if (FILEBUFUSED > len)
2437 logf("Skipping APE tag (%ldB)", len);
2438 buf_widx = RINGBUF_SUB(buf_widx, len);
2439 tracks[track_widx].available -= len;
2440 tracks[track_widx].filesize -= len;
2445 /* Returns true if a whole file is read, false otherwise */
2446 static bool audio_read_file(size_t minimum)
2448 bool ret_val = false;
2450 /* If we're called and no file is open, this is an error */
2451 if (current_fd < 0)
2453 logf("Bad fd in arf");
2454 /* Give some hope of miraculous recovery by forcing a track reload */
2455 tracks[track_widx].filesize = 0;
2456 /* Stop this buffering run */
2457 return ret_val;
2460 trigger_cpu_boost();
2461 while (tracks[track_widx].filerem > 0)
2463 size_t copy_n;
2464 int overlap;
2465 int rc;
2467 /* copy_n is the largest chunk that is safe to read */
2468 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2470 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2471 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2472 break;
2474 /* rc is the actual amount read */
2475 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2477 if (rc < 0)
2479 logf("File ended %ldB early", tracks[track_widx].filerem);
2480 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2481 tracks[track_widx].filerem = 0;
2482 break;
2485 /* How much of the playing track did we overwrite */
2486 if (buf_widx == CUR_TI->buf_idx)
2488 /* Special handling; zero or full overlap? */
2489 if (track_widx == track_ridx && CUR_TI->available == 0)
2490 overlap = 0;
2491 else
2492 overlap = rc;
2494 else
2495 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2497 if ((unsigned)rc > tracks[track_widx].filerem)
2499 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2500 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2501 tracks[track_widx].filerem = rc;
2504 /* Advance buffer */
2505 buf_widx = RINGBUF_ADD(buf_widx, rc);
2506 tracks[track_widx].available += rc;
2507 tracks[track_widx].filerem -= rc;
2509 /* If we write into the playing track, adjust it's buffer info */
2510 if (overlap > 0)
2512 CUR_TI->buf_idx += overlap;
2513 CUR_TI->start_pos += overlap;
2516 /* For a rebuffer, fill at least this minimum */
2517 if (minimum > (unsigned)rc)
2518 minimum -= rc;
2519 /* Let the codec process up to the watermark */
2520 /* Break immediately if this is a quick buffer, or there is an event */
2521 else if (minimum || audio_yield_codecs())
2523 /* Exit quickly, but don't stop the overall buffering process */
2524 ret_val = true;
2525 break;
2529 if (tracks[track_widx].filerem == 0)
2531 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2532 close(current_fd);
2533 current_fd = -1;
2534 audio_strip_tags();
2536 track_widx++;
2537 track_widx &= MAX_TRACK_MASK;
2539 tracks[track_widx].filesize = 0;
2540 return true;
2542 else
2544 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2545 tracks[track_widx].filesize - tracks[track_widx].filerem);
2546 return ret_val;
2550 static bool audio_loadcodec(bool start_play)
2552 size_t size = 0;
2553 int fd;
2554 int rc;
2555 size_t copy_n;
2556 int prev_track;
2557 char codec_path[MAX_PATH]; /* Full path to codec */
2559 const char * codec_fn =
2560 get_codec_filename(tracks[track_widx].id3.codectype);
2561 if (codec_fn == NULL)
2562 return false;
2564 tracks[track_widx].has_codec = false;
2566 if (start_play)
2568 /* Load the codec directly from disk and save some memory. */
2569 track_ridx = track_widx;
2570 ci.filesize = CUR_TI->filesize;
2571 ci.id3 = &CUR_TI->id3;
2572 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2573 ci.curpos = 0;
2574 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2575 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2576 return true;
2578 else
2580 /* If we already have another track than this one buffered */
2581 if (track_widx != track_ridx)
2583 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2585 /* If the previous codec is the same as this one, there is no need
2586 * to put another copy of it on the file buffer */
2587 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2588 get_codec_base_type(tracks[prev_track].id3.codectype)
2589 && audio_codec_loaded)
2591 logf("Reusing prev. codec");
2592 return true;
2597 codec_get_full_path(codec_path, codec_fn);
2599 fd = open(codec_path, O_RDONLY);
2600 if (fd < 0)
2602 logf("Codec doesn't exist!");
2603 return false;
2606 tracks[track_widx].codecsize = filesize(fd);
2608 /* Never load a partial codec */
2609 if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0)
2611 logf("Not enough space");
2612 close(fd);
2613 return false;
2616 while (size < tracks[track_widx].codecsize)
2618 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2619 rc = read(fd, &filebuf[buf_widx], copy_n);
2620 if (rc < 0)
2622 close(fd);
2623 /* This is an error condition, likely the codec file is corrupt */
2624 logf("Partial codec loaded");
2625 /* Must undo the buffer write of the partial codec */
2626 buf_widx = RINGBUF_SUB(buf_widx, size);
2627 tracks[track_widx].codecsize = 0;
2628 return false;
2631 buf_widx = RINGBUF_ADD(buf_widx, rc);
2633 size += rc;
2636 tracks[track_widx].has_codec = true;
2638 close(fd);
2639 logf("Done: %ldB", size);
2641 return true;
2644 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2645 static void audio_set_elapsed(struct mp3entry* id3)
2647 unsigned long offset = id3->offset > id3->first_frame_offset ?
2648 id3->offset - id3->first_frame_offset : 0;
2650 if ( id3->vbr ) {
2651 if ( id3->has_toc ) {
2652 /* calculate elapsed time using TOC */
2653 int i;
2654 unsigned int remainder, plen, relpos, nextpos;
2656 /* find wich percent we're at */
2657 for (i=0; i<100; i++ )
2658 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2659 break;
2661 i--;
2662 if (i < 0)
2663 i = 0;
2665 relpos = id3->toc[i];
2667 if (i < 99)
2668 nextpos = id3->toc[i+1];
2669 else
2670 nextpos = 256;
2672 remainder = offset - (relpos * (id3->filesize / 256));
2674 /* set time for this percent (divide before multiply to prevent
2675 overflow on long files. loss of precision is negligible on
2676 short files) */
2677 id3->elapsed = i * (id3->length / 100);
2679 /* calculate remainder time */
2680 plen = (nextpos - relpos) * (id3->filesize / 256);
2681 id3->elapsed += (((remainder * 100) / plen) *
2682 (id3->length / 10000));
2684 else {
2685 /* no TOC exists. set a rough estimate using average bitrate */
2686 int tpk = id3->length /
2687 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2688 1024);
2689 id3->elapsed = offset / 1024 * tpk;
2692 else
2694 /* constant bitrate, use exact calculation */
2695 if (id3->bitrate != 0)
2696 id3->elapsed = offset / (id3->bitrate / 8);
2700 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2702 char *trackname;
2703 off_t size;
2704 char msgbuf[80];
2706 /* Stop buffer filling if there is no free track entries.
2707 Don't fill up the last track entry (we wan't to store next track
2708 metadata there). */
2709 if (!audio_have_free_tracks())
2711 logf("No free tracks");
2712 return false;
2715 if (current_fd >= 0)
2717 logf("Nonzero fd in alt");
2718 close(current_fd);
2719 current_fd = -1;
2722 last_peek_offset++;
2723 peek_again:
2724 logf("Buffering track:%d/%d", track_widx, track_ridx);
2725 /* Get track name from current playlist read position. */
2726 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2728 /* Handle broken playlists. */
2729 current_fd = open(trackname, O_RDONLY);
2730 if (current_fd < 0)
2732 logf("Open failed");
2733 /* Skip invalid entry from playlist. */
2734 playlist_skip_entry(NULL, last_peek_offset);
2736 else
2737 break;
2740 if (!trackname)
2742 logf("End-of-playlist");
2743 playlist_end = true;
2744 return false;
2747 /* Initialize track entry. */
2748 size = filesize(current_fd);
2749 tracks[track_widx].filerem = size;
2750 tracks[track_widx].filesize = size;
2751 tracks[track_widx].available = 0;
2753 /* Set default values */
2754 if (start_play)
2756 int last_codec = current_codec;
2758 set_current_codec(CODEC_IDX_AUDIO);
2759 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2760 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2761 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2762 dsp_configure(DSP_RESET, 0);
2763 set_current_codec(last_codec);
2766 /* Get track metadata if we don't already have it. */
2767 if (!tracks[track_widx].taginfo_ready)
2769 if (get_metadata(&(tracks[track_widx].id3),current_fd,trackname))
2771 tracks[track_widx].taginfo_ready = true;
2772 if (start_play)
2774 track_changed = true;
2775 playlist_update_resume_info(audio_current_track());
2778 else
2780 logf("mde:%s!",trackname);
2782 /* Set filesize to zero to indicate no file was loaded. */
2783 tracks[track_widx].filesize = 0;
2784 tracks[track_widx].filerem = 0;
2785 close(current_fd);
2786 current_fd = -1;
2788 /* Skip invalid entry from playlist. */
2789 playlist_skip_entry(NULL, last_peek_offset);
2790 tracks[track_widx].taginfo_ready = false;
2791 goto peek_again;
2796 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2798 char cuepath[MAX_PATH];
2800 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2802 if (look_for_cuesheet_file(trackname, cuepath) &&
2803 parse_cuesheet(cuepath, cue))
2805 strcpy((cue)->audio_filename, trackname);
2806 if (start_play)
2807 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2811 /* Load the codec. */
2812 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2813 if (!audio_loadcodec(start_play))
2815 /* Set filesize to zero to indicate no file was loaded. */
2816 tracks[track_widx].filesize = 0;
2817 tracks[track_widx].filerem = 0;
2818 close(current_fd);
2819 current_fd = -1;
2821 if (tracks[track_widx].codecsize)
2823 /* No space for codec on buffer, not an error */
2824 tracks[track_widx].codecsize = 0;
2825 return false;
2828 /* This is an error condition, either no codec was found, or reading
2829 * the codec file failed part way through, either way, skip the track */
2830 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2831 /* We should not use gui_syncplash from audio thread! */
2832 gui_syncsplash(HZ*2, msgbuf);
2833 /* Skip invalid entry from playlist. */
2834 playlist_skip_entry(NULL, last_peek_offset);
2835 tracks[track_widx].taginfo_ready = false;
2836 goto peek_again;
2839 tracks[track_widx].start_pos = 0;
2840 set_filebuf_watermark(buffer_margin);
2841 tracks[track_widx].id3.elapsed = 0;
2843 if (offset > 0)
2845 switch (tracks[track_widx].id3.codectype) {
2846 case AFMT_MPA_L1:
2847 case AFMT_MPA_L2:
2848 case AFMT_MPA_L3:
2849 lseek(current_fd, offset, SEEK_SET);
2850 tracks[track_widx].id3.offset = offset;
2851 audio_set_elapsed(&tracks[track_widx].id3);
2852 tracks[track_widx].filerem = size - offset;
2853 ci.curpos = offset;
2854 tracks[track_widx].start_pos = offset;
2855 break;
2857 case AFMT_WAVPACK:
2858 lseek(current_fd, offset, SEEK_SET);
2859 tracks[track_widx].id3.offset = offset;
2860 tracks[track_widx].id3.elapsed =
2861 tracks[track_widx].id3.length / 2;
2862 tracks[track_widx].filerem = size - offset;
2863 ci.curpos = offset;
2864 tracks[track_widx].start_pos = offset;
2865 break;
2867 case AFMT_OGG_VORBIS:
2868 case AFMT_SPEEX:
2869 case AFMT_FLAC:
2870 case AFMT_PCM_WAV:
2871 case AFMT_A52:
2872 case AFMT_AAC:
2873 case AFMT_MPC:
2874 case AFMT_APE:
2875 tracks[track_widx].id3.offset = offset;
2876 break;
2880 logf("alt:%s", trackname);
2881 tracks[track_widx].buf_idx = buf_widx;
2883 return audio_read_file(rebuffer);
2886 static bool audio_read_next_metadata(void)
2888 int fd;
2889 char *trackname;
2890 int next_idx;
2891 int status;
2893 next_idx = track_widx;
2894 if (tracks[next_idx].taginfo_ready)
2896 next_idx++;
2897 next_idx &= MAX_TRACK_MASK;
2899 if (tracks[next_idx].taginfo_ready)
2900 return true;
2903 trackname = playlist_peek(last_peek_offset + 1);
2904 if (!trackname)
2905 return false;
2907 fd = open(trackname, O_RDONLY);
2908 if (fd < 0)
2909 return false;
2911 status = get_metadata(&(tracks[next_idx].id3),fd,trackname);
2912 /* Preload the glyphs in the tags */
2913 if (status)
2915 tracks[next_idx].taginfo_ready = true;
2916 if (tracks[next_idx].id3.title)
2917 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2918 if (tracks[next_idx].id3.artist)
2919 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2920 if (tracks[next_idx].id3.album)
2921 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2923 close(fd);
2925 return status;
2928 /* Send callback events to notify about new tracks. */
2929 static void audio_generate_postbuffer_events(void)
2931 int cur_idx;
2932 int last_idx = -1;
2934 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2936 if (audio_have_tracks())
2938 cur_idx = track_ridx;
2940 while (1) {
2941 if (!tracks[cur_idx].event_sent)
2943 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2945 /* Mark the event 'sent' even if we don't really send one */
2946 tracks[last_idx].event_sent = true;
2947 if (track_buffer_callback)
2948 track_buffer_callback(&tracks[last_idx].id3, false);
2950 last_idx = cur_idx;
2952 if (cur_idx == track_widx)
2953 break;
2954 cur_idx++;
2955 cur_idx &= MAX_TRACK_MASK;
2958 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2960 tracks[last_idx].event_sent = true;
2961 if (track_buffer_callback)
2962 track_buffer_callback(&tracks[last_idx].id3, true);
2967 static bool audio_initialize_buffer_fill(bool clear_tracks)
2969 /* Don't initialize if we're already initialized */
2970 if (filling)
2971 return true;
2973 logf("Starting buffer fill");
2975 /* Set the filling flag true before calling audio_clear_tracks as that
2976 * function can yield and we start looping. */
2977 filling = true;
2979 if (clear_tracks)
2980 audio_clear_track_entries(false);
2982 /* Save the current resume position once. */
2983 playlist_update_resume_info(audio_current_track());
2985 return true;
2988 static void audio_fill_file_buffer(
2989 bool start_play, bool rebuffer, size_t offset)
2991 bool had_next_track = audio_next_track() != NULL;
2992 bool continue_buffering;
2994 /* Must reset the buffer before use if trashed or voice only - voice
2995 file size shouldn't have changed so we can go straight from
2996 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2997 if (buffer_state != BUFFER_STATE_INITIALIZED)
2998 audio_reset_buffer();
3000 if (!audio_initialize_buffer_fill(!start_play))
3001 return ;
3003 /* If we have a partially buffered track, continue loading,
3004 * otherwise load a new track */
3005 if (tracks[track_widx].filesize > 0)
3006 continue_buffering = audio_read_file(rebuffer);
3007 else
3008 continue_buffering = audio_load_track(offset, start_play, rebuffer);
3010 if (!had_next_track && audio_next_track())
3011 track_changed = true;
3013 /* If we're done buffering */
3014 if (!continue_buffering)
3016 audio_read_next_metadata();
3018 audio_generate_postbuffer_events();
3019 filling = false;
3021 #ifndef SIMULATOR
3022 ata_sleep();
3023 #endif
3027 static void audio_rebuffer(void)
3029 logf("Forcing rebuffer");
3031 /* Stop in progress fill, and clear open file descriptor */
3032 if (current_fd >= 0)
3034 close(current_fd);
3035 current_fd = -1;
3037 filling = false;
3039 /* Reset buffer and track pointers */
3040 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3041 track_widx = track_ridx;
3042 audio_clear_track_entries(true);
3043 CUR_TI->available = 0;
3045 /* Fill the buffer */
3046 last_peek_offset = -1;
3047 CUR_TI->filesize = 0;
3048 CUR_TI->start_pos = 0;
3049 ci.curpos = 0;
3051 if (!CUR_TI->taginfo_ready)
3052 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
3054 audio_fill_file_buffer(false, true, 0);
3057 static int audio_check_new_track(void)
3059 int track_count = audio_track_count();
3060 int old_track_ridx = track_ridx;
3061 bool forward;
3063 if (dir_skip)
3065 dir_skip = false;
3066 if (playlist_next_dir(ci.new_track))
3068 ci.new_track = 0;
3069 CUR_TI->taginfo_ready = false;
3070 audio_rebuffer();
3071 goto skip_done;
3073 else
3075 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3076 return Q_CODEC_REQUEST_FAILED;
3080 if (new_playlist)
3081 ci.new_track = 0;
3083 /* If the playlist isn't that big */
3084 if (!playlist_check(ci.new_track))
3086 if (ci.new_track >= 0)
3088 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3089 return Q_CODEC_REQUEST_FAILED;
3091 /* Find the beginning backward if the user over-skips it */
3092 while (!playlist_check(++ci.new_track))
3093 if (ci.new_track >= 0)
3095 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3096 return Q_CODEC_REQUEST_FAILED;
3099 /* Update the playlist */
3100 last_peek_offset -= ci.new_track;
3102 if (playlist_next(ci.new_track) < 0)
3104 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3105 return Q_CODEC_REQUEST_FAILED;
3108 if (new_playlist)
3110 ci.new_track = 1;
3111 new_playlist = false;
3114 /* Save the old track */
3115 prev_ti = CUR_TI;
3117 /* Move to the new track */
3118 track_ridx += ci.new_track;
3119 track_ridx &= MAX_TRACK_MASK;
3121 if (automatic_skip)
3122 playlist_end = false;
3124 track_changed = !automatic_skip;
3126 /* If it is not safe to even skip this many track entries */
3127 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3129 ci.new_track = 0;
3130 CUR_TI->taginfo_ready = false;
3131 audio_rebuffer();
3132 goto skip_done;
3135 forward = ci.new_track > 0;
3136 ci.new_track = 0;
3138 /* If the target track is clearly not in memory */
3139 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3141 audio_rebuffer();
3142 goto skip_done;
3145 /* The track may be in memory, see if it really is */
3146 if (forward)
3148 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3149 audio_rebuffer();
3151 else
3153 int cur_idx = track_ridx;
3154 bool taginfo_ready = true;
3155 bool wrap = track_ridx > old_track_ridx;
3157 while (1)
3159 cur_idx++;
3160 cur_idx &= MAX_TRACK_MASK;
3161 if (!(wrap || cur_idx < old_track_ridx))
3162 break;
3164 /* If we hit a track in between without valid tag info, bail */
3165 if (!tracks[cur_idx].taginfo_ready)
3167 taginfo_ready = false;
3168 break;
3171 tracks[cur_idx].available = tracks[cur_idx].filesize;
3172 if (tracks[cur_idx].codecsize)
3173 tracks[cur_idx].has_codec = true;
3175 if (taginfo_ready)
3177 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3178 audio_rebuffer();
3180 else
3182 CUR_TI->taginfo_ready = false;
3183 audio_rebuffer();
3187 skip_done:
3188 audio_update_trackinfo();
3189 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3190 return Q_CODEC_REQUEST_COMPLETE;
3193 static int audio_rebuffer_and_seek(size_t newpos)
3195 size_t real_preseek;
3196 int fd;
3197 char *trackname;
3199 /* (Re-)open current track's file handle. */
3200 trackname = playlist_peek(0);
3201 fd = open(trackname, O_RDONLY);
3202 if (fd < 0)
3204 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3205 return Q_CODEC_REQUEST_FAILED;
3208 if (current_fd >= 0)
3209 close(current_fd);
3210 current_fd = fd;
3212 playlist_end = false;
3214 ci.curpos = newpos;
3216 /* Clear codec buffer. */
3217 track_widx = track_ridx;
3218 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3220 last_peek_offset = 0;
3221 filling = false;
3222 audio_initialize_buffer_fill(true);
3224 /* This may have been tweaked by the id3v1 code */
3225 CUR_TI->filesize=filesize(fd);
3226 if (newpos > conf_preseek)
3228 CUR_TI->start_pos = newpos - conf_preseek;
3229 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3230 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3231 real_preseek = conf_preseek;
3233 else
3235 CUR_TI->start_pos = 0;
3236 CUR_TI->filerem = CUR_TI->filesize;
3237 real_preseek = newpos;
3240 CUR_TI->available = 0;
3242 audio_read_file(real_preseek);
3244 /* Account for the data we just read that is 'behind' us now */
3245 CUR_TI->available -= real_preseek;
3247 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3249 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3250 return Q_CODEC_REQUEST_COMPLETE;
3253 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3254 bool last_track))
3256 track_buffer_callback = handler;
3259 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3260 bool last_track))
3262 track_unbuffer_callback = handler;
3265 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3267 track_changed_callback = handler;
3270 unsigned long audio_prev_elapsed(void)
3272 return prev_track_elapsed;
3275 static void audio_stop_codec_flush(void)
3277 ci.stop_codec = true;
3278 pcmbuf_pause(true);
3280 while (audio_codec_loaded)
3281 yield();
3283 /* If the audio codec is not loaded any more, and the audio is still
3284 * playing, it is now and _only_ now safe to call this function from the
3285 * audio thread */
3286 if (pcm_is_playing())
3287 pcmbuf_play_stop();
3288 pcmbuf_pause(paused);
3291 static void audio_stop_playback(void)
3293 /* If we were playing, save resume information */
3294 if (playing)
3296 struct mp3entry *id3 = NULL;
3298 if (!playlist_end || !ci.stop_codec)
3300 /* Set this early, the outside code yields and may allow the codec
3301 to try to wait for a reply on a buffer wait */
3302 ci.stop_codec = true;
3303 id3 = audio_current_track();
3306 /* Save the current playing spot, or NULL if the playlist has ended */
3307 playlist_update_resume_info(id3);
3309 prev_track_elapsed = CUR_TI->id3.elapsed;
3311 /* Increment index so runtime info is saved in audio_clear_track_entries().
3312 * Done here, as audio_stop_playback() may be called more than once.
3313 * Don't update runtime unless playback is stopped because of end of playlist.
3314 * Updating runtime when manually stopping a tracks, can destroy autoscores
3315 * and playcounts.
3317 if (playlist_end)
3319 track_ridx++;
3320 track_ridx &= MAX_TRACK_MASK;
3324 filling = false;
3325 paused = false;
3326 audio_stop_codec_flush();
3327 playing = false;
3329 if (current_fd >= 0)
3331 close(current_fd);
3332 current_fd = -1;
3335 /* Mark all entries null. */
3336 audio_clear_track_entries(false);
3339 static void audio_play_start(size_t offset)
3341 #if INPUT_SRC_CAPS != 0
3342 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3343 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3344 #endif
3346 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3347 paused = false;
3348 audio_stop_codec_flush();
3350 track_changed = true;
3351 playlist_end = false;
3353 playing = true;
3355 ci.new_track = 0;
3356 ci.seek_time = 0;
3357 wps_offset = 0;
3359 if (current_fd >= 0)
3361 close(current_fd);
3362 current_fd = -1;
3365 sound_set_volume(global_settings.volume);
3366 track_widx = track_ridx = 0;
3367 buf_ridx = buf_widx = 0;
3369 /* Mark all entries null. */
3370 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3372 last_peek_offset = -1;
3374 /* Officially playing */
3375 queue_reply(&audio_queue, 1);
3377 audio_fill_file_buffer(true, false, offset);
3379 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3380 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3384 /* Invalidates all but currently playing track. */
3385 static void audio_invalidate_tracks(void)
3387 if (audio_have_tracks())
3389 last_peek_offset = 0;
3390 playlist_end = false;
3391 track_widx = track_ridx;
3393 /* Mark all other entries null (also buffered wrong metadata). */
3394 audio_clear_track_entries(true);
3396 /* If the current track is fully buffered, advance the write pointer */
3397 if (tracks[track_widx].filerem == 0)
3398 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3400 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3402 audio_read_next_metadata();
3406 static void audio_new_playlist(void)
3408 /* Prepare to start a new fill from the beginning of the playlist */
3409 last_peek_offset = -1;
3410 if (audio_have_tracks())
3412 if (paused)
3413 skipped_during_pause = true;
3414 playlist_end = false;
3415 track_widx = track_ridx;
3416 audio_clear_track_entries(true);
3418 track_widx++;
3419 track_widx &= MAX_TRACK_MASK;
3421 /* Stop reading the current track */
3422 CUR_TI->filerem = 0;
3423 close(current_fd);
3424 current_fd = -1;
3426 /* Mark the current track as invalid to prevent skipping back to it */
3427 CUR_TI->taginfo_ready = false;
3429 /* Invalidate the buffer other than the playing track */
3430 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3433 /* Signal the codec to initiate a track change forward */
3434 new_playlist = true;
3435 ci.new_track = 1;
3437 /* Officially playing */
3438 queue_reply(&audio_queue, 1);
3440 audio_fill_file_buffer(false, true, 0);
3443 static void audio_initiate_track_change(long direction)
3445 playlist_end = false;
3446 ci.new_track += direction;
3447 wps_offset -= direction;
3448 if (paused)
3449 skipped_during_pause = true;
3452 static void audio_initiate_dir_change(long direction)
3454 playlist_end = false;
3455 dir_skip = true;
3456 ci.new_track = direction;
3457 if (paused)
3458 skipped_during_pause = true;
3462 * Layout audio buffer as follows - iram buffer depends on target:
3463 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3465 static void audio_reset_buffer(void)
3467 /* see audio_get_recording_buffer if this is modified */
3468 logf("audio_reset_buffer");
3470 /* If the setup of anything allocated before the file buffer is
3471 changed, do check the adjustments after the buffer_alloc call
3472 as it will likely be affected and need sliding over */
3474 /* Initially set up file buffer as all space available */
3475 malloc_buf = audiobuf + talk_get_bufsize();
3476 /* Align the malloc buf to line size. Especially important to cf
3477 targets that do line reads/writes. */
3478 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3479 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3480 filebuflen = audiobufend - filebuf;
3482 /* Allow for codec swap space at end of audio buffer */
3483 if (talk_voice_required())
3485 /* Layout of swap buffer:
3486 * #ifdef IRAM_STEAL (dedicated iram_buf):
3487 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3488 * #else:
3489 * audiobuf...|dram_buf|iram_buf|audiobufend
3491 #ifdef PLAYBACK_VOICE
3492 /* Check for an absolutely nasty situation which should never,
3493 ever happen - frankly should just panic */
3494 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3496 logf("buffer reset with voice swapped");
3498 /* line align length which line aligns the calculations below since
3499 all sizes are also at least line aligned - needed for memswap128 */
3500 filebuflen &= ~15;
3501 #ifdef IRAM_STEAL
3502 filebuflen -= CODEC_SIZE;
3503 #else
3504 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3505 #endif
3506 /* Allocate buffers for swapping voice <=> audio */
3507 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3508 and out of the way of buffer usage or else a call to audio_get_buffer
3509 and subsequent buffer use might trash the swap space. A plugin
3510 initializing IRAM after getting the full buffer would present similar
3511 problem. Options include: failing the request if the other buffer
3512 has been obtained already or never allowing use of the voice IRAM
3513 buffer within the audio buffer. Using buffer_alloc basically
3514 implements the second in a more convenient way. */
3515 dram_buf = filebuf + filebuflen;
3517 #ifdef IRAM_STEAL
3518 /* Allocate voice IRAM swap buffer once */
3519 if (iram_buf == NULL)
3521 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3522 /* buffer_alloc moves audiobuf; this is safe because only the end
3523 * has been touched so far in this function and the address of
3524 * filebuf + filebuflen is not changed */
3525 malloc_buf += CODEC_IRAM_SIZE;
3526 filebuf += CODEC_IRAM_SIZE;
3527 filebuflen -= CODEC_IRAM_SIZE;
3529 #else
3530 /* Allocate iram_buf after dram_buf */
3531 iram_buf = dram_buf + CODEC_SIZE;
3532 #endif /* IRAM_STEAL */
3533 #endif /* PLAYBACK_VOICE */
3535 else
3537 #ifdef PLAYBACK_VOICE
3538 /* No swap buffers needed */
3539 iram_buf = NULL;
3540 dram_buf = NULL;
3541 #endif
3544 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3545 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3547 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3548 will already be line aligned */
3549 filebuflen &= ~3;
3551 /* Set the high watermark as 75% full...or 25% empty :) */
3552 #if MEM > 8
3553 high_watermark = 3*filebuflen / 4;
3554 #endif
3556 /* Clear any references to the file buffer */
3557 buffer_state = BUFFER_STATE_INITIALIZED;
3559 #ifdef ROCKBOX_HAS_LOGF
3560 /* Make sure everything adds up - yes, some info is a bit redundant but
3561 aids viewing and the sumation of certain variables should add up to
3562 the location of others. */
3564 size_t pcmbufsize;
3565 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3566 logf("mabuf: %08X", (unsigned)malloc_buf);
3567 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3568 logf("fbuf: %08X", (unsigned)filebuf);
3569 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3570 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3571 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3572 logf("pcmb: %08X", (unsigned)pcmbuf);
3573 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3574 if (dram_buf)
3576 logf("dramb: %08X", (unsigned)dram_buf);
3577 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3579 if (iram_buf)
3581 logf("iramb: %08X", (unsigned)iram_buf);
3582 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3585 #endif
3588 #if MEM > 8
3589 /* we dont want this rebuffering on targets with little ram
3590 because the disk may never spin down */
3591 static bool ata_fillbuffer_callback(void)
3593 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3594 return true;
3596 #endif
3598 static void audio_thread(void)
3600 struct queue_event ev;
3602 pcm_postinit();
3604 #ifdef PLAYBACK_VOICE
3605 /* Unlock semaphore that init stage locks before creating this thread */
3606 semaphore_release(&sem_codecthread);
3608 /* Buffers must be set up by now - should panic - really */
3609 if (buffer_state != BUFFER_STATE_INITIALIZED)
3611 logf("audio_thread start: no buffer");
3614 /* Have to wait for voice to load up or else the codec swap will be
3615 invalid when an audio codec is loaded */
3616 wait_for_voice_swap_in();
3617 #endif
3619 while (1)
3621 if (filling)
3623 queue_wait_w_tmo(&audio_queue, &ev, 0);
3624 if (ev.id == SYS_TIMEOUT)
3625 ev.id = Q_AUDIO_FILL_BUFFER;
3627 else
3629 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3630 #if MEM > 8
3631 if (playing && (ev.id == SYS_TIMEOUT) &&
3632 (FILEBUFUSED < high_watermark))
3633 register_ata_idle_func(ata_fillbuffer_callback);
3634 #endif
3637 switch (ev.id) {
3638 #if MEM > 8
3639 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3640 /* only fill if the disk is still spining */
3641 #ifndef SIMULATOR
3642 if (!ata_disk_is_active())
3643 break;
3644 #endif
3645 #endif /* MEM > 8 */
3646 /* else fall through to Q_AUDIO_FILL_BUFFER */
3647 case Q_AUDIO_FILL_BUFFER:
3648 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3649 if (!filling)
3650 if (!playing || playlist_end || ci.stop_codec)
3651 break;
3652 audio_fill_file_buffer(false, false, 0);
3653 break;
3655 case Q_AUDIO_PLAY:
3656 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3657 if (playing && ev.data <= 0)
3658 audio_new_playlist();
3659 else
3661 audio_stop_playback();
3662 audio_play_start((size_t)ev.data);
3664 break;
3666 case Q_AUDIO_STOP:
3667 LOGFQUEUE("audio < Q_AUDIO_STOP");
3668 if (playing)
3669 audio_stop_playback();
3670 if (ev.data != 0)
3671 queue_clear(&audio_queue);
3672 break;
3674 case Q_AUDIO_PAUSE:
3675 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3676 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3677 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3678 skipped_during_pause = false;
3679 if (!playing)
3680 break;
3681 pcmbuf_pause((bool)ev.data);
3682 paused = (bool)ev.data;
3683 break;
3685 case Q_AUDIO_SKIP:
3686 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3687 audio_initiate_track_change((long)ev.data);
3688 break;
3690 case Q_AUDIO_PRE_FF_REWIND:
3691 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3692 if (!playing)
3693 break;
3694 pcmbuf_pause(true);
3695 break;
3697 case Q_AUDIO_FF_REWIND:
3698 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3699 if (!playing)
3700 break;
3701 ci.seek_time = (long)ev.data+1;
3702 break;
3704 case Q_AUDIO_REBUFFER_SEEK:
3705 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3706 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3707 break;
3709 case Q_AUDIO_CHECK_NEW_TRACK:
3710 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3711 queue_reply(&audio_queue, audio_check_new_track());
3712 break;
3714 case Q_AUDIO_DIR_SKIP:
3715 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3716 playlist_end = false;
3717 audio_initiate_dir_change(ev.data);
3718 break;
3720 case Q_AUDIO_FLUSH:
3721 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3722 audio_invalidate_tracks();
3723 break;
3725 case Q_AUDIO_TRACK_CHANGED:
3726 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3727 if (track_changed_callback)
3728 track_changed_callback(&CUR_TI->id3);
3729 track_changed = true;
3730 playlist_update_resume_info(audio_current_track());
3731 break;
3733 #ifndef SIMULATOR
3734 case SYS_USB_CONNECTED:
3735 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3736 if (playing)
3737 audio_stop_playback();
3738 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3739 usb_wait_for_disconnect(&audio_queue);
3740 break;
3741 #endif
3743 case SYS_TIMEOUT:
3744 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3745 break;
3747 default:
3748 LOGFQUEUE("audio < default");
3749 } /* end switch */
3750 } /* end while */
3753 #ifdef ROCKBOX_HAS_LOGF
3754 static void audio_test_track_changed_event(struct mp3entry *id3)
3756 (void)id3;
3758 logf("tce:%s", id3->path);
3760 #endif
3762 /* Initialize the audio system - called from init() in main.c.
3763 * Last function because of all the references to internal symbols
3765 void audio_init(void)
3767 #ifdef PLAYBACK_VOICE
3768 static bool voicetagtrue = true;
3769 static struct mp3entry id3_voice;
3770 struct thread_entry *voice_thread_p = NULL;
3771 #endif
3772 struct thread_entry *audio_thread_p;
3774 /* Can never do this twice */
3775 if (audio_is_initialized)
3777 logf("audio: already initialized");
3778 return;
3781 logf("audio: initializing");
3783 /* Initialize queues before giving control elsewhere in case it likes
3784 to send messages. Thread creation will be delayed however so nothing
3785 starts running until ready if something yields such as talk_init. */
3786 #ifdef PLAYBACK_VOICE
3787 /* Take ownership of lock to prevent playback of anything before audio
3788 hardware is initialized - audio thread unlocks it after final init
3789 stage */
3790 semaphore_init(&sem_codecthread, 1, 0);
3791 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3792 #endif
3793 queue_init(&audio_queue, true);
3794 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3795 queue_init(&codec_queue, true);
3797 pcm_init();
3799 #ifdef ROCKBOX_HAS_LOGF
3800 audio_set_track_changed_event(audio_test_track_changed_event);
3801 #endif
3803 /* Initialize codec api. */
3804 ci.read_filebuf = codec_filebuf_callback;
3805 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3806 ci.get_codec_memory = codec_get_memory_callback;
3807 ci.request_buffer = codec_request_buffer_callback;
3808 ci.advance_buffer = codec_advance_buffer_callback;
3809 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3810 ci.request_next_track = codec_request_next_track_callback;
3811 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3812 ci.seek_buffer = codec_seek_buffer_callback;
3813 ci.seek_complete = codec_seek_complete_callback;
3814 ci.set_elapsed = codec_set_elapsed_callback;
3815 ci.set_offset = codec_set_offset_callback;
3816 ci.configure = codec_configure_callback;
3817 ci.discard_codec = codec_discard_codec_callback;
3819 /* Initialize voice codec api. */
3820 #ifdef PLAYBACK_VOICE
3821 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3822 memset(&id3_voice, 0, sizeof(id3_voice));
3823 ci_voice.read_filebuf = voice_filebuf_callback;
3824 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3825 ci_voice.get_codec_memory = voice_get_memory_callback;
3826 ci_voice.request_buffer = voice_request_buffer_callback;
3827 ci_voice.advance_buffer = voice_advance_buffer_callback;
3828 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3829 ci_voice.request_next_track = voice_request_next_track_callback;
3830 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3831 ci_voice.seek_buffer = voice_seek_buffer_callback;
3832 ci_voice.seek_complete = voice_do_nothing;
3833 ci_voice.set_elapsed = voice_set_elapsed_callback;
3834 ci_voice.set_offset = voice_set_offset_callback;
3835 ci_voice.configure = voice_configure_callback;
3836 ci_voice.discard_codec = voice_do_nothing;
3837 ci_voice.taginfo_ready = &voicetagtrue;
3838 ci_voice.id3 = &id3_voice;
3839 id3_voice.frequency = 11200;
3840 id3_voice.length = 1000000L;
3841 #endif
3843 /* initialize the buffer */
3844 filebuf = audiobuf;
3846 /* audio_reset_buffer must to know the size of voice buffer so init
3847 talk first */
3848 talk_init();
3850 codec_thread_p = create_thread(
3851 codec_thread, codec_stack, sizeof(codec_stack),
3852 CREATE_THREAD_FROZEN,
3853 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3854 IF_COP(, CPU));
3856 audio_thread_p = create_thread(audio_thread, audio_stack,
3857 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3858 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3859 IF_COP(, CPU));
3861 #ifdef PLAYBACK_VOICE
3862 /* TODO: Change this around when various speech codecs can be used */
3863 if (talk_voice_required())
3865 logf("Starting voice codec");
3866 queue_init(&voice_queue, true);
3867 voice_thread_p = create_thread(voice_thread, voice_stack,
3868 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3869 voice_thread_name
3870 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3872 #endif
3874 /* Set crossfade setting for next buffer init which should be about... */
3875 pcmbuf_crossfade_enable(global_settings.crossfade);
3877 /* ...now! Set up the buffers */
3878 audio_reset_buffer();
3880 /* Probably safe to say */
3881 audio_is_initialized = true;
3883 sound_settings_apply();
3884 #ifdef HAVE_WM8758
3885 eq_hw_enable(global_settings.eq_hw_enabled);
3886 #endif
3887 #ifndef HAVE_FLASH_STORAGE
3888 audio_set_buffer_margin(global_settings.buffer_margin);
3889 #endif
3891 /* it's safe to let the threads run now */
3892 thread_thaw(codec_thread_p);
3893 #ifdef PLAYBACK_VOICE
3894 if (voice_thread_p)
3895 thread_thaw(voice_thread_p);
3896 #endif
3897 thread_thaw(audio_thread_p);
3898 } /* audio_init */