The install window doesn't need to be wider than the other ones.
[Rockbox.git] / apps / playback.c
blob13167e3ffe6ff1a4a39b4c697bbd67579a8d145c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
34 #include "system.h"
35 #include "thread.h"
36 #include "file.h"
37 #include "panic.h"
38 #include "memory.h"
39 #include "lcd.h"
40 #include "font.h"
41 #include "button.h"
42 #include "kernel.h"
43 #include "tree.h"
44 #include "debug.h"
45 #include "sprintf.h"
46 #include "settings.h"
47 #include "codecs.h"
48 #include "audio.h"
49 #include "logf.h"
50 #include "mp3_playback.h"
51 #include "usb.h"
52 #include "status.h"
53 #include "ata.h"
54 #include "screens.h"
55 #include "playlist.h"
56 #include "playback.h"
57 #include "pcmbuf.h"
58 #include "buffer.h"
59 #include "dsp.h"
60 #include "abrepeat.h"
61 #include "cuesheet.h"
62 #ifdef HAVE_TAGCACHE
63 #include "tagcache.h"
64 #endif
65 #ifdef HAVE_LCD_BITMAP
66 #include "icons.h"
67 #include "peakmeter.h"
68 #include "action.h"
69 #endif
70 #include "lang.h"
71 #include "bookmark.h"
72 #include "misc.h"
73 #include "sound.h"
74 #include "metadata.h"
75 #include "splash.h"
76 #include "talk.h"
77 #include "ata_idle_notify.h"
79 #ifdef HAVE_RECORDING
80 #include "recording.h"
81 #include "talk.h"
82 #endif
84 #ifdef HAVE_WM8758
85 #include "menus/eq_menu.h"
86 #endif
88 #define PLAYBACK_VOICE
91 /* default point to start buffer refill */
92 #define AUDIO_DEFAULT_WATERMARK (1024*512)
93 /* amount of data to read in one read() call */
94 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
95 /* point at which the file buffer will fight for CPU time */
96 #define AUDIO_FILEBUF_CRITICAL (1024*128)
97 /* amount of guess-space to allow for codecs that must hunt and peck
98 * for their correct seeek target, 32k seems a good size */
99 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
101 /* macros to enable logf for queues
102 logging on SYS_TIMEOUT can be disabled */
103 #ifdef SIMULATOR
104 /* Define this for logf output of all queuing except SYS_TIMEOUT */
105 #define PLAYBACK_LOGQUEUES
106 /* Define this to logf SYS_TIMEOUT messages */
107 #define PLAYBACK_LOGQUEUES_SYS_TIMEOUT
108 #endif
110 #ifdef PLAYBACK_LOGQUEUES
111 #define LOGFQUEUE logf
112 #else
113 #define LOGFQUEUE(...)
114 #endif
116 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
117 #define LOGFQUEUE_SYS_TIMEOUT logf
118 #else
119 #define LOGFQUEUE_SYS_TIMEOUT(...)
120 #endif
123 /* Define one constant that includes recording related functionality */
124 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
125 #define AUDIO_HAVE_RECORDING
126 #endif
128 enum {
129 Q_AUDIO_PLAY = 1,
130 Q_AUDIO_STOP,
131 Q_AUDIO_PAUSE,
132 Q_AUDIO_SKIP,
133 Q_AUDIO_PRE_FF_REWIND,
134 Q_AUDIO_FF_REWIND,
135 Q_AUDIO_REBUFFER_SEEK,
136 Q_AUDIO_CHECK_NEW_TRACK,
137 Q_AUDIO_FLUSH,
138 Q_AUDIO_TRACK_CHANGED,
139 Q_AUDIO_DIR_SKIP,
140 Q_AUDIO_POSTINIT,
141 Q_AUDIO_FILL_BUFFER,
142 #if MEM > 8
143 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
144 #endif
145 Q_CODEC_REQUEST_COMPLETE,
146 Q_CODEC_REQUEST_FAILED,
148 Q_VOICE_PLAY,
149 Q_VOICE_STOP,
151 Q_CODEC_LOAD,
152 Q_CODEC_LOAD_DISK,
154 #ifdef AUDIO_HAVE_RECORDING
155 Q_ENCODER_LOAD_DISK,
156 Q_ENCODER_RECORD,
157 #endif
160 /* As defined in plugins/lib/xxx2wav.h */
161 #if MEM > 1
162 #define MALLOC_BUFSIZE (512*1024)
163 #define GUARD_BUFSIZE (32*1024)
164 #else
165 #define MALLOC_BUFSIZE (100*1024)
166 #define GUARD_BUFSIZE (8*1024)
167 #endif
169 /* As defined in plugin.lds */
170 #if defined(CPU_PP)
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
174 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
175 #define CODEC_IRAM_SIZE ((size_t)0x10000)
176 #else
177 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
178 #define CODEC_IRAM_SIZE ((size_t)0xc000)
179 #endif
181 #ifndef IBSS_ATTR_VOICE_STACK
182 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
183 #endif
185 bool audio_is_initialized = false;
187 /* Variables are commented with the threads that use them: *
188 * A=audio, C=codec, V=voice. A suffix of - indicates that *
189 * the variable is read but not updated on that thread. */
190 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
192 /* Main state control */
193 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
194 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
195 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
196 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
198 /* Ring buffer where compressed audio and codecs are loaded */
199 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
200 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
201 /* FIXME: make filebuflen static */
202 size_t filebuflen = 0; /* Size of buffer (A/C-) */
203 /* FIXME: make buf_ridx (C/A-) */
204 static volatile size_t buf_ridx IDATA_ATTR = 0; /* Buffer read position (A/C)*/
205 static volatile size_t buf_widx IDATA_ATTR = 0; /* Buffer write position (A/C-) */
207 /* Possible arrangements of the buffer */
208 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
209 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
210 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
211 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
213 /* Compressed ring buffer helper macros */
214 /* Buffer pointer (p) plus value (v), wrapped if necessary */
215 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
216 /* Buffer pointer (p) minus value (v), wrapped if necessary */
217 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
218 /* How far value (v) plus buffer pointer (p1) will cross buffer pointer (p2) */
219 #define RINGBUF_ADD_CROSS(p1,v,p2) \
220 ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
221 /* Bytes available in the buffer */
222 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
224 /* Track info structure about songs in the file buffer (A/C-) */
225 static struct track_info tracks[MAX_TRACK];
226 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
227 static int track_widx = 0; /* Track being buffered (A) */
229 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
230 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
232 /* Set by the audio thread when the current track information has updated
233 * and the WPS may need to update its cached information */
234 static bool track_changed = false;
236 /* Information used only for filling the buffer */
237 /* Playlist steps from playing track to next track to be buffered (A) */
238 static int last_peek_offset = 0;
239 /* Partially loaded track file handle to continue buffering (A) */
240 static int current_fd = -1;
242 /* Scrobbler support */
243 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
245 /* Track change controls */
246 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
247 static bool playlist_end = false; /* Has the current playlist ended? (A) */
248 static bool dir_skip = false; /* Is a directory skip pending? (A) */
249 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
250 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
251 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
253 /* Callbacks which applications or plugins may set */
254 /* When the playing track has changed from the user's perspective */
255 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
256 /* When a track has been buffered */
257 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
258 /* When a track's buffer has been overwritten or cleared */
259 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
261 /* Configuration */
262 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
263 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
264 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
265 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
266 static bool v1first = false; /* ID3 data control, true if V1 then V2 (A) */
267 #if MEM > 8
268 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
269 #endif
271 /* Multiple threads */
272 static void set_current_codec(int codec_idx);
273 /* Set the watermark to trigger buffer fill (A/C) FIXME */
274 static void set_filebuf_watermark(int seconds);
276 /* Audio thread */
277 static struct event_queue audio_queue;
278 static struct queue_sender_list audio_queue_sender_list;
279 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
280 static const char audio_thread_name[] = "audio";
282 static void audio_thread(void);
283 static void audio_initiate_track_change(long direction);
284 static bool audio_have_tracks(void);
285 static void audio_reset_buffer(void);
287 /* Codec thread */
288 extern struct codec_api ci;
289 static struct event_queue codec_queue NOCACHEBSS_ATTR;
290 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
291 IBSS_ATTR;
292 static const char codec_thread_name[] = "codec";
293 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
295 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
297 /* Voice thread */
298 #ifdef PLAYBACK_VOICE
300 extern struct codec_api ci_voice;
302 static struct thread_entry *voice_thread_p = NULL;
303 static struct event_queue voice_queue NOCACHEBSS_ATTR;
304 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
305 IBSS_ATTR_VOICE_STACK;
306 static const char voice_thread_name[] = "voice codec";
308 /* Voice codec swapping control */
309 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
311 #ifdef SIMULATOR
312 /* IRAM codec swap buffer for sim*/
313 static unsigned char sim_iram[CODEC_IRAM_SIZE];
314 #undef CODEC_IRAM_ORIGIN
315 #define CODEC_IRAM_ORIGIN sim_iram
316 #endif
318 /* iram_buf and dram_buf are either both NULL or both non-NULL */
319 /* Pointer to IRAM buffer for codec swapping */
320 static unsigned char *iram_buf = NULL;
321 /* Pointer to DRAM buffer for codec swapping */
322 static unsigned char *dram_buf = NULL;
323 /* Parity of swap_codec calls - needed because one codec swapping itself in
324 automatically swaps in the other and the swap when unlocking should not
325 happen if the parity is even.
327 static bool swap_codec_parity = false; /* true=odd, false=even */
328 /* Mutex to control which codec (normal/voice) is running */
329 static struct mutex mutex_codecthread NOCACHEBSS_ATTR;
331 /* Voice state */
332 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
333 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
334 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
335 static unsigned char *voicebuf = NULL;
336 static size_t voice_remaining = 0;
338 #ifdef IRAM_STEAL
339 /* Voice IRAM has been stolen for other use */
340 static bool voice_iram_stolen = false;
341 #endif
343 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
345 struct voice_info {
346 void (*callback)(unsigned char **start, size_t* size);
347 size_t size;
348 unsigned char *buf;
350 static void voice_thread(void);
351 static void voice_stop(void);
353 #endif /* PLAYBACK_VOICE */
355 /* --- External interfaces --- */
357 void mp3_play_data(const unsigned char* start, int size,
358 void (*get_more)(unsigned char** start, size_t* size))
360 #ifdef PLAYBACK_VOICE
361 static struct voice_info voice_clip;
362 voice_clip.callback = get_more;
363 voice_clip.buf = (unsigned char*)start;
364 voice_clip.size = size;
365 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
366 queue_post(&voice_queue, Q_VOICE_STOP, 0);
367 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
368 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
369 voice_thread_start = true;
370 trigger_cpu_boost();
371 #else
372 (void) start;
373 (void) size;
374 (void) get_more;
375 #endif
378 void mp3_play_stop(void)
380 #ifdef PLAYBACK_VOICE
381 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
382 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
383 queue_post(&voice_queue, Q_VOICE_STOP, 1);
384 #endif
387 void mp3_play_pause(bool play)
389 /* a dummy */
390 (void)play;
393 bool mp3_is_playing(void)
395 return voice_is_playing;
398 void mpeg_id3_options(bool _v1first)
400 v1first = _v1first;
403 /* If voice could be swapped out - wait for it to return
404 * Used by buffer claming functions.
406 static void wait_for_voice_swap_in(void)
408 #ifdef PLAYBACK_VOICE
409 if (NULL == iram_buf)
410 return;
412 while (current_codec != CODEC_IDX_VOICE)
413 yield();
414 #endif /* PLAYBACK_VOICE */
417 /* This sends a stop message and the audio thread will dump all it's
418 subsequenct messages */
419 static void audio_hard_stop(void)
421 /* Stop playback */
422 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
423 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
426 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
428 unsigned char *buf, *end;
430 if (audio_is_initialized)
432 audio_hard_stop();
433 wait_for_voice_swap_in();
434 voice_stop();
436 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
438 if (buffer_size == NULL)
440 /* Special case for talk_init to use since it already knows it's
441 trashed */
442 buffer_state = BUFFER_STATE_TRASHED;
443 return NULL;
446 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
447 || !talk_voice_required())
449 logf("get buffer: talk, audio");
450 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
451 the talk buffer is not needed because voice isn't being used, or
452 could be BUFFER_STATE_TRASHED already. If state is
453 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
454 without the caller knowing what's going on. Changing certain settings
455 may move it to a worse condition but the memory in use by something
456 else will remain undisturbed.
458 if (buffer_state != BUFFER_STATE_TRASHED)
460 talk_buffer_steal();
461 buffer_state = BUFFER_STATE_TRASHED;
464 buf = audiobuf;
465 end = audiobufend;
467 else
469 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
470 still BUFFER_STATE_INITIALIZED */
471 /* Skip talk buffer and move pcm buffer to end to maximize available
472 contiguous memory - no audio running means voice will not need the
473 swap space */
474 logf("get buffer: audio");
475 buf = audiobuf + talk_get_bufsize();
476 end = audiobufend - pcmbuf_init(audiobufend);
477 buffer_state = BUFFER_STATE_VOICED_ONLY;
480 *buffer_size = end - buf;
482 return buf;
485 #ifdef IRAM_STEAL
486 void audio_iram_steal(void)
488 /* We need to stop audio playback in order to use codec IRAM */
489 audio_hard_stop();
491 #ifdef PLAYBACK_VOICE
492 if (NULL != iram_buf)
494 /* Can't already be stolen */
495 if (voice_iram_stolen)
496 return;
498 /* Must wait for voice to be current again if it is swapped which
499 would cause the caller's buffer to get clobbered when voice locks
500 and runs - we'll wait for it to lock and yield again then make sure
501 the ride has come to a complete stop */
502 wait_for_voice_swap_in();
503 voice_stop();
505 /* Save voice IRAM but just memcpy - safe to do here since voice
506 is current and no audio codec is loaded */
507 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
508 voice_iram_stolen = true;
510 else
512 /* Nothing much to do if no voice */
513 voice_iram_stolen = false;
515 #endif
517 #endif /* IRAM_STEAL */
519 #ifdef HAVE_RECORDING
520 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
522 /* Don't allow overwrite of voice swap area or we'll trash the
523 swapped-out voice codec but can use whole thing if none */
524 unsigned char *end;
526 /* Stop audio and voice. Wait for voice to swap in and be clear
527 of pending events to ensure trouble-free operation of encoders */
528 audio_hard_stop();
529 wait_for_voice_swap_in();
530 voice_stop();
531 talk_buffer_steal();
533 #ifdef PLAYBACK_VOICE
534 /* If no dram_buf, swap space not used and recording gets more
535 memory. Codec swap areas will remain unaffected by the next init
536 since they're allocated at the end of the buffer and their sizes
537 don't change between calls */
538 end = dram_buf;
539 if (NULL == end)
540 #endif /* PLAYBACK_VOICE */
541 end = audiobufend;
543 buffer_state = BUFFER_STATE_TRASHED;
545 *buffer_size = end - audiobuf;
547 return (unsigned char *)audiobuf;
550 bool audio_load_encoder(int afmt)
552 #ifndef SIMULATOR
553 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
554 if (!enc_fn)
555 return false;
557 audio_remove_encoder();
558 ci.enc_codec_loaded = 0; /* clear any previous error condition */
560 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
561 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
563 while (ci.enc_codec_loaded == 0)
564 yield();
566 logf("codec loaded: %d", ci.enc_codec_loaded);
568 return ci.enc_codec_loaded > 0;
569 #else
570 (void)afmt;
571 return true;
572 #endif
573 } /* audio_load_encoder */
575 void audio_remove_encoder(void)
577 #ifndef SIMULATOR
578 /* force encoder codec unload (if currently loaded) */
579 if (ci.enc_codec_loaded <= 0)
580 return;
582 ci.stop_encoder = true;
583 while (ci.enc_codec_loaded > 0)
584 yield();
585 #endif
586 } /* audio_remove_encoder */
588 #endif /* HAVE_RECORDING */
590 struct mp3entry* audio_current_track(void)
592 const char *filename;
593 const char *p;
594 static struct mp3entry temp_id3;
595 int cur_idx;
596 int offset = ci.new_track + wps_offset;
598 cur_idx = track_ridx + offset;
599 cur_idx &= MAX_TRACK_MASK;
601 if (tracks[cur_idx].taginfo_ready)
602 return &tracks[cur_idx].id3;
604 memset(&temp_id3, 0, sizeof(struct mp3entry));
606 filename = playlist_peek(0);
607 if (!filename)
608 filename = "No file!";
610 #ifdef HAVE_TC_RAMCACHE
611 if (tagcache_fill_tags(&temp_id3, filename))
612 return &temp_id3;
613 #endif
615 p = strrchr(filename, '/');
616 if (!p)
617 p = filename;
618 else
619 p++;
621 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
622 temp_id3.title = &temp_id3.path[0];
624 return &temp_id3;
627 struct mp3entry* audio_next_track(void)
629 int next_idx = track_ridx;
631 if (!audio_have_tracks())
632 return NULL;
634 next_idx++;
635 next_idx &= MAX_TRACK_MASK;
637 if (!tracks[next_idx].taginfo_ready)
638 return NULL;
640 return &tracks[next_idx].id3;
643 bool audio_has_changed_track(void)
645 if (track_changed)
647 track_changed = false;
648 return true;
651 return false;
654 void audio_play(long offset)
656 logf("audio_play");
658 #ifdef PLAYBACK_VOICE
659 /* Truncate any existing voice output so we don't have spelling
660 * etc. over the first part of the played track */
661 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
662 queue_post(&voice_queue, Q_VOICE_STOP, 1);
663 #endif
665 /* Start playback */
666 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
667 /* Don't return until playback has actually started */
668 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
671 void audio_stop(void)
673 /* Stop playback */
674 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
675 /* Don't return until playback has actually stopped */
676 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
679 void audio_pause(void)
681 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
682 /* Don't return until playback has actually paused */
683 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
686 void audio_resume(void)
688 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
689 /* Don't return until playback has actually resumed */
690 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
693 void audio_next(void)
695 if (playlist_check(ci.new_track + wps_offset + 1))
697 if (global_settings.beep)
698 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
700 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
701 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
702 /* Update wps while our message travels inside deep playback queues. */
703 wps_offset++;
704 track_changed = true;
706 else
708 /* No more tracks. */
709 if (global_settings.beep)
710 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
714 void audio_prev(void)
716 if (playlist_check(ci.new_track + wps_offset - 1))
718 if (global_settings.beep)
719 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
721 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
722 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
723 /* Update wps while our message travels inside deep playback queues. */
724 wps_offset--;
725 track_changed = true;
727 else
729 /* No more tracks. */
730 if (global_settings.beep)
731 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
735 void audio_next_dir(void)
737 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
738 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
741 void audio_prev_dir(void)
743 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
744 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
747 void audio_pre_ff_rewind(void)
749 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
750 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
753 void audio_ff_rewind(long newpos)
755 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
756 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
759 void audio_flush_and_reload_tracks(void)
761 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
762 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
765 void audio_error_clear(void)
767 #ifdef AUDIO_HAVE_RECORDING
768 pcm_rec_error_clear();
769 #endif
772 int audio_status(void)
774 int ret = 0;
776 if (playing)
777 ret |= AUDIO_STATUS_PLAY;
779 if (paused)
780 ret |= AUDIO_STATUS_PAUSE;
782 #ifdef HAVE_RECORDING
783 /* Do this here for constitency with mpeg.c version */
784 ret |= pcm_rec_status();
785 #endif
787 return ret;
790 int audio_get_file_pos(void)
792 return 0;
795 #ifndef HAVE_FLASH_STORAGE
796 void audio_set_buffer_margin(int setting)
798 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
799 buffer_margin = lookup[setting];
800 logf("buffer margin: %ld", buffer_margin);
801 set_filebuf_watermark(buffer_margin);
803 #endif
805 /* Take nescessary steps to enable or disable the crossfade setting */
806 void audio_set_crossfade(int enable)
808 size_t offset;
809 bool was_playing;
810 size_t size;
812 /* Tell it the next setting to use */
813 pcmbuf_crossfade_enable(enable);
815 /* Return if size hasn't changed or this is too early to determine
816 which in the second case there's no way we could be playing
817 anything at all */
818 if (pcmbuf_is_same_size())
820 /* This function is a copout and just syncs some variables -
821 to be removed at a later date */
822 pcmbuf_crossfade_enable_finished();
823 return;
826 offset = 0;
827 was_playing = playing;
829 /* Playback has to be stopped before changing the buffer size */
830 if (was_playing)
832 /* Store the track resume position */
833 offset = CUR_TI->id3.offset;
834 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
837 /* Blast it - audio buffer will have to be setup again next time
838 something plays */
839 audio_get_buffer(true, &size);
841 /* Restart playback if audio was running previously */
842 if (was_playing)
843 audio_play(offset);
846 /* --- Routines called from multiple threads --- */
847 static void set_current_codec(int codec_idx)
849 current_codec = codec_idx;
850 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
853 #ifdef PLAYBACK_VOICE
854 static void swap_codec(void)
856 int my_codec;
858 /* Swap nothing if no swap buffers exist */
859 if (dram_buf == NULL)
861 logf("swap: no swap buffers");
862 return;
865 my_codec = current_codec;
867 logf("swapping out codec: %d", my_codec);
869 /* Invert this when a codec thread enters and leaves */
870 swap_codec_parity = !swap_codec_parity;
872 /* If this is true, an odd number of calls has occurred and there's
873 no codec thread waiting to swap us out when it locks and runs. This
874 occurs when playback is stopped or when just starting playback and
875 the audio thread is loading a codec; parities should always be even
876 on entry when a thread calls this during playback */
877 if (swap_codec_parity)
879 /* Save our current IRAM and DRAM */
880 #ifdef IRAM_STEAL
881 if (voice_iram_stolen)
883 logf("swap: iram restore");
884 voice_iram_stolen = false;
885 /* Don't swap trashed data into buffer as the voice IRAM will
886 already be swapped out - should _always_ be the case if
887 voice_iram_stolen is true since the voice has been swapped
888 in beforehand */
889 if (my_codec == CODEC_IDX_VOICE)
891 logf("voice iram already swapped");
892 goto skip_iram_swap;
895 #endif
897 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
899 #ifdef IRAM_STEAL
900 skip_iram_swap:
901 #endif
903 memswap128(dram_buf, codecbuf, CODEC_SIZE);
904 /* No cache invalidation needed; it will be done in codec_load_ram
905 or we won't be here otherwise */
908 /* Release my semaphore */
909 mutex_unlock(&mutex_codecthread);
910 logf("unlocked: %d", my_codec);
912 /* Loop until the other codec has locked and run */
913 do {
914 /* Release my semaphore and force a task switch. */
915 yield();
916 } while (my_codec == current_codec);
918 /* Wait for other codec to unlock */
919 mutex_lock(&mutex_codecthread);
921 /* Take control */
922 logf("waiting for lock: %d", my_codec);
923 set_current_codec(my_codec);
925 /* Reload our IRAM and DRAM */
926 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
927 memswap128(dram_buf, codecbuf, CODEC_SIZE);
928 invalidate_icache();
930 /* Flip parity again */
931 swap_codec_parity = !swap_codec_parity;
933 logf("resuming codec: %d", my_codec);
936 /* This function is meant to be used by the buffer stealing functions to
937 ensure the codec is no longer active and so voice will be swapped-in
938 before it is called */
939 static void voice_stop(void)
941 #ifdef PLAYBACK_VOICE
942 /* Must have a voice codec loaded or we'll hang forever here */
943 if (!voice_codec_loaded)
944 return;
946 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
947 queue_post(&voice_queue, Q_VOICE_STOP, 0);
949 /* Loop until voice empties it's queue, stops and picks up on the new
950 track; the voice thread must be stopped and waiting for messages
951 outside the codec */
952 while (voice_is_playing || !queue_empty(&voice_queue) ||
953 ci_voice.new_track)
954 yield();
956 if (!playing)
957 pcmbuf_play_stop();
958 #endif
959 } /* voice_stop */
961 /* Is voice still speaking */
962 /* Unfortunately only reliable when music is not also playing. */
963 static bool is_voice_speaking(void)
965 return is_voice_queued()
966 || voice_is_playing
967 || (!playing && pcm_is_playing());
970 /* Wait for voice to finish speaking. */
971 /* Also only reliable when music is not also playing. */
972 void voice_wait(void)
974 while (is_voice_speaking())
975 sleep(HZ/10);
978 #endif /* PLAYBACK_VOICE */
980 static void set_filebuf_watermark(int seconds)
982 size_t bytes;
984 if (!filebuf)
985 return; /* Audio buffers not yet set up */
987 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
988 bytes = MIN(bytes, filebuflen / 2);
989 conf_watermark = bytes;
992 const char * get_codec_filename(int cod_spec)
994 const char *fname;
996 #ifdef HAVE_RECORDING
997 /* Can choose decoder or encoder if one available */
998 int type = cod_spec & CODEC_TYPE_MASK;
999 int afmt = cod_spec & CODEC_AFMT_MASK;
1001 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1002 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1004 fname = (type == CODEC_TYPE_ENCODER) ?
1005 audio_formats[afmt].codec_enc_root_fn :
1006 audio_formats[afmt].codec_root_fn;
1008 logf("%s: %d - %s",
1009 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1010 afmt, fname ? fname : "<unknown>");
1011 #else /* !HAVE_RECORDING */
1012 /* Always decoder */
1013 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1014 cod_spec = AFMT_UNKNOWN;
1015 fname = audio_formats[cod_spec].codec_root_fn;
1016 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1017 #endif /* HAVE_RECORDING */
1019 return fname;
1020 } /* get_codec_filename */
1023 /* --- Voice thread --- */
1025 #ifdef PLAYBACK_VOICE
1027 static bool voice_pcmbuf_insert_callback(
1028 const void *ch1, const void *ch2, int count)
1030 const char *src[2] = { ch1, ch2 };
1032 while (count > 0)
1034 int out_count = dsp_output_count(count);
1035 int inp_count;
1036 char *dest;
1038 while ((dest = pcmbuf_request_voice_buffer(
1039 &out_count, playing)) == NULL)
1041 if (playing && audio_codec_loaded)
1042 swap_codec();
1043 else
1044 yield();
1047 /* Get the real input_size for output_size bytes, guarding
1048 * against resampling buffer overflows. */
1049 inp_count = dsp_input_count(out_count);
1051 if (inp_count <= 0)
1052 return true;
1054 /* Input size has grown, no error, just don't write more than length */
1055 if (inp_count > count)
1056 inp_count = count;
1058 out_count = dsp_process(dest, src, inp_count);
1060 if (out_count <= 0)
1061 return true;
1063 if (playing)
1065 pcmbuf_mix_voice(out_count);
1066 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1067 audio_codec_loaded)
1068 swap_codec();
1070 else
1071 pcmbuf_write_complete(out_count);
1073 count -= inp_count;
1076 return true;
1077 } /* voice_pcmbuf_insert_callback */
1079 static void* voice_get_memory_callback(size_t *size)
1081 /* Voice should have no use for this. If it did, we'd have to
1082 swap the malloc buffer as well. */
1083 *size = 0;
1084 return NULL;
1087 static void voice_set_elapsed_callback(unsigned int value)
1089 (void)value;
1092 static void voice_set_offset_callback(size_t value)
1094 (void)value;
1097 static void voice_configure_callback(int setting, intptr_t value)
1099 if (!dsp_configure(setting, value))
1101 logf("Illegal key:%d", setting);
1105 static size_t voice_filebuf_callback(void *ptr, size_t size)
1107 (void)ptr;
1108 (void)size;
1110 return 0;
1113 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1114 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1116 if (aborting && !playing && pcm_is_playing())
1118 /* Aborting: Slight hack - flush PCM buffer if
1119 only being used for voice */
1120 pcmbuf_play_stop();
1123 if (voice_is_playing)
1125 /* Clear the current buffer */
1126 voice_is_playing = false;
1127 voice_getmore = NULL;
1128 voice_remaining = 0;
1129 voicebuf = NULL;
1131 /* Cancel any automatic boost if no more clips requested. */
1132 if (!playing || !voice_thread_start)
1133 sleep(0);
1135 /* Force the codec to think it's changing tracks */
1136 ci_voice.new_track = 1;
1138 *realsize = 0;
1139 return true; /* Yes, change tracks */
1142 return false;
1145 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1147 struct event ev;
1149 if (ci_voice.new_track)
1151 *realsize = 0;
1152 return NULL;
1155 while (1)
1157 if (voice_is_playing || playing)
1159 queue_wait_w_tmo(&voice_queue, &ev, 0);
1160 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1161 ev.id = Q_AUDIO_PLAY;
1163 else
1165 queue_wait(&voice_queue, &ev);
1168 switch (ev.id) {
1169 case Q_AUDIO_PLAY:
1170 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1171 if (playing)
1173 if (audio_codec_loaded)
1174 swap_codec();
1175 yield();
1177 break;
1179 #ifdef AUDIO_HAVE_RECORDING
1180 case Q_ENCODER_RECORD:
1181 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1182 swap_codec();
1183 break;
1184 #endif
1186 case Q_VOICE_STOP:
1187 LOGFQUEUE("voice < Q_VOICE_STOP");
1188 if (voice_on_voice_stop(ev.data, realsize))
1189 return NULL;
1190 break;
1192 case SYS_USB_CONNECTED:
1194 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1195 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1196 /* Voice is obviously current so let us swap ourselves away if
1197 playing so audio may stop itself - audio_codec_loaded can
1198 only be true in this case if we're here even if the codec
1199 is only about to load */
1200 if (audio_codec_loaded)
1201 swap_codec();
1202 /* Playback should be finished by now - ack and wait */
1203 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1204 usb_wait_for_disconnect(&voice_queue);
1205 if (change_tracks)
1206 return NULL;
1207 break;
1210 case Q_VOICE_PLAY:
1211 LOGFQUEUE("voice < Q_VOICE_PLAY");
1212 if (!voice_is_playing)
1214 /* Set up new voice data */
1215 struct voice_info *voice_data;
1216 #ifdef IRAM_STEAL
1217 if (voice_iram_stolen)
1219 /* Voice is the first to run again and is currently
1220 loaded */
1221 logf("voice: iram restore");
1222 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1223 voice_iram_stolen = false;
1225 #endif
1226 /* Must reset the buffer before any playback begins if
1227 needed */
1228 if (buffer_state == BUFFER_STATE_TRASHED)
1229 audio_reset_buffer();
1231 voice_is_playing = true;
1232 trigger_cpu_boost();
1233 voice_data = (struct voice_info *)ev.data;
1234 voice_remaining = voice_data->size;
1235 voicebuf = voice_data->buf;
1236 voice_getmore = voice_data->callback;
1238 goto voice_play_clip; /* To exit both switch and while */
1240 case SYS_TIMEOUT:
1241 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1242 goto voice_play_clip;
1244 default:
1245 LOGFQUEUE("voice < default");
1249 voice_play_clip:
1251 if (voice_remaining == 0 || voicebuf == NULL)
1253 if (voice_getmore)
1254 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1256 /* If this clip is done */
1257 if (voice_remaining == 0)
1259 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1260 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1261 /* Force pcm playback. */
1262 if (!pcm_is_playing())
1263 pcmbuf_play_start();
1267 *realsize = MIN(voice_remaining, reqsize);
1269 if (*realsize == 0)
1270 return NULL;
1272 return voicebuf;
1273 } /* voice_request_buffer_callback */
1275 static void voice_advance_buffer_callback(size_t amount)
1277 amount = MIN(amount, voice_remaining);
1278 voicebuf += amount;
1279 voice_remaining -= amount;
1282 static void voice_advance_buffer_loc_callback(void *ptr)
1284 size_t amount = (size_t)ptr - (size_t)voicebuf;
1286 voice_advance_buffer_callback(amount);
1289 static off_t voice_mp3_get_filepos_callback(int newtime)
1291 (void)newtime;
1293 return 0;
1296 static void voice_do_nothing(void)
1298 return;
1301 static bool voice_seek_buffer_callback(size_t newpos)
1303 (void)newpos;
1305 return false;
1308 static bool voice_request_next_track_callback(void)
1310 ci_voice.new_track = 0;
1311 return true;
1314 static void voice_thread(void)
1316 logf("Loading voice codec");
1317 voice_codec_loaded = true;
1318 mutex_lock(&mutex_codecthread);
1319 set_current_codec(CODEC_IDX_VOICE);
1320 dsp_configure(DSP_RESET, 0);
1321 voice_remaining = 0;
1322 voice_getmore = NULL;
1324 /* FIXME: If we being starting the voice thread without reboot, the
1325 voice_queue could be full of old stuff and we must flush it. */
1326 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1328 logf("Voice codec finished");
1329 voice_codec_loaded = false;
1330 mutex_unlock(&mutex_codecthread);
1331 voice_thread_p = NULL;
1332 remove_thread(NULL);
1333 } /* voice_thread */
1335 #endif /* PLAYBACK_VOICE */
1337 /* --- Codec thread --- */
1338 static bool codec_pcmbuf_insert_callback(
1339 const void *ch1, const void *ch2, int count)
1341 const char *src[2] = { ch1, ch2 };
1343 while (count > 0)
1345 int out_count = dsp_output_count(count);
1346 int inp_count;
1347 char *dest;
1349 /* Prevent audio from a previous track from playing */
1350 if (ci.new_track || ci.stop_codec)
1351 return true;
1353 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1355 sleep(1);
1356 if (ci.seek_time || ci.new_track || ci.stop_codec)
1357 return true;
1360 /* Get the real input_size for output_size bytes, guarding
1361 * against resampling buffer overflows. */
1362 inp_count = dsp_input_count(out_count);
1364 if (inp_count <= 0)
1365 return true;
1367 /* Input size has grown, no error, just don't write more than length */
1368 if (inp_count > count)
1369 inp_count = count;
1371 out_count = dsp_process(dest, src, inp_count);
1373 if (out_count <= 0)
1374 return true;
1376 pcmbuf_write_complete(out_count);
1378 #ifdef PLAYBACK_VOICE
1379 if ((voice_is_playing || voice_thread_start)
1380 && pcm_is_playing() && voice_codec_loaded &&
1381 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1383 voice_thread_start = false;
1384 swap_codec();
1386 #endif
1388 count -= inp_count;
1391 return true;
1392 } /* codec_pcmbuf_insert_callback */
1394 static void* codec_get_memory_callback(size_t *size)
1396 *size = MALLOC_BUFSIZE;
1397 return malloc_buf;
1400 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1401 static void codec_pcmbuf_position_callback(size_t size)
1403 /* This is called from an ISR, so be quick */
1404 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1405 prev_ti->id3.elapsed;
1407 if (time >= prev_ti->id3.length)
1409 pcmbuf_set_position_callback(NULL);
1410 prev_ti->id3.elapsed = prev_ti->id3.length;
1412 else
1413 prev_ti->id3.elapsed = time;
1416 static void codec_set_elapsed_callback(unsigned int value)
1418 unsigned int latency;
1419 if (ci.seek_time)
1420 return;
1422 #ifdef AB_REPEAT_ENABLE
1423 ab_position_report(value);
1424 #endif
1426 latency = pcmbuf_get_latency();
1427 if (value < latency)
1428 CUR_TI->id3.elapsed = 0;
1429 else if (value - latency > CUR_TI->id3.elapsed ||
1430 value - latency < CUR_TI->id3.elapsed - 2)
1432 CUR_TI->id3.elapsed = value - latency;
1436 static void codec_set_offset_callback(size_t value)
1438 unsigned int latency;
1440 if (ci.seek_time)
1441 return;
1443 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1444 if (value < latency)
1445 CUR_TI->id3.offset = 0;
1446 else
1447 CUR_TI->id3.offset = value - latency;
1450 static void codec_advance_buffer_counters(size_t amount)
1452 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1453 ci.curpos += amount;
1454 CUR_TI->available -= amount;
1456 /* Start buffer filling as necessary. */
1457 if (!pcmbuf_is_lowdata() && !filling)
1459 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1461 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1462 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1467 /* copy up-to size bytes into ptr and return the actual size copied */
1468 static size_t codec_filebuf_callback(void *ptr, size_t size)
1470 char *buf = (char *)ptr;
1471 size_t copy_n;
1472 size_t part_n;
1474 if (ci.stop_codec || !playing)
1475 return 0;
1477 /* The ammount to copy is the lesser of the requested amount and the
1478 * amount left of the current track (both on disk and already loaded) */
1479 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1481 /* Nothing requested OR nothing left */
1482 if (copy_n == 0)
1483 return 0;
1485 /* Let the disk buffer catch fill until enough data is available */
1486 while (copy_n > CUR_TI->available)
1488 if (!filling)
1490 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1491 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1494 sleep(1);
1495 if (ci.stop_codec || ci.new_track)
1496 return 0;
1499 /* Copy as much as possible without wrapping */
1500 part_n = MIN(copy_n, filebuflen - buf_ridx);
1501 memcpy(buf, &filebuf[buf_ridx], part_n);
1502 /* Copy the rest in the case of a wrap */
1503 if (part_n < copy_n) {
1504 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1507 /* Update read and other position pointers */
1508 codec_advance_buffer_counters(copy_n);
1510 /* Return the actual amount of data copied to the buffer */
1511 return copy_n;
1512 } /* codec_filebuf_callback */
1514 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1516 size_t short_n, copy_n, buf_rem;
1518 if (!playing)
1520 *realsize = 0;
1521 return NULL;
1524 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1525 if (copy_n == 0)
1527 *realsize = 0;
1528 return NULL;
1531 while (copy_n > CUR_TI->available)
1533 if (!filling)
1535 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1536 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1539 sleep(1);
1540 if (ci.stop_codec || ci.new_track)
1542 *realsize = 0;
1543 return NULL;
1547 /* How much is left at the end of the file buffer before wrap? */
1548 buf_rem = filebuflen - buf_ridx;
1550 /* If we can't satisfy the request without wrapping */
1551 if (buf_rem < copy_n)
1553 /* How short are we? */
1554 short_n = copy_n - buf_rem;
1556 /* If we can fudge it with the guardbuf */
1557 if (short_n < GUARD_BUFSIZE)
1558 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1559 else
1560 copy_n = buf_rem;
1563 *realsize = copy_n;
1565 return (char *)&filebuf[buf_ridx];
1566 } /* codec_request_buffer_callback */
1568 static int get_codec_base_type(int type)
1570 switch (type) {
1571 case AFMT_MPA_L1:
1572 case AFMT_MPA_L2:
1573 case AFMT_MPA_L3:
1574 return AFMT_MPA_L3;
1577 return type;
1580 static void codec_advance_buffer_callback(size_t amount)
1582 if (amount > CUR_TI->available + CUR_TI->filerem)
1583 amount = CUR_TI->available + CUR_TI->filerem;
1585 while (amount > CUR_TI->available && filling)
1586 sleep(1);
1588 if (amount > CUR_TI->available)
1590 intptr_t result = Q_CODEC_REQUEST_FAILED;
1592 if (!ci.stop_codec)
1594 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1595 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1596 ci.curpos + amount);
1599 switch (result)
1601 case Q_CODEC_REQUEST_FAILED:
1602 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1603 ci.stop_codec = true;
1604 return;
1606 case Q_CODEC_REQUEST_COMPLETE:
1607 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1608 return;
1610 default:
1611 LOGFQUEUE("codec |< default");
1612 ci.stop_codec = true;
1613 return;
1617 codec_advance_buffer_counters(amount);
1619 codec_set_offset_callback(ci.curpos);
1622 static void codec_advance_buffer_loc_callback(void *ptr)
1624 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1626 codec_advance_buffer_callback(amount);
1629 /* Copied from mpeg.c. Should be moved somewhere else. */
1630 static int codec_get_file_pos(void)
1632 int pos = -1;
1633 struct mp3entry *id3 = audio_current_track();
1635 if (id3->vbr)
1637 if (id3->has_toc)
1639 /* Use the TOC to find the new position */
1640 unsigned int percent, remainder;
1641 int curtoc, nexttoc, plen;
1643 percent = (id3->elapsed*100)/id3->length;
1644 if (percent > 99)
1645 percent = 99;
1647 curtoc = id3->toc[percent];
1649 if (percent < 99)
1650 nexttoc = id3->toc[percent+1];
1651 else
1652 nexttoc = 256;
1654 pos = (id3->filesize/256)*curtoc;
1656 /* Use the remainder to get a more accurate position */
1657 remainder = (id3->elapsed*100)%id3->length;
1658 remainder = (remainder*100)/id3->length;
1659 plen = (nexttoc - curtoc)*(id3->filesize/256);
1660 pos += (plen/100)*remainder;
1662 else
1664 /* No TOC exists, estimate the new position */
1665 pos = (id3->filesize / (id3->length / 1000)) *
1666 (id3->elapsed / 1000);
1669 else if (id3->bitrate)
1670 pos = id3->elapsed * (id3->bitrate / 8);
1671 else
1672 return -1;
1674 pos += id3->first_frame_offset;
1676 /* Don't seek right to the end of the file so that we can
1677 transition properly to the next song */
1678 if (pos >= (int)(id3->filesize - id3->id3v1len))
1679 pos = id3->filesize - id3->id3v1len - 1;
1681 return pos;
1684 static off_t codec_mp3_get_filepos_callback(int newtime)
1686 off_t newpos;
1688 CUR_TI->id3.elapsed = newtime;
1689 newpos = codec_get_file_pos();
1691 return newpos;
1694 static void codec_seek_complete_callback(void)
1696 logf("seek_complete");
1697 if (pcm_is_paused())
1699 /* If this is not a seamless seek, clear the buffer */
1700 pcmbuf_play_stop();
1701 dsp_configure(DSP_FLUSH, 0);
1703 /* If playback was not 'deliberately' paused, unpause now */
1704 if (!paused)
1705 pcmbuf_pause(false);
1707 ci.seek_time = 0;
1710 static bool codec_seek_buffer_callback(size_t newpos)
1712 int difference;
1714 logf("codec_seek_buffer_callback");
1716 if (newpos >= CUR_TI->filesize)
1717 newpos = CUR_TI->filesize - 1;
1719 difference = newpos - ci.curpos;
1720 if (difference >= 0)
1722 /* Seeking forward */
1723 logf("seek: +%d", difference);
1724 codec_advance_buffer_callback(difference);
1725 return true;
1728 /* Seeking backward */
1729 difference = -difference;
1730 if (ci.curpos - difference < 0)
1731 difference = ci.curpos;
1733 /* We need to reload the song. */
1734 if (newpos < CUR_TI->start_pos)
1736 intptr_t result = Q_CODEC_REQUEST_FAILED;
1738 if (!ci.stop_codec)
1740 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1741 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1742 newpos);
1745 switch (result)
1747 case Q_CODEC_REQUEST_COMPLETE:
1748 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1749 return true;
1751 case Q_CODEC_REQUEST_FAILED:
1752 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1753 ci.stop_codec = true;
1754 return false;
1756 default:
1757 LOGFQUEUE("codec |< default");
1758 return false;
1762 /* Seeking inside buffer space. */
1763 logf("seek: -%d", difference);
1764 CUR_TI->available += difference;
1765 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1766 ci.curpos -= difference;
1768 return true;
1771 static void codec_configure_callback(int setting, intptr_t value)
1773 switch (setting) {
1774 case CODEC_SET_FILEBUF_WATERMARK:
1775 conf_watermark = value;
1776 set_filebuf_watermark(buffer_margin);
1777 break;
1779 case CODEC_SET_FILEBUF_CHUNKSIZE:
1780 conf_filechunk = value;
1781 break;
1783 case CODEC_SET_FILEBUF_PRESEEK:
1784 conf_preseek = value;
1785 break;
1787 default:
1788 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1792 static void codec_track_changed(void)
1794 automatic_skip = false;
1795 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1796 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1799 static void codec_pcmbuf_track_changed_callback(void)
1801 pcmbuf_set_position_callback(NULL);
1802 codec_track_changed();
1805 static void codec_discard_codec_callback(void)
1807 if (CUR_TI->has_codec)
1809 CUR_TI->has_codec = false;
1810 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1813 #if 0
1814 /* Check if a buffer desync has happened, log it and stop playback. */
1815 if (buf_ridx != CUR_TI->buf_idx)
1817 int offset = CUR_TI->buf_idx - buf_ridx;
1818 size_t new_used = FILEBUFUSED - offset;
1820 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1821 logf("Used off:%d",FILEBUFUSED - new_used);
1823 /* This is a fatal internal error and it's not safe to
1824 * continue playback. */
1825 ci.stop_codec = true;
1826 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1828 #endif
1831 static inline void codec_gapless_track_change(void) {
1832 /* callback keeps the progress bar moving while the pcmbuf empties */
1833 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1834 /* set the pcmbuf callback for when the track really changes */
1835 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1838 static inline void codec_crossfade_track_change(void) {
1839 /* Initiate automatic crossfade mode */
1840 pcmbuf_crossfade_init(false);
1841 /* Notify the wps that the track change starts now */
1842 codec_track_changed();
1845 static void codec_track_skip_done(bool was_manual)
1847 int crossfade_mode = global_settings.crossfade;
1849 /* Manual track change (always crossfade or flush audio). */
1850 if (was_manual)
1852 pcmbuf_crossfade_init(true);
1853 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1854 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1856 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1857 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1858 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1860 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1862 if (global_settings.playlist_shuffle)
1863 /* shuffle mode is on, so crossfade: */
1864 codec_crossfade_track_change();
1865 else
1866 /* shuffle mode is off, so do a gapless track change */
1867 codec_gapless_track_change();
1869 else
1870 /* normal crossfade: */
1871 codec_crossfade_track_change();
1873 else
1874 /* normal gapless playback. */
1875 codec_gapless_track_change();
1878 static bool codec_load_next_track(void)
1880 intptr_t result = Q_CODEC_REQUEST_FAILED;
1882 prev_track_elapsed = CUR_TI->id3.elapsed;
1884 if (ci.seek_time)
1885 codec_seek_complete_callback();
1887 #ifdef AB_REPEAT_ENABLE
1888 ab_end_of_track_report();
1889 #endif
1891 logf("Request new track");
1893 if (ci.new_track == 0)
1895 ci.new_track++;
1896 automatic_skip = true;
1899 if (!ci.stop_codec)
1901 trigger_cpu_boost();
1902 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1903 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1906 switch (result)
1908 case Q_CODEC_REQUEST_COMPLETE:
1909 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1910 codec_track_skip_done(!automatic_skip);
1911 return true;
1913 case Q_CODEC_REQUEST_FAILED:
1914 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1915 ci.new_track = 0;
1916 ci.stop_codec = true;
1917 return false;
1919 default:
1920 LOGFQUEUE("codec |< default");
1921 ci.stop_codec = true;
1922 return false;
1926 static bool codec_request_next_track_callback(void)
1928 int prev_codectype;
1930 if (ci.stop_codec || !playing)
1931 return false;
1933 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1935 if (!codec_load_next_track())
1936 return false;
1938 /* Check if the next codec is the same file. */
1939 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1941 logf("New track loaded");
1942 codec_discard_codec_callback();
1943 return true;
1945 else
1947 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1948 return false;
1952 static void codec_thread(void)
1954 struct event ev;
1955 int status;
1956 size_t wrap;
1958 while (1) {
1959 status = 0;
1960 queue_wait(&codec_queue, &ev);
1962 switch (ev.id) {
1963 case Q_CODEC_LOAD_DISK:
1964 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1965 audio_codec_loaded = true;
1966 #ifdef PLAYBACK_VOICE
1967 /* Don't sent messages to voice codec if it's already swapped
1968 out or it will never get this */
1969 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1971 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1972 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1974 mutex_lock(&mutex_codecthread);
1975 #endif
1976 set_current_codec(CODEC_IDX_AUDIO);
1977 ci.stop_codec = false;
1978 status = codec_load_file((const char *)ev.data, &ci);
1979 #ifdef PLAYBACK_VOICE
1980 mutex_unlock(&mutex_codecthread);
1981 #endif
1982 break;
1984 case Q_CODEC_LOAD:
1985 LOGFQUEUE("codec < Q_CODEC_LOAD");
1986 if (!CUR_TI->has_codec) {
1987 logf("Codec slot is empty!");
1988 /* Wait for the pcm buffer to go empty */
1989 while (pcm_is_playing())
1990 yield();
1991 /* This must be set to prevent an infinite loop */
1992 ci.stop_codec = true;
1993 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1994 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1995 break;
1998 audio_codec_loaded = true;
1999 #ifdef PLAYBACK_VOICE
2000 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2002 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2003 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2005 mutex_lock(&mutex_codecthread);
2006 #endif
2007 set_current_codec(CODEC_IDX_AUDIO);
2008 ci.stop_codec = false;
2009 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
2010 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
2011 &filebuf[0], wrap, &ci);
2012 #ifdef PLAYBACK_VOICE
2013 mutex_unlock(&mutex_codecthread);
2014 #endif
2015 break;
2017 #ifdef AUDIO_HAVE_RECORDING
2018 case Q_ENCODER_LOAD_DISK:
2019 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2020 audio_codec_loaded = false; /* Not audio codec! */
2021 #ifdef PLAYBACK_VOICE
2022 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2024 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2025 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2027 mutex_lock(&mutex_codecthread);
2028 #endif
2029 logf("loading encoder");
2030 set_current_codec(CODEC_IDX_AUDIO);
2031 ci.stop_encoder = false;
2032 status = codec_load_file((const char *)ev.data, &ci);
2033 #ifdef PLAYBACK_VOICE
2034 mutex_unlock(&mutex_codecthread);
2035 #endif
2036 logf("encoder stopped");
2037 break;
2038 #endif /* AUDIO_HAVE_RECORDING */
2040 #ifndef SIMULATOR
2041 case SYS_USB_CONNECTED:
2042 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2043 queue_clear(&codec_queue);
2044 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2045 usb_wait_for_disconnect(&codec_queue);
2046 break;
2047 #endif
2049 default:
2050 LOGFQUEUE("codec < default");
2053 if (audio_codec_loaded)
2055 if (ci.stop_codec)
2057 status = CODEC_OK;
2058 if (!playing)
2059 pcmbuf_play_stop();
2062 audio_codec_loaded = false;
2065 switch (ev.id) {
2066 case Q_CODEC_LOAD_DISK:
2067 case Q_CODEC_LOAD:
2068 LOGFQUEUE("codec < Q_CODEC_LOAD");
2069 if (playing)
2071 if (ci.new_track || status != CODEC_OK)
2073 if (!ci.new_track)
2075 logf("Codec failure");
2076 gui_syncsplash(HZ*2, "Codec failure");
2079 if (!codec_load_next_track())
2081 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2082 /* End of playlist */
2083 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2084 break;
2087 else
2089 logf("Codec finished");
2090 if (ci.stop_codec)
2092 /* Wait for the audio to stop playing before
2093 * triggering the WPS exit */
2094 while(pcm_is_playing())
2096 CUR_TI->id3.elapsed =
2097 CUR_TI->id3.length - pcmbuf_get_latency();
2098 sleep(1);
2100 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2101 /* End of playlist */
2102 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2103 break;
2107 if (CUR_TI->has_codec)
2109 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2110 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2112 else
2114 const char *codec_fn =
2115 get_codec_filename(CUR_TI->id3.codectype);
2116 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2117 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2118 (intptr_t)codec_fn);
2121 break;
2123 #ifdef AUDIO_HAVE_RECORDING
2124 case Q_ENCODER_LOAD_DISK:
2125 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2127 if (status == CODEC_OK)
2128 break;
2130 logf("Encoder failure");
2131 gui_syncsplash(HZ*2, "Encoder failure");
2133 if (ci.enc_codec_loaded < 0)
2134 break;
2136 logf("Encoder failed to load");
2137 ci.enc_codec_loaded = -1;
2138 break;
2139 #endif /* AUDIO_HAVE_RECORDING */
2141 default:
2142 LOGFQUEUE("codec < default");
2144 } /* end switch */
2149 /* --- Audio thread --- */
2151 static bool audio_filebuf_is_lowdata(void)
2153 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
2156 static bool audio_have_tracks(void)
2158 return track_ridx != track_widx || CUR_TI->filesize;
2161 static bool audio_have_free_tracks(void)
2163 if (track_widx < track_ridx)
2164 return track_widx + 1 < track_ridx;
2165 else if (track_ridx == 0)
2166 return track_widx < MAX_TRACK - 1;
2168 return true;
2171 int audio_track_count(void)
2173 if (audio_have_tracks())
2175 int relative_track_widx = track_widx;
2177 if (track_ridx > track_widx)
2178 relative_track_widx += MAX_TRACK;
2180 return relative_track_widx - track_ridx + 1;
2183 return 0;
2186 long audio_filebufused(void)
2188 return (long) FILEBUFUSED;
2191 /* Count the data BETWEEN the selected tracks */
2192 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2194 size_t amount = 0;
2195 bool need_wrap = to_track < from_track;
2197 while (1)
2199 if (++from_track >= MAX_TRACK)
2201 from_track -= MAX_TRACK;
2202 need_wrap = false;
2205 if (from_track >= to_track && !need_wrap)
2206 break;
2208 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2210 return amount;
2213 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2215 size_t amount;
2217 /* Start with the remainder of the previously playing track */
2218 amount = tracks[old_track_ridx].filesize - ci.curpos;
2219 /* Then collect all data from tracks in between them */
2220 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2221 logf("bwf:%ldB", (long) amount);
2223 if (amount > FILEBUFUSED)
2224 return false;
2226 /* Wind the buffer to the beginning of the target track or its codec */
2227 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2229 return true;
2232 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2234 /* Available buffer data */
2235 size_t buf_back;
2236 /* Start with the previously playing track's data and our data */
2237 size_t amount;
2239 amount = ci.curpos;
2240 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2242 /* If we're not just resetting the current track */
2243 if (new_track_ridx != old_track_ridx)
2245 /* Need to wind to before the old track's codec and our filesize */
2246 amount += tracks[old_track_ridx].codecsize;
2247 amount += tracks[new_track_ridx].filesize;
2249 /* Rewind the old track to its beginning */
2250 tracks[old_track_ridx].available =
2251 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2254 /* If the codec was ever buffered */
2255 if (tracks[new_track_ridx].codecsize)
2257 /* Add the codec to the needed size */
2258 amount += tracks[new_track_ridx].codecsize;
2259 tracks[new_track_ridx].has_codec = true;
2262 /* Then collect all data from tracks between new and old */
2263 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2265 /* Do we have space to make this skip? */
2266 if (amount > buf_back)
2267 return false;
2269 logf("bwb:%ldB",amount);
2271 /* Rewind the buffer to the beginning of the target track or its codec */
2272 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2274 /* Reset to the beginning of the new track */
2275 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2277 return true;
2280 static void audio_update_trackinfo(void)
2282 ci.filesize = CUR_TI->filesize;
2283 CUR_TI->id3.elapsed = 0;
2284 CUR_TI->id3.offset = 0;
2285 ci.id3 = &CUR_TI->id3;
2286 ci.curpos = 0;
2287 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2290 /* Yield to codecs for as long as possible if they are in need of data
2291 * return true if the caller should break to let the audio thread process
2292 * new events */
2293 static bool audio_yield_codecs(void)
2295 yield();
2297 if (!queue_empty(&audio_queue))
2298 return true;
2300 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2301 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2303 if (filling)
2304 yield();
2305 else
2306 sleep(2);
2308 if (!queue_empty(&audio_queue))
2309 return true;
2312 return false;
2315 static void audio_clear_track_entries(bool clear_unbuffered)
2317 int cur_idx = track_widx;
2318 int last_idx = -1;
2320 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2322 /* Loop over all tracks from write-to-read */
2323 while (1)
2325 cur_idx++;
2326 cur_idx &= MAX_TRACK_MASK;
2328 if (cur_idx == track_ridx)
2329 break;
2331 /* If the track is buffered, conditionally clear/notify,
2332 * otherwise clear the track if that option is selected */
2333 if (tracks[cur_idx].event_sent)
2335 if (last_idx >= 0)
2337 /* If there is an unbuffer callback, call it, otherwise,
2338 * just clear the track */
2339 if (track_unbuffer_callback)
2340 track_unbuffer_callback(&tracks[last_idx].id3, false);
2342 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2344 last_idx = cur_idx;
2346 else if (clear_unbuffered)
2347 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2350 /* We clear the previous instance of a buffered track throughout
2351 * the above loop to facilitate 'last' detection. Clear/notify
2352 * the last track here */
2353 if (last_idx >= 0)
2355 if (track_unbuffer_callback)
2356 track_unbuffer_callback(&tracks[last_idx].id3, true);
2357 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2361 /* FIXME: This code should be made more generic and move to metadata.c */
2362 static void audio_strip_tags(void)
2364 int i;
2365 static const unsigned char tag[] = "TAG";
2366 static const unsigned char apetag[] = "APETAGEX";
2367 size_t tag_idx;
2368 size_t cur_idx;
2369 size_t len, version;
2371 tag_idx = RINGBUF_SUB(buf_widx, 128);
2373 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2375 cur_idx = tag_idx;
2376 for(i = 0;i < 3;i++)
2378 if(filebuf[cur_idx] != tag[i])
2379 goto strip_ape_tag;
2381 cur_idx = RINGBUF_ADD(cur_idx, 1);
2384 /* Skip id3v1 tag */
2385 logf("Skipping ID3v1 tag");
2386 buf_widx = tag_idx;
2387 tracks[track_widx].available -= 128;
2388 tracks[track_widx].filesize -= 128;
2391 strip_ape_tag:
2392 /* Check for APE tag (look for the APE tag footer) */
2393 tag_idx = RINGBUF_SUB(buf_widx, 32);
2395 if (FILEBUFUSED > 32 && tag_idx > buf_ridx)
2397 cur_idx = tag_idx;
2398 for(i = 0;i < 8;i++)
2400 if(filebuf[cur_idx] != apetag[i])
2401 return;
2403 cur_idx = RINGBUF_ADD(cur_idx, 1);
2406 /* Read the version and length from the footer */
2407 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2408 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2409 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2410 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2411 if (version == 2000)
2412 len += 32; /* APEv2 has a 32 byte header */
2414 /* Skip APE tag */
2415 if (FILEBUFUSED > len)
2417 logf("Skipping APE tag (%ldB)", len);
2418 buf_widx = RINGBUF_SUB(buf_widx, len);
2419 tracks[track_widx].available -= len;
2420 tracks[track_widx].filesize -= len;
2425 /* Returns true if a whole file is read, false otherwise */
2426 static bool audio_read_file(size_t minimum)
2428 bool ret_val = false;
2430 /* If we're called and no file is open, this is an error */
2431 if (current_fd < 0)
2433 logf("Bad fd in arf");
2434 /* Give some hope of miraculous recovery by forcing a track reload */
2435 tracks[track_widx].filesize = 0;
2436 /* Stop this buffering run */
2437 return ret_val;
2440 trigger_cpu_boost();
2441 while (tracks[track_widx].filerem > 0)
2443 size_t copy_n;
2444 int overlap;
2445 int rc;
2447 /* copy_n is the largest chunk that is safe to read */
2448 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2450 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2451 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2452 break;
2454 /* rc is the actual amount read */
2455 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2457 if (rc < 0)
2459 logf("File ended %ldB early", tracks[track_widx].filerem);
2460 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2461 tracks[track_widx].filerem = 0;
2462 break;
2465 /* How much of the playing track did we overwrite */
2466 if (buf_widx == CUR_TI->buf_idx)
2468 /* Special handling; zero or full overlap? */
2469 if (track_widx == track_ridx && CUR_TI->available == 0)
2470 overlap = 0;
2471 else
2472 overlap = rc;
2474 else
2475 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2477 if ((unsigned)rc > tracks[track_widx].filerem)
2479 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2480 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2481 tracks[track_widx].filerem = rc;
2484 /* Advance buffer */
2485 buf_widx = RINGBUF_ADD(buf_widx, rc);
2486 tracks[track_widx].available += rc;
2487 tracks[track_widx].filerem -= rc;
2489 /* If we write into the playing track, adjust it's buffer info */
2490 if (overlap > 0)
2492 CUR_TI->buf_idx += overlap;
2493 CUR_TI->start_pos += overlap;
2496 /* For a rebuffer, fill at least this minimum */
2497 if (minimum > (unsigned)rc)
2498 minimum -= rc;
2499 /* Let the codec process up to the watermark */
2500 /* Break immediately if this is a quick buffer, or there is an event */
2501 else if (minimum || audio_yield_codecs())
2503 /* Exit quickly, but don't stop the overall buffering process */
2504 ret_val = true;
2505 break;
2509 if (tracks[track_widx].filerem == 0)
2511 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2512 close(current_fd);
2513 current_fd = -1;
2514 audio_strip_tags();
2516 track_widx++;
2517 track_widx &= MAX_TRACK_MASK;
2519 tracks[track_widx].filesize = 0;
2520 return true;
2522 else
2524 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2525 tracks[track_widx].filesize - tracks[track_widx].filerem);
2526 return ret_val;
2530 static bool audio_loadcodec(bool start_play)
2532 size_t size = 0;
2533 int fd;
2534 int rc;
2535 size_t copy_n;
2536 int prev_track;
2537 char codec_path[MAX_PATH]; /* Full path to codec */
2539 const char * codec_fn =
2540 get_codec_filename(tracks[track_widx].id3.codectype);
2541 if (codec_fn == NULL)
2542 return false;
2544 tracks[track_widx].has_codec = false;
2546 if (start_play)
2548 /* Load the codec directly from disk and save some memory. */
2549 track_ridx = track_widx;
2550 ci.filesize = CUR_TI->filesize;
2551 ci.id3 = &CUR_TI->id3;
2552 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2553 ci.curpos = 0;
2554 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2555 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2556 return true;
2558 else
2560 /* If we already have another track than this one buffered */
2561 if (track_widx != track_ridx)
2563 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2565 /* If the previous codec is the same as this one, there is no need
2566 * to put another copy of it on the file buffer */
2567 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2568 get_codec_base_type(tracks[prev_track].id3.codectype)
2569 && audio_codec_loaded)
2571 logf("Reusing prev. codec");
2572 return true;
2577 codec_get_full_path(codec_path, codec_fn);
2579 fd = open(codec_path, O_RDONLY);
2580 if (fd < 0)
2582 logf("Codec doesn't exist!");
2583 return false;
2586 tracks[track_widx].codecsize = filesize(fd);
2588 /* Never load a partial codec */
2589 if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0)
2591 logf("Not enough space");
2592 close(fd);
2593 return false;
2596 while (size < tracks[track_widx].codecsize)
2598 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2599 rc = read(fd, &filebuf[buf_widx], copy_n);
2600 if (rc < 0)
2602 close(fd);
2603 /* This is an error condition, likely the codec file is corrupt */
2604 logf("Partial codec loaded");
2605 /* Must undo the buffer write of the partial codec */
2606 buf_widx = RINGBUF_SUB(buf_widx, size);
2607 tracks[track_widx].codecsize = 0;
2608 return false;
2611 buf_widx = RINGBUF_ADD(buf_widx, rc);
2613 size += rc;
2616 tracks[track_widx].has_codec = true;
2618 close(fd);
2619 logf("Done: %ldB", size);
2621 return true;
2624 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2625 static void audio_set_elapsed(struct mp3entry* id3)
2627 unsigned long offset = id3->offset > id3->first_frame_offset ?
2628 id3->offset - id3->first_frame_offset : 0;
2630 if ( id3->vbr ) {
2631 if ( id3->has_toc ) {
2632 /* calculate elapsed time using TOC */
2633 int i;
2634 unsigned int remainder, plen, relpos, nextpos;
2636 /* find wich percent we're at */
2637 for (i=0; i<100; i++ )
2638 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2639 break;
2641 i--;
2642 if (i < 0)
2643 i = 0;
2645 relpos = id3->toc[i];
2647 if (i < 99)
2648 nextpos = id3->toc[i+1];
2649 else
2650 nextpos = 256;
2652 remainder = offset - (relpos * (id3->filesize / 256));
2654 /* set time for this percent (divide before multiply to prevent
2655 overflow on long files. loss of precision is negligible on
2656 short files) */
2657 id3->elapsed = i * (id3->length / 100);
2659 /* calculate remainder time */
2660 plen = (nextpos - relpos) * (id3->filesize / 256);
2661 id3->elapsed += (((remainder * 100) / plen) *
2662 (id3->length / 10000));
2664 else {
2665 /* no TOC exists. set a rough estimate using average bitrate */
2666 int tpk = id3->length /
2667 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2668 1024);
2669 id3->elapsed = offset / 1024 * tpk;
2672 else
2674 /* constant bitrate, use exact calculation */
2675 if (id3->bitrate != 0)
2676 id3->elapsed = offset / (id3->bitrate / 8);
2680 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2682 char *trackname;
2683 off_t size;
2684 char msgbuf[80];
2686 /* Stop buffer filling if there is no free track entries.
2687 Don't fill up the last track entry (we wan't to store next track
2688 metadata there). */
2689 if (!audio_have_free_tracks())
2691 logf("No free tracks");
2692 return false;
2695 if (current_fd >= 0)
2697 logf("Nonzero fd in alt");
2698 close(current_fd);
2699 current_fd = -1;
2702 last_peek_offset++;
2703 peek_again:
2704 logf("Buffering track:%d/%d", track_widx, track_ridx);
2705 /* Get track name from current playlist read position. */
2706 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2708 /* Handle broken playlists. */
2709 current_fd = open(trackname, O_RDONLY);
2710 if (current_fd < 0)
2712 logf("Open failed");
2713 /* Skip invalid entry from playlist. */
2714 playlist_skip_entry(NULL, last_peek_offset);
2716 else
2717 break;
2720 if (!trackname)
2722 logf("End-of-playlist");
2723 playlist_end = true;
2724 return false;
2727 /* Initialize track entry. */
2728 size = filesize(current_fd);
2729 tracks[track_widx].filerem = size;
2730 tracks[track_widx].filesize = size;
2731 tracks[track_widx].available = 0;
2733 /* Set default values */
2734 if (start_play)
2736 int last_codec = current_codec;
2738 set_current_codec(CODEC_IDX_AUDIO);
2739 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2740 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2741 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2742 dsp_configure(DSP_RESET, 0);
2743 set_current_codec(last_codec);
2746 /* Get track metadata if we don't already have it. */
2747 if (!tracks[track_widx].taginfo_ready)
2749 if (get_metadata(&(tracks[track_widx].id3),current_fd,trackname,v1first))
2751 tracks[track_widx].taginfo_ready = true;
2752 if (start_play)
2754 track_changed = true;
2755 playlist_update_resume_info(audio_current_track());
2758 else
2760 logf("mde:%s!",trackname);
2762 /* Set filesize to zero to indicate no file was loaded. */
2763 tracks[track_widx].filesize = 0;
2764 tracks[track_widx].filerem = 0;
2765 close(current_fd);
2766 current_fd = -1;
2768 /* Skip invalid entry from playlist. */
2769 playlist_skip_entry(NULL, last_peek_offset);
2770 tracks[track_widx].taginfo_ready = false;
2771 goto peek_again;
2776 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2778 char cuepath[MAX_PATH];
2780 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2782 if (look_for_cuesheet_file(trackname, cuepath) &&
2783 parse_cuesheet(cuepath, cue))
2785 strcpy((cue)->audio_filename, trackname);
2786 if (start_play)
2787 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2791 /* Load the codec. */
2792 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2793 if (!audio_loadcodec(start_play))
2795 /* Set filesize to zero to indicate no file was loaded. */
2796 tracks[track_widx].filesize = 0;
2797 tracks[track_widx].filerem = 0;
2798 close(current_fd);
2799 current_fd = -1;
2801 if (tracks[track_widx].codecsize)
2803 /* No space for codec on buffer, not an error */
2804 tracks[track_widx].codecsize = 0;
2805 return false;
2808 /* This is an error condition, either no codec was found, or reading
2809 * the codec file failed part way through, either way, skip the track */
2810 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2811 /* We should not use gui_syncplash from audio thread! */
2812 gui_syncsplash(HZ*2, msgbuf);
2813 /* Skip invalid entry from playlist. */
2814 playlist_skip_entry(NULL, last_peek_offset);
2815 tracks[track_widx].taginfo_ready = false;
2816 goto peek_again;
2819 tracks[track_widx].start_pos = 0;
2820 set_filebuf_watermark(buffer_margin);
2821 tracks[track_widx].id3.elapsed = 0;
2823 if (offset > 0)
2825 switch (tracks[track_widx].id3.codectype) {
2826 case AFMT_MPA_L1:
2827 case AFMT_MPA_L2:
2828 case AFMT_MPA_L3:
2829 lseek(current_fd, offset, SEEK_SET);
2830 tracks[track_widx].id3.offset = offset;
2831 audio_set_elapsed(&tracks[track_widx].id3);
2832 tracks[track_widx].filerem = size - offset;
2833 ci.curpos = offset;
2834 tracks[track_widx].start_pos = offset;
2835 break;
2837 case AFMT_WAVPACK:
2838 lseek(current_fd, offset, SEEK_SET);
2839 tracks[track_widx].id3.offset = offset;
2840 tracks[track_widx].id3.elapsed =
2841 tracks[track_widx].id3.length / 2;
2842 tracks[track_widx].filerem = size - offset;
2843 ci.curpos = offset;
2844 tracks[track_widx].start_pos = offset;
2845 break;
2847 case AFMT_OGG_VORBIS:
2848 case AFMT_SPEEX:
2849 case AFMT_FLAC:
2850 case AFMT_PCM_WAV:
2851 case AFMT_A52:
2852 case AFMT_AAC:
2853 case AFMT_MPC:
2854 case AFMT_APE:
2855 tracks[track_widx].id3.offset = offset;
2856 break;
2860 logf("alt:%s", trackname);
2861 tracks[track_widx].buf_idx = buf_widx;
2863 return audio_read_file(rebuffer);
2866 static bool audio_read_next_metadata(void)
2868 int fd;
2869 char *trackname;
2870 int next_idx;
2871 int status;
2873 next_idx = track_widx;
2874 if (tracks[next_idx].taginfo_ready)
2876 next_idx++;
2877 next_idx &= MAX_TRACK_MASK;
2879 if (tracks[next_idx].taginfo_ready)
2880 return true;
2883 trackname = playlist_peek(last_peek_offset + 1);
2884 if (!trackname)
2885 return false;
2887 fd = open(trackname, O_RDONLY);
2888 if (fd < 0)
2889 return false;
2891 status = get_metadata(&(tracks[next_idx].id3),fd,trackname,v1first);
2892 /* Preload the glyphs in the tags */
2893 if (status)
2895 tracks[next_idx].taginfo_ready = true;
2896 if (tracks[next_idx].id3.title)
2897 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2898 if (tracks[next_idx].id3.artist)
2899 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2900 if (tracks[next_idx].id3.album)
2901 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2903 close(fd);
2905 return status;
2908 /* Send callback events to notify about new tracks. */
2909 static void audio_generate_postbuffer_events(void)
2911 int cur_idx;
2912 int last_idx = -1;
2914 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2916 if (audio_have_tracks())
2918 cur_idx = track_ridx;
2920 while (1) {
2921 if (!tracks[cur_idx].event_sent)
2923 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2925 /* Mark the event 'sent' even if we don't really send one */
2926 tracks[last_idx].event_sent = true;
2927 if (track_buffer_callback)
2928 track_buffer_callback(&tracks[last_idx].id3, false);
2930 last_idx = cur_idx;
2932 if (cur_idx == track_widx)
2933 break;
2934 cur_idx++;
2935 cur_idx &= MAX_TRACK_MASK;
2938 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2940 tracks[last_idx].event_sent = true;
2941 if (track_buffer_callback)
2942 track_buffer_callback(&tracks[last_idx].id3, true);
2947 static bool audio_initialize_buffer_fill(bool clear_tracks)
2949 /* Don't initialize if we're already initialized */
2950 if (filling)
2951 return true;
2953 logf("Starting buffer fill");
2955 /* Set the filling flag true before calling audio_clear_tracks as that
2956 * function can yield and we start looping. */
2957 filling = true;
2959 if (clear_tracks)
2960 audio_clear_track_entries(false);
2962 /* Save the current resume position once. */
2963 playlist_update_resume_info(audio_current_track());
2965 return true;
2968 static void audio_fill_file_buffer(
2969 bool start_play, bool rebuffer, size_t offset)
2971 bool had_next_track = audio_next_track() != NULL;
2972 bool continue_buffering;
2974 /* Must reset the buffer before use if trashed or voice only - voice
2975 file size shouldn't have changed so we can go straight from
2976 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2977 if (buffer_state != BUFFER_STATE_INITIALIZED)
2978 audio_reset_buffer();
2980 if (!audio_initialize_buffer_fill(!start_play))
2981 return ;
2983 /* If we have a partially buffered track, continue loading,
2984 * otherwise load a new track */
2985 if (tracks[track_widx].filesize > 0)
2986 continue_buffering = audio_read_file(rebuffer);
2987 else
2988 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2990 if (!had_next_track && audio_next_track())
2991 track_changed = true;
2993 /* If we're done buffering */
2994 if (!continue_buffering)
2996 audio_read_next_metadata();
2998 audio_generate_postbuffer_events();
2999 filling = false;
3001 #ifndef SIMULATOR
3002 ata_sleep();
3003 #endif
3007 static void audio_rebuffer(void)
3009 logf("Forcing rebuffer");
3011 /* Stop in progress fill, and clear open file descriptor */
3012 if (current_fd >= 0)
3014 close(current_fd);
3015 current_fd = -1;
3017 filling = false;
3019 /* Reset buffer and track pointers */
3020 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3021 track_widx = track_ridx;
3022 audio_clear_track_entries(true);
3023 CUR_TI->available = 0;
3025 /* Fill the buffer */
3026 last_peek_offset = -1;
3027 CUR_TI->filesize = 0;
3028 CUR_TI->start_pos = 0;
3029 ci.curpos = 0;
3031 if (!CUR_TI->taginfo_ready)
3032 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
3034 audio_fill_file_buffer(false, true, 0);
3037 static int audio_check_new_track(void)
3039 int track_count = audio_track_count();
3040 int old_track_ridx = track_ridx;
3041 bool forward;
3043 if (dir_skip)
3045 dir_skip = false;
3046 if (playlist_next_dir(ci.new_track))
3048 ci.new_track = 0;
3049 CUR_TI->taginfo_ready = false;
3050 audio_rebuffer();
3051 goto skip_done;
3053 else
3055 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3056 return Q_CODEC_REQUEST_FAILED;
3060 if (new_playlist)
3061 ci.new_track = 0;
3063 /* If the playlist isn't that big */
3064 if (!playlist_check(ci.new_track))
3066 if (ci.new_track >= 0)
3068 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3069 return Q_CODEC_REQUEST_FAILED;
3071 /* Find the beginning backward if the user over-skips it */
3072 while (!playlist_check(++ci.new_track))
3073 if (ci.new_track >= 0)
3075 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3076 return Q_CODEC_REQUEST_FAILED;
3079 /* Update the playlist */
3080 last_peek_offset -= ci.new_track;
3082 if (playlist_next(ci.new_track) < 0)
3084 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3085 return Q_CODEC_REQUEST_FAILED;
3088 if (new_playlist)
3090 ci.new_track = 1;
3091 new_playlist = false;
3094 /* Save the old track */
3095 prev_ti = CUR_TI;
3097 /* Move to the new track */
3098 track_ridx += ci.new_track;
3099 track_ridx &= MAX_TRACK_MASK;
3101 if (automatic_skip)
3102 playlist_end = false;
3104 track_changed = !automatic_skip;
3106 /* If it is not safe to even skip this many track entries */
3107 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3109 ci.new_track = 0;
3110 CUR_TI->taginfo_ready = false;
3111 audio_rebuffer();
3112 goto skip_done;
3115 forward = ci.new_track > 0;
3116 ci.new_track = 0;
3118 /* If the target track is clearly not in memory */
3119 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3121 audio_rebuffer();
3122 goto skip_done;
3125 /* The track may be in memory, see if it really is */
3126 if (forward)
3128 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3129 audio_rebuffer();
3131 else
3133 int cur_idx = track_ridx;
3134 bool taginfo_ready = true;
3135 bool wrap = track_ridx > old_track_ridx;
3137 while (1)
3139 cur_idx++;
3140 cur_idx &= MAX_TRACK_MASK;
3141 if (!(wrap || cur_idx < old_track_ridx))
3142 break;
3144 /* If we hit a track in between without valid tag info, bail */
3145 if (!tracks[cur_idx].taginfo_ready)
3147 taginfo_ready = false;
3148 break;
3151 tracks[cur_idx].available = tracks[cur_idx].filesize;
3152 if (tracks[cur_idx].codecsize)
3153 tracks[cur_idx].has_codec = true;
3155 if (taginfo_ready)
3157 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3158 audio_rebuffer();
3160 else
3162 CUR_TI->taginfo_ready = false;
3163 audio_rebuffer();
3167 skip_done:
3168 audio_update_trackinfo();
3169 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3170 return Q_CODEC_REQUEST_COMPLETE;
3173 static int audio_rebuffer_and_seek(size_t newpos)
3175 size_t real_preseek;
3176 int fd;
3177 char *trackname;
3179 /* (Re-)open current track's file handle. */
3180 trackname = playlist_peek(0);
3181 fd = open(trackname, O_RDONLY);
3182 if (fd < 0)
3184 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3185 return Q_CODEC_REQUEST_FAILED;
3188 if (current_fd >= 0)
3189 close(current_fd);
3190 current_fd = fd;
3192 playlist_end = false;
3194 ci.curpos = newpos;
3196 /* Clear codec buffer. */
3197 track_widx = track_ridx;
3198 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3200 last_peek_offset = 0;
3201 filling = false;
3202 audio_initialize_buffer_fill(true);
3204 /* This may have been tweaked by the id3v1 code */
3205 CUR_TI->filesize=filesize(fd);
3206 if (newpos > conf_preseek)
3208 CUR_TI->start_pos = newpos - conf_preseek;
3209 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3210 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3211 real_preseek = conf_preseek;
3213 else
3215 CUR_TI->start_pos = 0;
3216 CUR_TI->filerem = CUR_TI->filesize;
3217 real_preseek = newpos;
3220 CUR_TI->available = 0;
3222 audio_read_file(real_preseek);
3224 /* Account for the data we just read that is 'behind' us now */
3225 CUR_TI->available -= real_preseek;
3227 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3229 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3230 return Q_CODEC_REQUEST_COMPLETE;
3233 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3234 bool last_track))
3236 track_buffer_callback = handler;
3239 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3240 bool last_track))
3242 track_unbuffer_callback = handler;
3245 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3247 track_changed_callback = handler;
3250 unsigned long audio_prev_elapsed(void)
3252 return prev_track_elapsed;
3255 static void audio_stop_codec_flush(void)
3257 ci.stop_codec = true;
3258 pcmbuf_pause(true);
3260 while (audio_codec_loaded)
3261 yield();
3263 /* If the audio codec is not loaded any more, and the audio is still
3264 * playing, it is now and _only_ now safe to call this function from the
3265 * audio thread */
3266 if (pcm_is_playing())
3267 pcmbuf_play_stop();
3268 pcmbuf_pause(paused);
3271 static void audio_stop_playback(void)
3273 /* If we were playing, save resume information */
3274 if (playing)
3276 struct mp3entry *id3 = NULL;
3278 if (!playlist_end || !ci.stop_codec)
3280 /* Set this early, the outside code yields and may allow the codec
3281 to try to wait for a reply on a buffer wait */
3282 ci.stop_codec = true;
3283 id3 = audio_current_track();
3286 /* Save the current playing spot, or NULL if the playlist has ended */
3287 playlist_update_resume_info(id3);
3289 prev_track_elapsed = CUR_TI->id3.elapsed;
3291 /* Increment index so runtime info is saved in audio_clear_track_entries().
3292 * Done here, as audio_stop_playback() may be called more than once.
3293 * Don't update runtime unless playback is stopped because of end of playlist.
3294 * Updating runtime when manually stopping a tracks, can destroy autoscores
3295 * and playcounts.
3297 if (playlist_end)
3299 track_ridx++;
3300 track_ridx &= MAX_TRACK_MASK;
3304 filling = false;
3305 paused = false;
3306 audio_stop_codec_flush();
3307 playing = false;
3309 if (current_fd >= 0)
3311 close(current_fd);
3312 current_fd = -1;
3315 /* Mark all entries null. */
3316 audio_clear_track_entries(false);
3319 static void audio_play_start(size_t offset)
3321 #if INPUT_SRC_CAPS != 0
3322 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3323 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3324 #endif
3326 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3327 paused = false;
3328 audio_stop_codec_flush();
3330 track_changed = true;
3331 playlist_end = false;
3333 playing = true;
3335 ci.new_track = 0;
3336 ci.seek_time = 0;
3337 wps_offset = 0;
3339 if (current_fd >= 0)
3341 close(current_fd);
3342 current_fd = -1;
3345 sound_set_volume(global_settings.volume);
3346 track_widx = track_ridx = 0;
3347 buf_ridx = buf_widx = 0;
3349 /* Mark all entries null. */
3350 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3352 last_peek_offset = -1;
3354 /* Officially playing */
3355 queue_reply(&audio_queue, 1);
3357 audio_fill_file_buffer(true, false, offset);
3359 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3360 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3364 /* Invalidates all but currently playing track. */
3365 static void audio_invalidate_tracks(void)
3367 if (audio_have_tracks())
3369 last_peek_offset = 0;
3370 playlist_end = false;
3371 track_widx = track_ridx;
3373 /* Mark all other entries null (also buffered wrong metadata). */
3374 audio_clear_track_entries(true);
3376 /* If the current track is fully buffered, advance the write pointer */
3377 if (tracks[track_widx].filerem == 0)
3378 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3380 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3382 audio_read_next_metadata();
3386 static void audio_new_playlist(void)
3388 /* Prepare to start a new fill from the beginning of the playlist */
3389 last_peek_offset = -1;
3390 if (audio_have_tracks())
3392 if (paused)
3393 skipped_during_pause = true;
3394 playlist_end = false;
3395 track_widx = track_ridx;
3396 audio_clear_track_entries(true);
3398 track_widx++;
3399 track_widx &= MAX_TRACK_MASK;
3401 /* Stop reading the current track */
3402 CUR_TI->filerem = 0;
3403 close(current_fd);
3404 current_fd = -1;
3406 /* Mark the current track as invalid to prevent skipping back to it */
3407 CUR_TI->taginfo_ready = false;
3409 /* Invalidate the buffer other than the playing track */
3410 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3413 /* Signal the codec to initiate a track change forward */
3414 new_playlist = true;
3415 ci.new_track = 1;
3417 /* Officially playing */
3418 queue_reply(&audio_queue, 1);
3420 audio_fill_file_buffer(false, true, 0);
3423 static void audio_initiate_track_change(long direction)
3425 playlist_end = false;
3426 ci.new_track += direction;
3427 wps_offset -= direction;
3428 if (paused)
3429 skipped_during_pause = true;
3432 static void audio_initiate_dir_change(long direction)
3434 playlist_end = false;
3435 dir_skip = true;
3436 ci.new_track = direction;
3437 if (paused)
3438 skipped_during_pause = true;
3442 * Layout audio buffer as follows - iram buffer depends on target:
3443 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3445 static void audio_reset_buffer(void)
3447 /* see audio_get_recording_buffer if this is modified */
3448 logf("audio_reset_buffer");
3450 /* If the setup of anything allocated before the file buffer is
3451 changed, do check the adjustments after the buffer_alloc call
3452 as it will likely be affected and need sliding over */
3454 /* Initially set up file buffer as all space available */
3455 malloc_buf = audiobuf + talk_get_bufsize();
3456 /* Align the malloc buf to line size. Especially important to cf
3457 targets that do line reads/writes. */
3458 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3459 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3460 filebuflen = audiobufend - filebuf;
3462 /* Allow for codec swap space at end of audio buffer */
3463 if (talk_voice_required())
3465 /* Layout of swap buffer:
3466 * #ifdef IRAM_STEAL (dedicated iram_buf):
3467 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3468 * #else:
3469 * audiobuf...|dram_buf|iram_buf|audiobufend
3471 #ifdef PLAYBACK_VOICE
3472 /* Check for an absolutely nasty situation which should never,
3473 ever happen - frankly should just panic */
3474 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3476 logf("buffer reset with voice swapped");
3478 /* line align length which line aligns the calculations below since
3479 all sizes are also at least line aligned - needed for memswap128 */
3480 filebuflen &= ~15;
3481 #ifdef IRAM_STEAL
3482 filebuflen -= CODEC_SIZE;
3483 #else
3484 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3485 #endif
3486 /* Allocate buffers for swapping voice <=> audio */
3487 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3488 and out of the way of buffer usage or else a call to audio_get_buffer
3489 and subsequent buffer use might trash the swap space. A plugin
3490 initializing IRAM after getting the full buffer would present similar
3491 problem. Options include: failing the request if the other buffer
3492 has been obtained already or never allowing use of the voice IRAM
3493 buffer within the audio buffer. Using buffer_alloc basically
3494 implements the second in a more convenient way. */
3495 dram_buf = filebuf + filebuflen;
3497 #ifdef IRAM_STEAL
3498 /* Allocate voice IRAM swap buffer once */
3499 if (iram_buf == NULL)
3501 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3502 /* buffer_alloc moves audiobuf; this is safe because only the end
3503 * has been touched so far in this function and the address of
3504 * filebuf + filebuflen is not changed */
3505 malloc_buf += CODEC_IRAM_SIZE;
3506 filebuf += CODEC_IRAM_SIZE;
3507 filebuflen -= CODEC_IRAM_SIZE;
3509 #else
3510 /* Allocate iram_buf after dram_buf */
3511 iram_buf = dram_buf + CODEC_SIZE;
3512 #endif /* IRAM_STEAL */
3513 #endif /* PLAYBACK_VOICE */
3515 else
3517 #ifdef PLAYBACK_VOICE
3518 /* No swap buffers needed */
3519 iram_buf = NULL;
3520 dram_buf = NULL;
3521 #endif
3524 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3525 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3527 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3528 will already be line aligned */
3529 filebuflen &= ~3;
3531 /* Set the high watermark as 75% full...or 25% empty :) */
3532 #if MEM > 8
3533 high_watermark = 3*filebuflen / 4;
3534 #endif
3536 /* Clear any references to the file buffer */
3537 buffer_state = BUFFER_STATE_INITIALIZED;
3539 #ifdef ROCKBOX_HAS_LOGF
3540 /* Make sure everything adds up - yes, some info is a bit redundant but
3541 aids viewing and the sumation of certain variables should add up to
3542 the location of others. */
3544 size_t pcmbufsize;
3545 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3546 logf("mabuf: %08X", (unsigned)malloc_buf);
3547 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3548 logf("fbuf: %08X", (unsigned)filebuf);
3549 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3550 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3551 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3552 logf("pcmb: %08X", (unsigned)pcmbuf);
3553 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3554 if (dram_buf)
3556 logf("dramb: %08X", (unsigned)dram_buf);
3557 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3559 if (iram_buf)
3561 logf("iramb: %08X", (unsigned)iram_buf);
3562 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3565 #endif
3568 #if MEM > 8
3569 /* we dont want this rebuffering on targets with little ram
3570 because the disk may never spin down */
3571 static bool ata_fillbuffer_callback(void)
3573 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3574 return true;
3576 #endif
3578 static void audio_thread(void)
3580 struct event ev;
3582 pcm_postinit();
3584 #ifdef PLAYBACK_VOICE
3585 /* Unlock mutex that init stage locks before creating this thread */
3586 mutex_unlock(&mutex_codecthread);
3588 /* Buffers must be set up by now - should panic - really */
3589 if (buffer_state != BUFFER_STATE_INITIALIZED)
3591 logf("audio_thread start: no buffer");
3594 /* Have to wait for voice to load up or else the codec swap will be
3595 invalid when an audio codec is loaded */
3596 wait_for_voice_swap_in();
3597 #endif
3599 while (1)
3601 intptr_t result = 0;
3603 if (filling)
3605 queue_wait_w_tmo(&audio_queue, &ev, 0);
3606 if (ev.id == SYS_TIMEOUT)
3607 ev.id = Q_AUDIO_FILL_BUFFER;
3609 else
3611 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3612 #if MEM > 8
3613 if (playing && (ev.id == SYS_TIMEOUT) &&
3614 (FILEBUFUSED < high_watermark))
3615 register_ata_idle_func(ata_fillbuffer_callback);
3616 #endif
3619 switch (ev.id) {
3620 #if MEM > 8
3621 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3622 /* only fill if the disk is still spining */
3623 #ifndef SIMULATOR
3624 if (!ata_disk_is_active())
3625 break;
3626 #endif
3627 #endif /* MEM > 8 */
3628 /* else fall through to Q_AUDIO_FILL_BUFFER */
3629 case Q_AUDIO_FILL_BUFFER:
3630 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3631 if (!filling)
3632 if (!playing || playlist_end || ci.stop_codec)
3633 break;
3634 audio_fill_file_buffer(false, false, 0);
3635 break;
3637 case Q_AUDIO_PLAY:
3638 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3639 if (playing && ev.data <= 0)
3640 audio_new_playlist();
3641 else
3643 audio_stop_playback();
3644 audio_play_start((size_t)ev.data);
3646 break;
3648 case Q_AUDIO_STOP:
3649 LOGFQUEUE("audio < Q_AUDIO_STOP");
3650 if (playing)
3651 audio_stop_playback();
3652 if (ev.data != 0)
3653 queue_clear(&audio_queue);
3654 break;
3656 case Q_AUDIO_PAUSE:
3657 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3658 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3659 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3660 skipped_during_pause = false;
3661 if (!playing)
3662 break;
3663 pcmbuf_pause((bool)ev.data);
3664 paused = (bool)ev.data;
3665 break;
3667 case Q_AUDIO_SKIP:
3668 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3669 audio_initiate_track_change((long)ev.data);
3670 break;
3672 case Q_AUDIO_PRE_FF_REWIND:
3673 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3674 if (!playing)
3675 break;
3676 pcmbuf_pause(true);
3677 break;
3679 case Q_AUDIO_FF_REWIND:
3680 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3681 if (!playing)
3682 break;
3683 ci.seek_time = (long)ev.data+1;
3684 break;
3686 case Q_AUDIO_REBUFFER_SEEK:
3687 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3688 result = audio_rebuffer_and_seek(ev.data);
3689 break;
3691 case Q_AUDIO_CHECK_NEW_TRACK:
3692 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3693 result = audio_check_new_track();
3694 break;
3696 case Q_AUDIO_DIR_SKIP:
3697 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3698 playlist_end = false;
3699 audio_initiate_dir_change(ev.data);
3700 break;
3702 case Q_AUDIO_FLUSH:
3703 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3704 audio_invalidate_tracks();
3705 break;
3707 case Q_AUDIO_TRACK_CHANGED:
3708 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3709 if (track_changed_callback)
3710 track_changed_callback(&CUR_TI->id3);
3711 track_changed = true;
3712 playlist_update_resume_info(audio_current_track());
3713 break;
3715 #ifndef SIMULATOR
3716 case SYS_USB_CONNECTED:
3717 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3718 if (playing)
3719 audio_stop_playback();
3720 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3721 usb_wait_for_disconnect(&audio_queue);
3722 break;
3723 #endif
3725 case SYS_TIMEOUT:
3726 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3727 break;
3729 default:
3730 LOGFQUEUE("audio < default");
3731 } /* end switch */
3733 queue_reply(&audio_queue, result);
3734 } /* end while */
3737 #ifdef ROCKBOX_HAS_LOGF
3738 static void audio_test_track_changed_event(struct mp3entry *id3)
3740 (void)id3;
3742 logf("tce:%s", id3->path);
3744 #endif
3746 /* Initialize the audio system - called from init() in main.c.
3747 * Last function because of all the references to internal symbols
3749 void audio_init(void)
3751 #ifdef PLAYBACK_VOICE
3752 static bool voicetagtrue = true;
3753 static struct mp3entry id3_voice;
3754 #endif
3756 /* Can never do this twice */
3757 if (audio_is_initialized)
3759 logf("audio: already initialized");
3760 return;
3763 logf("audio: initializing");
3765 /* Initialize queues before giving control elsewhere in case it likes
3766 to send messages. Thread creation will be delayed however so nothing
3767 starts running until ready if something yields such as talk_init. */
3768 #ifdef PLAYBACK_VOICE
3769 mutex_init(&mutex_codecthread);
3770 /* Take ownership of lock to prevent playback of anything before audio
3771 hardware is initialized - audio thread unlocks it after final init
3772 stage */
3773 mutex_lock(&mutex_codecthread);
3774 #endif
3775 queue_init(&audio_queue, true);
3776 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3777 queue_init(&codec_queue, true);
3779 pcm_init();
3781 #ifdef ROCKBOX_HAS_LOGF
3782 audio_set_track_changed_event(audio_test_track_changed_event);
3783 #endif
3785 /* Initialize codec api. */
3786 ci.read_filebuf = codec_filebuf_callback;
3787 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3788 ci.get_codec_memory = codec_get_memory_callback;
3789 ci.request_buffer = codec_request_buffer_callback;
3790 ci.advance_buffer = codec_advance_buffer_callback;
3791 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3792 ci.request_next_track = codec_request_next_track_callback;
3793 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3794 ci.seek_buffer = codec_seek_buffer_callback;
3795 ci.seek_complete = codec_seek_complete_callback;
3796 ci.set_elapsed = codec_set_elapsed_callback;
3797 ci.set_offset = codec_set_offset_callback;
3798 ci.configure = codec_configure_callback;
3799 ci.discard_codec = codec_discard_codec_callback;
3801 /* Initialize voice codec api. */
3802 #ifdef PLAYBACK_VOICE
3803 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3804 memset(&id3_voice, 0, sizeof(id3_voice));
3805 ci_voice.read_filebuf = voice_filebuf_callback;
3806 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3807 ci_voice.get_codec_memory = voice_get_memory_callback;
3808 ci_voice.request_buffer = voice_request_buffer_callback;
3809 ci_voice.advance_buffer = voice_advance_buffer_callback;
3810 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3811 ci_voice.request_next_track = voice_request_next_track_callback;
3812 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3813 ci_voice.seek_buffer = voice_seek_buffer_callback;
3814 ci_voice.seek_complete = voice_do_nothing;
3815 ci_voice.set_elapsed = voice_set_elapsed_callback;
3816 ci_voice.set_offset = voice_set_offset_callback;
3817 ci_voice.configure = voice_configure_callback;
3818 ci_voice.discard_codec = voice_do_nothing;
3819 ci_voice.taginfo_ready = &voicetagtrue;
3820 ci_voice.id3 = &id3_voice;
3821 id3_voice.frequency = 11200;
3822 id3_voice.length = 1000000L;
3823 #endif
3825 /* initialize the buffer */
3826 filebuf = audiobuf;
3828 /* audio_reset_buffer must to know the size of voice buffer so init
3829 talk first */
3830 talk_init();
3832 /* Create the threads late now that we shouldn't be yielding again before
3833 returning */
3834 codec_thread_p = create_thread(
3835 codec_thread, codec_stack, sizeof(codec_stack),
3836 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3837 IF_COP(, CPU, true));
3839 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
3840 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3841 IF_COP(, CPU, false));
3843 #ifdef PLAYBACK_VOICE
3844 /* TODO: Change this around when various speech codecs can be used */
3845 if (talk_voice_required())
3847 logf("Starting voice codec");
3848 queue_init(&voice_queue, true);
3849 create_thread(voice_thread, voice_stack,
3850 sizeof(voice_stack), voice_thread_name
3851 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false));
3853 #endif
3855 /* Set crossfade setting for next buffer init which should be about... */
3856 pcmbuf_crossfade_enable(global_settings.crossfade);
3858 /* ...now! Set up the buffers */
3859 audio_reset_buffer();
3861 /* Probably safe to say */
3862 audio_is_initialized = true;
3864 sound_settings_apply();
3865 #ifdef HAVE_WM8758
3866 eq_hw_enable(global_settings.eq_hw_enabled);
3867 #endif
3868 #ifndef HAVE_FLASH_STORAGE
3869 audio_set_buffer_margin(global_settings.buffer_margin);
3870 #endif
3871 } /* audio_init */