Check target / mountpoint selection before performing any installation.
[Rockbox.git] / apps / playback.c
blobb7d3b9987f03aff4c19ad3179f7722af47364c0d
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 do_shutup();
662 #endif
664 /* Start playback */
665 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
666 /* Don't return until playback has actually started */
667 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
670 void audio_stop(void)
672 /* Stop playback */
673 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
674 /* Don't return until playback has actually stopped */
675 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
678 void audio_pause(void)
680 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
681 /* Don't return until playback has actually paused */
682 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
685 void audio_resume(void)
687 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
688 /* Don't return until playback has actually resumed */
689 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
692 void audio_next(void)
694 if (playlist_check(ci.new_track + wps_offset + 1))
696 if (global_settings.beep)
697 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
699 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
700 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
701 /* Update wps while our message travels inside deep playback queues. */
702 wps_offset++;
703 track_changed = true;
705 else
707 /* No more tracks. */
708 if (global_settings.beep)
709 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
713 void audio_prev(void)
715 if (playlist_check(ci.new_track + wps_offset - 1))
717 if (global_settings.beep)
718 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
720 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
721 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
722 /* Update wps while our message travels inside deep playback queues. */
723 wps_offset--;
724 track_changed = true;
726 else
728 /* No more tracks. */
729 if (global_settings.beep)
730 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
734 void audio_next_dir(void)
736 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
737 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
740 void audio_prev_dir(void)
742 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
743 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
746 void audio_pre_ff_rewind(void)
748 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
749 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
752 void audio_ff_rewind(long newpos)
754 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
755 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
758 void audio_flush_and_reload_tracks(void)
760 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
761 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
764 void audio_error_clear(void)
766 #ifdef AUDIO_HAVE_RECORDING
767 pcm_rec_error_clear();
768 #endif
771 int audio_status(void)
773 int ret = 0;
775 if (playing)
776 ret |= AUDIO_STATUS_PLAY;
778 if (paused)
779 ret |= AUDIO_STATUS_PAUSE;
781 #ifdef HAVE_RECORDING
782 /* Do this here for constitency with mpeg.c version */
783 ret |= pcm_rec_status();
784 #endif
786 return ret;
789 int audio_get_file_pos(void)
791 return 0;
794 #ifndef HAVE_FLASH_STORAGE
795 void audio_set_buffer_margin(int setting)
797 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
798 buffer_margin = lookup[setting];
799 logf("buffer margin: %ld", buffer_margin);
800 set_filebuf_watermark(buffer_margin);
802 #endif
804 /* Take nescessary steps to enable or disable the crossfade setting */
805 void audio_set_crossfade(int enable)
807 size_t offset;
808 bool was_playing;
809 size_t size;
811 /* Tell it the next setting to use */
812 pcmbuf_crossfade_enable(enable);
814 /* Return if size hasn't changed or this is too early to determine
815 which in the second case there's no way we could be playing
816 anything at all */
817 if (pcmbuf_is_same_size())
819 /* This function is a copout and just syncs some variables -
820 to be removed at a later date */
821 pcmbuf_crossfade_enable_finished();
822 return;
825 offset = 0;
826 was_playing = playing;
828 /* Playback has to be stopped before changing the buffer size */
829 if (was_playing)
831 /* Store the track resume position */
832 offset = CUR_TI->id3.offset;
833 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
836 /* Blast it - audio buffer will have to be setup again next time
837 something plays */
838 audio_get_buffer(true, &size);
840 /* Restart playback if audio was running previously */
841 if (was_playing)
842 audio_play(offset);
845 /* --- Routines called from multiple threads --- */
846 static void set_current_codec(int codec_idx)
848 current_codec = codec_idx;
849 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
852 #ifdef PLAYBACK_VOICE
853 static void swap_codec(void)
855 int my_codec;
857 /* Swap nothing if no swap buffers exist */
858 if (dram_buf == NULL)
860 logf("swap: no swap buffers");
861 return;
864 my_codec = current_codec;
866 logf("swapping out codec: %d", my_codec);
868 /* Invert this when a codec thread enters and leaves */
869 swap_codec_parity = !swap_codec_parity;
871 /* If this is true, an odd number of calls has occurred and there's
872 no codec thread waiting to swap us out when it locks and runs. This
873 occurs when playback is stopped or when just starting playback and
874 the audio thread is loading a codec; parities should always be even
875 on entry when a thread calls this during playback */
876 if (swap_codec_parity)
878 /* Save our current IRAM and DRAM */
879 #ifdef IRAM_STEAL
880 if (voice_iram_stolen)
882 logf("swap: iram restore");
883 voice_iram_stolen = false;
884 /* Don't swap trashed data into buffer as the voice IRAM will
885 already be swapped out - should _always_ be the case if
886 voice_iram_stolen is true since the voice has been swapped
887 in beforehand */
888 if (my_codec == CODEC_IDX_VOICE)
890 logf("voice iram already swapped");
891 goto skip_iram_swap;
894 #endif
896 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
898 #ifdef IRAM_STEAL
899 skip_iram_swap:
900 #endif
902 memswap128(dram_buf, codecbuf, CODEC_SIZE);
903 /* No cache invalidation needed; it will be done in codec_load_ram
904 or we won't be here otherwise */
907 /* Release my semaphore */
908 mutex_unlock(&mutex_codecthread);
909 logf("unlocked: %d", my_codec);
911 /* Loop until the other codec has locked and run */
912 do {
913 /* Release my semaphore and force a task switch. */
914 yield();
915 } while (my_codec == current_codec);
917 /* Wait for other codec to unlock */
918 mutex_lock(&mutex_codecthread);
920 /* Take control */
921 logf("waiting for lock: %d", my_codec);
922 set_current_codec(my_codec);
924 /* Reload our IRAM and DRAM */
925 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
926 memswap128(dram_buf, codecbuf, CODEC_SIZE);
927 invalidate_icache();
929 /* Flip parity again */
930 swap_codec_parity = !swap_codec_parity;
932 logf("resuming codec: %d", my_codec);
935 /* This function is meant to be used by the buffer stealing functions to
936 ensure the codec is no longer active and so voice will be swapped-in
937 before it is called */
938 static void voice_stop(void)
940 #ifdef PLAYBACK_VOICE
941 /* Must have a voice codec loaded or we'll hang forever here */
942 if (!voice_codec_loaded)
943 return;
945 do_shutup();
947 /* Loop until voice empties it's queue, stops and picks up on the new
948 track; the voice thread must be stopped and waiting for messages
949 outside the codec */
950 while (voice_is_playing || !queue_empty(&voice_queue) ||
951 ci_voice.new_track)
952 yield();
954 if (!playing)
955 pcmbuf_play_stop();
956 #endif
957 } /* voice_stop */
959 /* Is voice still speaking */
960 /* Unfortunately only reliable when music is not also playing. */
961 static bool is_voice_speaking(void)
963 return is_voice_queued()
964 || voice_is_playing
965 || (!playing && pcm_is_playing());
968 /* Wait for voice to finish speaking. */
969 /* Also only reliable when music is not also playing. */
970 void voice_wait(void)
972 while (is_voice_speaking())
973 sleep(HZ/10);
976 #endif /* PLAYBACK_VOICE */
978 static void set_filebuf_watermark(int seconds)
980 size_t bytes;
982 if (!filebuf)
983 return; /* Audio buffers not yet set up */
985 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
986 bytes = MIN(bytes, filebuflen / 2);
987 conf_watermark = bytes;
990 const char * get_codec_filename(int cod_spec)
992 const char *fname;
994 #ifdef HAVE_RECORDING
995 /* Can choose decoder or encoder if one available */
996 int type = cod_spec & CODEC_TYPE_MASK;
997 int afmt = cod_spec & CODEC_AFMT_MASK;
999 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1000 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1002 fname = (type == CODEC_TYPE_ENCODER) ?
1003 audio_formats[afmt].codec_enc_root_fn :
1004 audio_formats[afmt].codec_root_fn;
1006 logf("%s: %d - %s",
1007 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1008 afmt, fname ? fname : "<unknown>");
1009 #else /* !HAVE_RECORDING */
1010 /* Always decoder */
1011 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1012 cod_spec = AFMT_UNKNOWN;
1013 fname = audio_formats[cod_spec].codec_root_fn;
1014 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1015 #endif /* HAVE_RECORDING */
1017 return fname;
1018 } /* get_codec_filename */
1021 /* --- Voice thread --- */
1023 #ifdef PLAYBACK_VOICE
1025 static bool voice_pcmbuf_insert_callback(
1026 const void *ch1, const void *ch2, int count)
1028 const char *src[2] = { ch1, ch2 };
1030 while (count > 0)
1032 int out_count = dsp_output_count(count);
1033 int inp_count;
1034 char *dest;
1036 while ((dest = pcmbuf_request_voice_buffer(
1037 &out_count, playing)) == NULL)
1039 if (playing && audio_codec_loaded)
1040 swap_codec();
1041 else
1042 yield();
1045 /* Get the real input_size for output_size bytes, guarding
1046 * against resampling buffer overflows. */
1047 inp_count = dsp_input_count(out_count);
1049 if (inp_count <= 0)
1050 return true;
1052 /* Input size has grown, no error, just don't write more than length */
1053 if (inp_count > count)
1054 inp_count = count;
1056 out_count = dsp_process(dest, src, inp_count);
1058 if (out_count <= 0)
1059 return true;
1061 if (playing)
1063 pcmbuf_mix_voice(out_count);
1064 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1065 audio_codec_loaded)
1066 swap_codec();
1068 else
1069 pcmbuf_write_complete(out_count);
1071 count -= inp_count;
1074 return true;
1075 } /* voice_pcmbuf_insert_callback */
1077 static void* voice_get_memory_callback(size_t *size)
1079 /* Voice should have no use for this. If it did, we'd have to
1080 swap the malloc buffer as well. */
1081 *size = 0;
1082 return NULL;
1085 static void voice_set_elapsed_callback(unsigned int value)
1087 (void)value;
1090 static void voice_set_offset_callback(size_t value)
1092 (void)value;
1095 static void voice_configure_callback(int setting, intptr_t value)
1097 if (!dsp_configure(setting, value))
1099 logf("Illegal key:%d", setting);
1103 static size_t voice_filebuf_callback(void *ptr, size_t size)
1105 (void)ptr;
1106 (void)size;
1108 return 0;
1111 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1112 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1114 if (aborting && !playing && pcm_is_playing())
1116 /* Aborting: Slight hack - flush PCM buffer if
1117 only being used for voice */
1118 pcmbuf_play_stop();
1121 if (voice_is_playing)
1123 /* Clear the current buffer */
1124 voice_is_playing = false;
1125 voice_getmore = NULL;
1126 voice_remaining = 0;
1127 voicebuf = NULL;
1129 /* Cancel any automatic boost if no more clips requested. */
1130 if (!playing || !voice_thread_start)
1131 sleep(0);
1133 /* Force the codec to think it's changing tracks */
1134 ci_voice.new_track = 1;
1136 *realsize = 0;
1137 return true; /* Yes, change tracks */
1140 return false;
1143 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1145 struct event ev;
1147 if (ci_voice.new_track)
1149 *realsize = 0;
1150 return NULL;
1153 while (1)
1155 if (voice_is_playing || playing)
1157 queue_wait_w_tmo(&voice_queue, &ev, 0);
1158 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1159 ev.id = Q_AUDIO_PLAY;
1161 else
1163 queue_wait(&voice_queue, &ev);
1166 switch (ev.id) {
1167 case Q_AUDIO_PLAY:
1168 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1169 if (playing)
1171 if (audio_codec_loaded)
1172 swap_codec();
1173 yield();
1175 break;
1177 #ifdef AUDIO_HAVE_RECORDING
1178 case Q_ENCODER_RECORD:
1179 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1180 swap_codec();
1181 break;
1182 #endif
1184 case Q_VOICE_STOP:
1185 LOGFQUEUE("voice < Q_VOICE_STOP");
1186 if (voice_on_voice_stop(ev.data, realsize))
1187 return NULL;
1188 break;
1190 case SYS_USB_CONNECTED:
1192 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1193 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1194 /* Voice is obviously current so let us swap ourselves away if
1195 playing so audio may stop itself - audio_codec_loaded can
1196 only be true in this case if we're here even if the codec
1197 is only about to load */
1198 if (audio_codec_loaded)
1199 swap_codec();
1200 /* Playback should be finished by now - ack and wait */
1201 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1202 usb_wait_for_disconnect(&voice_queue);
1203 if (change_tracks)
1204 return NULL;
1205 break;
1208 case Q_VOICE_PLAY:
1209 LOGFQUEUE("voice < Q_VOICE_PLAY");
1210 if (!voice_is_playing)
1212 /* Set up new voice data */
1213 struct voice_info *voice_data;
1214 #ifdef IRAM_STEAL
1215 if (voice_iram_stolen)
1217 /* Voice is the first to run again and is currently
1218 loaded */
1219 logf("voice: iram restore");
1220 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1221 voice_iram_stolen = false;
1223 #endif
1224 /* Must reset the buffer before any playback begins if
1225 needed */
1226 if (buffer_state == BUFFER_STATE_TRASHED)
1227 audio_reset_buffer();
1229 voice_is_playing = true;
1230 trigger_cpu_boost();
1231 voice_data = (struct voice_info *)ev.data;
1232 voice_remaining = voice_data->size;
1233 voicebuf = voice_data->buf;
1234 voice_getmore = voice_data->callback;
1236 goto voice_play_clip; /* To exit both switch and while */
1238 case SYS_TIMEOUT:
1239 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1240 goto voice_play_clip;
1242 default:
1243 LOGFQUEUE("voice < default");
1247 voice_play_clip:
1249 if (voice_remaining == 0 || voicebuf == NULL)
1251 if (voice_getmore)
1252 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1254 /* If this clip is done */
1255 if (voice_remaining == 0)
1257 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1258 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1259 /* Force pcm playback. */
1260 if (!pcm_is_playing())
1261 pcmbuf_play_start();
1265 *realsize = MIN(voice_remaining, reqsize);
1267 if (*realsize == 0)
1268 return NULL;
1270 return voicebuf;
1271 } /* voice_request_buffer_callback */
1273 static void voice_advance_buffer_callback(size_t amount)
1275 amount = MIN(amount, voice_remaining);
1276 voicebuf += amount;
1277 voice_remaining -= amount;
1280 static void voice_advance_buffer_loc_callback(void *ptr)
1282 size_t amount = (size_t)ptr - (size_t)voicebuf;
1284 voice_advance_buffer_callback(amount);
1287 static off_t voice_mp3_get_filepos_callback(int newtime)
1289 (void)newtime;
1291 return 0;
1294 static void voice_do_nothing(void)
1296 return;
1299 static bool voice_seek_buffer_callback(size_t newpos)
1301 (void)newpos;
1303 return false;
1306 static bool voice_request_next_track_callback(void)
1308 ci_voice.new_track = 0;
1309 return true;
1312 static void voice_thread(void)
1314 logf("Loading voice codec");
1315 voice_codec_loaded = true;
1316 mutex_lock(&mutex_codecthread);
1317 set_current_codec(CODEC_IDX_VOICE);
1318 dsp_configure(DSP_RESET, 0);
1319 voice_remaining = 0;
1320 voice_getmore = NULL;
1322 /* FIXME: If we being starting the voice thread without reboot, the
1323 voice_queue could be full of old stuff and we must flush it. */
1324 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1326 logf("Voice codec finished");
1327 voice_codec_loaded = false;
1328 mutex_unlock(&mutex_codecthread);
1329 voice_thread_p = NULL;
1330 remove_thread(NULL);
1331 } /* voice_thread */
1333 #endif /* PLAYBACK_VOICE */
1335 /* --- Codec thread --- */
1336 static bool codec_pcmbuf_insert_callback(
1337 const void *ch1, const void *ch2, int count)
1339 const char *src[2] = { ch1, ch2 };
1341 while (count > 0)
1343 int out_count = dsp_output_count(count);
1344 int inp_count;
1345 char *dest;
1347 /* Prevent audio from a previous track from playing */
1348 if (ci.new_track || ci.stop_codec)
1349 return true;
1351 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1353 sleep(1);
1354 if (ci.seek_time || ci.new_track || ci.stop_codec)
1355 return true;
1358 /* Get the real input_size for output_size bytes, guarding
1359 * against resampling buffer overflows. */
1360 inp_count = dsp_input_count(out_count);
1362 if (inp_count <= 0)
1363 return true;
1365 /* Input size has grown, no error, just don't write more than length */
1366 if (inp_count > count)
1367 inp_count = count;
1369 out_count = dsp_process(dest, src, inp_count);
1371 if (out_count <= 0)
1372 return true;
1374 pcmbuf_write_complete(out_count);
1376 #ifdef PLAYBACK_VOICE
1377 if ((voice_is_playing || voice_thread_start)
1378 && pcm_is_playing() && voice_codec_loaded &&
1379 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1381 voice_thread_start = false;
1382 swap_codec();
1384 #endif
1386 count -= inp_count;
1389 return true;
1390 } /* codec_pcmbuf_insert_callback */
1392 static void* codec_get_memory_callback(size_t *size)
1394 *size = MALLOC_BUFSIZE;
1395 return malloc_buf;
1398 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1399 static void codec_pcmbuf_position_callback(size_t size)
1401 /* This is called from an ISR, so be quick */
1402 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1403 prev_ti->id3.elapsed;
1405 if (time >= prev_ti->id3.length)
1407 pcmbuf_set_position_callback(NULL);
1408 prev_ti->id3.elapsed = prev_ti->id3.length;
1410 else
1411 prev_ti->id3.elapsed = time;
1414 static void codec_set_elapsed_callback(unsigned int value)
1416 unsigned int latency;
1417 if (ci.seek_time)
1418 return;
1420 #ifdef AB_REPEAT_ENABLE
1421 ab_position_report(value);
1422 #endif
1424 latency = pcmbuf_get_latency();
1425 if (value < latency)
1426 CUR_TI->id3.elapsed = 0;
1427 else if (value - latency > CUR_TI->id3.elapsed ||
1428 value - latency < CUR_TI->id3.elapsed - 2)
1430 CUR_TI->id3.elapsed = value - latency;
1434 static void codec_set_offset_callback(size_t value)
1436 unsigned int latency;
1438 if (ci.seek_time)
1439 return;
1441 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1442 if (value < latency)
1443 CUR_TI->id3.offset = 0;
1444 else
1445 CUR_TI->id3.offset = value - latency;
1448 static void codec_advance_buffer_counters(size_t amount)
1450 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1451 ci.curpos += amount;
1452 CUR_TI->available -= amount;
1454 /* Start buffer filling as necessary. */
1455 if (!pcmbuf_is_lowdata() && !filling)
1457 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1459 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1460 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1465 /* copy up-to size bytes into ptr and return the actual size copied */
1466 static size_t codec_filebuf_callback(void *ptr, size_t size)
1468 char *buf = (char *)ptr;
1469 size_t copy_n;
1470 size_t part_n;
1472 if (ci.stop_codec || !playing)
1473 return 0;
1475 /* The ammount to copy is the lesser of the requested amount and the
1476 * amount left of the current track (both on disk and already loaded) */
1477 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1479 /* Nothing requested OR nothing left */
1480 if (copy_n == 0)
1481 return 0;
1483 /* Let the disk buffer catch fill until enough data is available */
1484 while (copy_n > CUR_TI->available)
1486 if (!filling)
1488 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1489 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1492 sleep(1);
1493 if (ci.stop_codec || ci.new_track)
1494 return 0;
1497 /* Copy as much as possible without wrapping */
1498 part_n = MIN(copy_n, filebuflen - buf_ridx);
1499 memcpy(buf, &filebuf[buf_ridx], part_n);
1500 /* Copy the rest in the case of a wrap */
1501 if (part_n < copy_n) {
1502 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1505 /* Update read and other position pointers */
1506 codec_advance_buffer_counters(copy_n);
1508 /* Return the actual amount of data copied to the buffer */
1509 return copy_n;
1510 } /* codec_filebuf_callback */
1512 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1514 size_t short_n, copy_n, buf_rem;
1516 if (!playing)
1518 *realsize = 0;
1519 return NULL;
1522 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1523 if (copy_n == 0)
1525 *realsize = 0;
1526 return NULL;
1529 while (copy_n > CUR_TI->available)
1531 if (!filling)
1533 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1534 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1537 sleep(1);
1538 if (ci.stop_codec || ci.new_track)
1540 *realsize = 0;
1541 return NULL;
1545 /* How much is left at the end of the file buffer before wrap? */
1546 buf_rem = filebuflen - buf_ridx;
1548 /* If we can't satisfy the request without wrapping */
1549 if (buf_rem < copy_n)
1551 /* How short are we? */
1552 short_n = copy_n - buf_rem;
1554 /* If we can fudge it with the guardbuf */
1555 if (short_n < GUARD_BUFSIZE)
1556 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1557 else
1558 copy_n = buf_rem;
1561 *realsize = copy_n;
1563 return (char *)&filebuf[buf_ridx];
1564 } /* codec_request_buffer_callback */
1566 static int get_codec_base_type(int type)
1568 switch (type) {
1569 case AFMT_MPA_L1:
1570 case AFMT_MPA_L2:
1571 case AFMT_MPA_L3:
1572 return AFMT_MPA_L3;
1575 return type;
1578 static void codec_advance_buffer_callback(size_t amount)
1580 if (amount > CUR_TI->available + CUR_TI->filerem)
1581 amount = CUR_TI->available + CUR_TI->filerem;
1583 while (amount > CUR_TI->available && filling)
1584 sleep(1);
1586 if (amount > CUR_TI->available)
1588 intptr_t result = Q_CODEC_REQUEST_FAILED;
1590 if (!ci.stop_codec)
1592 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1593 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1594 ci.curpos + amount);
1597 switch (result)
1599 case Q_CODEC_REQUEST_FAILED:
1600 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1601 ci.stop_codec = true;
1602 return;
1604 case Q_CODEC_REQUEST_COMPLETE:
1605 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1606 return;
1608 default:
1609 LOGFQUEUE("codec |< default");
1610 ci.stop_codec = true;
1611 return;
1615 codec_advance_buffer_counters(amount);
1617 codec_set_offset_callback(ci.curpos);
1620 static void codec_advance_buffer_loc_callback(void *ptr)
1622 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1624 codec_advance_buffer_callback(amount);
1627 /* Copied from mpeg.c. Should be moved somewhere else. */
1628 static int codec_get_file_pos(void)
1630 int pos = -1;
1631 struct mp3entry *id3 = audio_current_track();
1633 if (id3->vbr)
1635 if (id3->has_toc)
1637 /* Use the TOC to find the new position */
1638 unsigned int percent, remainder;
1639 int curtoc, nexttoc, plen;
1641 percent = (id3->elapsed*100)/id3->length;
1642 if (percent > 99)
1643 percent = 99;
1645 curtoc = id3->toc[percent];
1647 if (percent < 99)
1648 nexttoc = id3->toc[percent+1];
1649 else
1650 nexttoc = 256;
1652 pos = (id3->filesize/256)*curtoc;
1654 /* Use the remainder to get a more accurate position */
1655 remainder = (id3->elapsed*100)%id3->length;
1656 remainder = (remainder*100)/id3->length;
1657 plen = (nexttoc - curtoc)*(id3->filesize/256);
1658 pos += (plen/100)*remainder;
1660 else
1662 /* No TOC exists, estimate the new position */
1663 pos = (id3->filesize / (id3->length / 1000)) *
1664 (id3->elapsed / 1000);
1667 else if (id3->bitrate)
1668 pos = id3->elapsed * (id3->bitrate / 8);
1669 else
1670 return -1;
1672 pos += id3->first_frame_offset;
1674 /* Don't seek right to the end of the file so that we can
1675 transition properly to the next song */
1676 if (pos >= (int)(id3->filesize - id3->id3v1len))
1677 pos = id3->filesize - id3->id3v1len - 1;
1679 return pos;
1682 static off_t codec_mp3_get_filepos_callback(int newtime)
1684 off_t newpos;
1686 CUR_TI->id3.elapsed = newtime;
1687 newpos = codec_get_file_pos();
1689 return newpos;
1692 static void codec_seek_complete_callback(void)
1694 logf("seek_complete");
1695 if (pcm_is_paused())
1697 /* If this is not a seamless seek, clear the buffer */
1698 pcmbuf_play_stop();
1699 dsp_configure(DSP_FLUSH, 0);
1701 /* If playback was not 'deliberately' paused, unpause now */
1702 if (!paused)
1703 pcmbuf_pause(false);
1705 ci.seek_time = 0;
1708 static bool codec_seek_buffer_callback(size_t newpos)
1710 int difference;
1712 logf("codec_seek_buffer_callback");
1714 if (newpos >= CUR_TI->filesize)
1715 newpos = CUR_TI->filesize - 1;
1717 difference = newpos - ci.curpos;
1718 if (difference >= 0)
1720 /* Seeking forward */
1721 logf("seek: +%d", difference);
1722 codec_advance_buffer_callback(difference);
1723 return true;
1726 /* Seeking backward */
1727 difference = -difference;
1728 if (ci.curpos - difference < 0)
1729 difference = ci.curpos;
1731 /* We need to reload the song. */
1732 if (newpos < CUR_TI->start_pos)
1734 intptr_t result = Q_CODEC_REQUEST_FAILED;
1736 if (!ci.stop_codec)
1738 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1739 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1740 newpos);
1743 switch (result)
1745 case Q_CODEC_REQUEST_COMPLETE:
1746 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1747 return true;
1749 case Q_CODEC_REQUEST_FAILED:
1750 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1751 ci.stop_codec = true;
1752 return false;
1754 default:
1755 LOGFQUEUE("codec |< default");
1756 return false;
1760 /* Seeking inside buffer space. */
1761 logf("seek: -%d", difference);
1762 CUR_TI->available += difference;
1763 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1764 ci.curpos -= difference;
1766 return true;
1769 static void codec_configure_callback(int setting, intptr_t value)
1771 switch (setting) {
1772 case CODEC_SET_FILEBUF_WATERMARK:
1773 conf_watermark = value;
1774 set_filebuf_watermark(buffer_margin);
1775 break;
1777 case CODEC_SET_FILEBUF_CHUNKSIZE:
1778 conf_filechunk = value;
1779 break;
1781 case CODEC_SET_FILEBUF_PRESEEK:
1782 conf_preseek = value;
1783 break;
1785 default:
1786 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1790 static void codec_track_changed(void)
1792 automatic_skip = false;
1793 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1794 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1797 static void codec_pcmbuf_track_changed_callback(void)
1799 pcmbuf_set_position_callback(NULL);
1800 codec_track_changed();
1803 static void codec_discard_codec_callback(void)
1805 if (CUR_TI->has_codec)
1807 CUR_TI->has_codec = false;
1808 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1811 #if 0
1812 /* Check if a buffer desync has happened, log it and stop playback. */
1813 if (buf_ridx != CUR_TI->buf_idx)
1815 int offset = CUR_TI->buf_idx - buf_ridx;
1816 size_t new_used = FILEBUFUSED - offset;
1818 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1819 logf("Used off:%d",FILEBUFUSED - new_used);
1821 /* This is a fatal internal error and it's not safe to
1822 * continue playback. */
1823 ci.stop_codec = true;
1824 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1826 #endif
1829 static inline void codec_gapless_track_change(void) {
1830 /* callback keeps the progress bar moving while the pcmbuf empties */
1831 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1832 /* set the pcmbuf callback for when the track really changes */
1833 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1836 static inline void codec_crossfade_track_change(void) {
1837 /* Initiate automatic crossfade mode */
1838 pcmbuf_crossfade_init(false);
1839 /* Notify the wps that the track change starts now */
1840 codec_track_changed();
1843 static void codec_track_skip_done(bool was_manual)
1845 int crossfade_mode = global_settings.crossfade;
1847 /* Manual track change (always crossfade or flush audio). */
1848 if (was_manual)
1850 pcmbuf_crossfade_init(true);
1851 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1852 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1854 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1855 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1856 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1858 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1860 if (global_settings.playlist_shuffle)
1861 /* shuffle mode is on, so crossfade: */
1862 codec_crossfade_track_change();
1863 else
1864 /* shuffle mode is off, so do a gapless track change */
1865 codec_gapless_track_change();
1867 else
1868 /* normal crossfade: */
1869 codec_crossfade_track_change();
1871 else
1872 /* normal gapless playback. */
1873 codec_gapless_track_change();
1876 static bool codec_load_next_track(void)
1878 intptr_t result = Q_CODEC_REQUEST_FAILED;
1880 prev_track_elapsed = CUR_TI->id3.elapsed;
1882 if (ci.seek_time)
1883 codec_seek_complete_callback();
1885 #ifdef AB_REPEAT_ENABLE
1886 ab_end_of_track_report();
1887 #endif
1889 logf("Request new track");
1891 if (ci.new_track == 0)
1893 ci.new_track++;
1894 automatic_skip = true;
1897 if (!ci.stop_codec)
1899 trigger_cpu_boost();
1900 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1901 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1904 switch (result)
1906 case Q_CODEC_REQUEST_COMPLETE:
1907 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1908 codec_track_skip_done(!automatic_skip);
1909 return true;
1911 case Q_CODEC_REQUEST_FAILED:
1912 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1913 ci.new_track = 0;
1914 ci.stop_codec = true;
1915 return false;
1917 default:
1918 LOGFQUEUE("codec |< default");
1919 ci.stop_codec = true;
1920 return false;
1924 static bool codec_request_next_track_callback(void)
1926 int prev_codectype;
1928 if (ci.stop_codec || !playing)
1929 return false;
1931 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1933 if (!codec_load_next_track())
1934 return false;
1936 /* Check if the next codec is the same file. */
1937 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1939 logf("New track loaded");
1940 codec_discard_codec_callback();
1941 return true;
1943 else
1945 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1946 return false;
1950 static void codec_thread(void)
1952 struct event ev;
1953 int status;
1954 size_t wrap;
1956 while (1) {
1957 status = 0;
1958 queue_wait(&codec_queue, &ev);
1960 switch (ev.id) {
1961 case Q_CODEC_LOAD_DISK:
1962 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1963 audio_codec_loaded = true;
1964 #ifdef PLAYBACK_VOICE
1965 /* Don't sent messages to voice codec if it's already swapped
1966 out or it will never get this */
1967 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1969 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1970 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1972 mutex_lock(&mutex_codecthread);
1973 #endif
1974 set_current_codec(CODEC_IDX_AUDIO);
1975 ci.stop_codec = false;
1976 status = codec_load_file((const char *)ev.data, &ci);
1977 #ifdef PLAYBACK_VOICE
1978 mutex_unlock(&mutex_codecthread);
1979 #endif
1980 break;
1982 case Q_CODEC_LOAD:
1983 LOGFQUEUE("codec < Q_CODEC_LOAD");
1984 if (!CUR_TI->has_codec) {
1985 logf("Codec slot is empty!");
1986 /* Wait for the pcm buffer to go empty */
1987 while (pcm_is_playing())
1988 yield();
1989 /* This must be set to prevent an infinite loop */
1990 ci.stop_codec = true;
1991 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1992 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1993 break;
1996 audio_codec_loaded = true;
1997 #ifdef PLAYBACK_VOICE
1998 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2000 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2001 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2003 mutex_lock(&mutex_codecthread);
2004 #endif
2005 set_current_codec(CODEC_IDX_AUDIO);
2006 ci.stop_codec = false;
2007 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
2008 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
2009 &filebuf[0], wrap, &ci);
2010 #ifdef PLAYBACK_VOICE
2011 mutex_unlock(&mutex_codecthread);
2012 #endif
2013 break;
2015 #ifdef AUDIO_HAVE_RECORDING
2016 case Q_ENCODER_LOAD_DISK:
2017 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2018 audio_codec_loaded = false; /* Not audio codec! */
2019 #ifdef PLAYBACK_VOICE
2020 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2022 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2023 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2025 mutex_lock(&mutex_codecthread);
2026 #endif
2027 logf("loading encoder");
2028 set_current_codec(CODEC_IDX_AUDIO);
2029 ci.stop_encoder = false;
2030 status = codec_load_file((const char *)ev.data, &ci);
2031 #ifdef PLAYBACK_VOICE
2032 mutex_unlock(&mutex_codecthread);
2033 #endif
2034 logf("encoder stopped");
2035 break;
2036 #endif /* AUDIO_HAVE_RECORDING */
2038 #ifndef SIMULATOR
2039 case SYS_USB_CONNECTED:
2040 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2041 queue_clear(&codec_queue);
2042 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2043 usb_wait_for_disconnect(&codec_queue);
2044 break;
2045 #endif
2047 default:
2048 LOGFQUEUE("codec < default");
2051 if (audio_codec_loaded)
2053 if (ci.stop_codec)
2055 status = CODEC_OK;
2056 if (!playing)
2057 pcmbuf_play_stop();
2060 audio_codec_loaded = false;
2063 switch (ev.id) {
2064 case Q_CODEC_LOAD_DISK:
2065 case Q_CODEC_LOAD:
2066 LOGFQUEUE("codec < Q_CODEC_LOAD");
2067 if (playing)
2069 if (ci.new_track || status != CODEC_OK)
2071 if (!ci.new_track)
2073 logf("Codec failure");
2074 gui_syncsplash(HZ*2, "Codec failure");
2077 if (!codec_load_next_track())
2079 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2080 /* End of playlist */
2081 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2082 break;
2085 else
2087 logf("Codec finished");
2088 if (ci.stop_codec)
2090 /* Wait for the audio to stop playing before
2091 * triggering the WPS exit */
2092 while(pcm_is_playing())
2094 CUR_TI->id3.elapsed =
2095 CUR_TI->id3.length - pcmbuf_get_latency();
2096 sleep(1);
2098 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2099 /* End of playlist */
2100 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2101 break;
2105 if (CUR_TI->has_codec)
2107 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2108 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2110 else
2112 const char *codec_fn =
2113 get_codec_filename(CUR_TI->id3.codectype);
2114 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2115 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2116 (intptr_t)codec_fn);
2119 break;
2121 #ifdef AUDIO_HAVE_RECORDING
2122 case Q_ENCODER_LOAD_DISK:
2123 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2125 if (status == CODEC_OK)
2126 break;
2128 logf("Encoder failure");
2129 gui_syncsplash(HZ*2, "Encoder failure");
2131 if (ci.enc_codec_loaded < 0)
2132 break;
2134 logf("Encoder failed to load");
2135 ci.enc_codec_loaded = -1;
2136 break;
2137 #endif /* AUDIO_HAVE_RECORDING */
2139 default:
2140 LOGFQUEUE("codec < default");
2142 } /* end switch */
2147 /* --- Audio thread --- */
2149 static bool audio_filebuf_is_lowdata(void)
2151 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
2154 static bool audio_have_tracks(void)
2156 return track_ridx != track_widx || CUR_TI->filesize;
2159 static bool audio_have_free_tracks(void)
2161 if (track_widx < track_ridx)
2162 return track_widx + 1 < track_ridx;
2163 else if (track_ridx == 0)
2164 return track_widx < MAX_TRACK - 1;
2166 return true;
2169 int audio_track_count(void)
2171 if (audio_have_tracks())
2173 int relative_track_widx = track_widx;
2175 if (track_ridx > track_widx)
2176 relative_track_widx += MAX_TRACK;
2178 return relative_track_widx - track_ridx + 1;
2181 return 0;
2184 long audio_filebufused(void)
2186 return (long) FILEBUFUSED;
2189 /* Count the data BETWEEN the selected tracks */
2190 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2192 size_t amount = 0;
2193 bool need_wrap = to_track < from_track;
2195 while (1)
2197 if (++from_track >= MAX_TRACK)
2199 from_track -= MAX_TRACK;
2200 need_wrap = false;
2203 if (from_track >= to_track && !need_wrap)
2204 break;
2206 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2208 return amount;
2211 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2213 size_t amount;
2215 /* Start with the remainder of the previously playing track */
2216 amount = tracks[old_track_ridx].filesize - ci.curpos;
2217 /* Then collect all data from tracks in between them */
2218 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2219 logf("bwf:%ldB", (long) amount);
2221 if (amount > FILEBUFUSED)
2222 return false;
2224 /* Wind the buffer to the beginning of the target track or its codec */
2225 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2227 return true;
2230 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2232 /* Available buffer data */
2233 size_t buf_back;
2234 /* Start with the previously playing track's data and our data */
2235 size_t amount;
2237 amount = ci.curpos;
2238 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2240 /* If we're not just resetting the current track */
2241 if (new_track_ridx != old_track_ridx)
2243 /* Need to wind to before the old track's codec and our filesize */
2244 amount += tracks[old_track_ridx].codecsize;
2245 amount += tracks[new_track_ridx].filesize;
2247 /* Rewind the old track to its beginning */
2248 tracks[old_track_ridx].available =
2249 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2252 /* If the codec was ever buffered */
2253 if (tracks[new_track_ridx].codecsize)
2255 /* Add the codec to the needed size */
2256 amount += tracks[new_track_ridx].codecsize;
2257 tracks[new_track_ridx].has_codec = true;
2260 /* Then collect all data from tracks between new and old */
2261 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2263 /* Do we have space to make this skip? */
2264 if (amount > buf_back)
2265 return false;
2267 logf("bwb:%ldB",amount);
2269 /* Rewind the buffer to the beginning of the target track or its codec */
2270 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2272 /* Reset to the beginning of the new track */
2273 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2275 return true;
2278 static void audio_update_trackinfo(void)
2280 ci.filesize = CUR_TI->filesize;
2281 CUR_TI->id3.elapsed = 0;
2282 CUR_TI->id3.offset = 0;
2283 ci.id3 = &CUR_TI->id3;
2284 ci.curpos = 0;
2285 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2288 /* Yield to codecs for as long as possible if they are in need of data
2289 * return true if the caller should break to let the audio thread process
2290 * new events */
2291 static bool audio_yield_codecs(void)
2293 yield();
2295 if (!queue_empty(&audio_queue))
2296 return true;
2298 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2299 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2301 if (filling)
2302 yield();
2303 else
2304 sleep(2);
2306 if (!queue_empty(&audio_queue))
2307 return true;
2310 return false;
2313 static void audio_clear_track_entries(bool clear_unbuffered)
2315 int cur_idx = track_widx;
2316 int last_idx = -1;
2318 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2320 /* Loop over all tracks from write-to-read */
2321 while (1)
2323 cur_idx++;
2324 cur_idx &= MAX_TRACK_MASK;
2326 if (cur_idx == track_ridx)
2327 break;
2329 /* If the track is buffered, conditionally clear/notify,
2330 * otherwise clear the track if that option is selected */
2331 if (tracks[cur_idx].event_sent)
2333 if (last_idx >= 0)
2335 /* If there is an unbuffer callback, call it, otherwise,
2336 * just clear the track */
2337 if (track_unbuffer_callback)
2338 track_unbuffer_callback(&tracks[last_idx].id3, false);
2340 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2342 last_idx = cur_idx;
2344 else if (clear_unbuffered)
2345 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2348 /* We clear the previous instance of a buffered track throughout
2349 * the above loop to facilitate 'last' detection. Clear/notify
2350 * the last track here */
2351 if (last_idx >= 0)
2353 if (track_unbuffer_callback)
2354 track_unbuffer_callback(&tracks[last_idx].id3, true);
2355 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2359 /* FIXME: This code should be made more generic and move to metadata.c */
2360 static void audio_strip_tags(void)
2362 int i;
2363 static const unsigned char tag[] = "TAG";
2364 static const unsigned char apetag[] = "APETAGEX";
2365 size_t tag_idx;
2366 size_t cur_idx;
2367 size_t len, version;
2369 tag_idx = RINGBUF_SUB(buf_widx, 128);
2371 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2373 cur_idx = tag_idx;
2374 for(i = 0;i < 3;i++)
2376 if(filebuf[cur_idx] != tag[i])
2377 goto strip_ape_tag;
2379 cur_idx = RINGBUF_ADD(cur_idx, 1);
2382 /* Skip id3v1 tag */
2383 logf("Skipping ID3v1 tag");
2384 buf_widx = tag_idx;
2385 tracks[track_widx].available -= 128;
2386 tracks[track_widx].filesize -= 128;
2389 strip_ape_tag:
2390 /* Check for APE tag (look for the APE tag footer) */
2391 tag_idx = RINGBUF_SUB(buf_widx, 32);
2393 if (FILEBUFUSED > 32 && tag_idx > buf_ridx)
2395 cur_idx = tag_idx;
2396 for(i = 0;i < 8;i++)
2398 if(filebuf[cur_idx] != apetag[i])
2399 return;
2401 cur_idx = RINGBUF_ADD(cur_idx, 1);
2404 /* Read the version and length from the footer */
2405 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2406 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2407 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2408 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2409 if (version == 2000)
2410 len += 32; /* APEv2 has a 32 byte header */
2412 /* Skip APE tag */
2413 if (FILEBUFUSED > len)
2415 logf("Skipping APE tag (%ldB)", len);
2416 buf_widx = RINGBUF_SUB(buf_widx, len);
2417 tracks[track_widx].available -= len;
2418 tracks[track_widx].filesize -= len;
2423 /* Returns true if a whole file is read, false otherwise */
2424 static bool audio_read_file(size_t minimum)
2426 bool ret_val = false;
2428 /* If we're called and no file is open, this is an error */
2429 if (current_fd < 0)
2431 logf("Bad fd in arf");
2432 /* Give some hope of miraculous recovery by forcing a track reload */
2433 tracks[track_widx].filesize = 0;
2434 /* Stop this buffering run */
2435 return ret_val;
2438 trigger_cpu_boost();
2439 while (tracks[track_widx].filerem > 0)
2441 size_t copy_n;
2442 int overlap;
2443 int rc;
2445 /* copy_n is the largest chunk that is safe to read */
2446 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2448 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2449 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2450 break;
2452 /* rc is the actual amount read */
2453 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2455 if (rc < 0)
2457 logf("File ended %ldB early", tracks[track_widx].filerem);
2458 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2459 tracks[track_widx].filerem = 0;
2460 break;
2463 /* How much of the playing track did we overwrite */
2464 if (buf_widx == CUR_TI->buf_idx)
2466 /* Special handling; zero or full overlap? */
2467 if (track_widx == track_ridx && CUR_TI->available == 0)
2468 overlap = 0;
2469 else
2470 overlap = rc;
2472 else
2473 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2475 if ((unsigned)rc > tracks[track_widx].filerem)
2477 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2478 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2479 tracks[track_widx].filerem = rc;
2482 /* Advance buffer */
2483 buf_widx = RINGBUF_ADD(buf_widx, rc);
2484 tracks[track_widx].available += rc;
2485 tracks[track_widx].filerem -= rc;
2487 /* If we write into the playing track, adjust it's buffer info */
2488 if (overlap > 0)
2490 CUR_TI->buf_idx += overlap;
2491 CUR_TI->start_pos += overlap;
2494 /* For a rebuffer, fill at least this minimum */
2495 if (minimum > (unsigned)rc)
2496 minimum -= rc;
2497 /* Let the codec process up to the watermark */
2498 /* Break immediately if this is a quick buffer, or there is an event */
2499 else if (minimum || audio_yield_codecs())
2501 /* Exit quickly, but don't stop the overall buffering process */
2502 ret_val = true;
2503 break;
2507 if (tracks[track_widx].filerem == 0)
2509 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2510 close(current_fd);
2511 current_fd = -1;
2512 audio_strip_tags();
2514 track_widx++;
2515 track_widx &= MAX_TRACK_MASK;
2517 tracks[track_widx].filesize = 0;
2518 return true;
2520 else
2522 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2523 tracks[track_widx].filesize - tracks[track_widx].filerem);
2524 return ret_val;
2528 static bool audio_loadcodec(bool start_play)
2530 size_t size = 0;
2531 int fd;
2532 int rc;
2533 size_t copy_n;
2534 int prev_track;
2535 char codec_path[MAX_PATH]; /* Full path to codec */
2537 const char * codec_fn =
2538 get_codec_filename(tracks[track_widx].id3.codectype);
2539 if (codec_fn == NULL)
2540 return false;
2542 tracks[track_widx].has_codec = false;
2544 if (start_play)
2546 /* Load the codec directly from disk and save some memory. */
2547 track_ridx = track_widx;
2548 ci.filesize = CUR_TI->filesize;
2549 ci.id3 = &CUR_TI->id3;
2550 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2551 ci.curpos = 0;
2552 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2553 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2554 return true;
2556 else
2558 /* If we already have another track than this one buffered */
2559 if (track_widx != track_ridx)
2561 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2563 /* If the previous codec is the same as this one, there is no need
2564 * to put another copy of it on the file buffer */
2565 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2566 get_codec_base_type(tracks[prev_track].id3.codectype)
2567 && audio_codec_loaded)
2569 logf("Reusing prev. codec");
2570 return true;
2575 codec_get_full_path(codec_path, codec_fn);
2577 fd = open(codec_path, O_RDONLY);
2578 if (fd < 0)
2580 logf("Codec doesn't exist!");
2581 return false;
2584 tracks[track_widx].codecsize = filesize(fd);
2586 /* Never load a partial codec */
2587 if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0)
2589 logf("Not enough space");
2590 close(fd);
2591 return false;
2594 while (size < tracks[track_widx].codecsize)
2596 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2597 rc = read(fd, &filebuf[buf_widx], copy_n);
2598 if (rc < 0)
2600 close(fd);
2601 /* This is an error condition, likely the codec file is corrupt */
2602 logf("Partial codec loaded");
2603 /* Must undo the buffer write of the partial codec */
2604 buf_widx = RINGBUF_SUB(buf_widx, size);
2605 tracks[track_widx].codecsize = 0;
2606 return false;
2609 buf_widx = RINGBUF_ADD(buf_widx, rc);
2611 size += rc;
2614 tracks[track_widx].has_codec = true;
2616 close(fd);
2617 logf("Done: %ldB", size);
2619 return true;
2622 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2623 static void audio_set_elapsed(struct mp3entry* id3)
2625 unsigned long offset = id3->offset > id3->first_frame_offset ?
2626 id3->offset - id3->first_frame_offset : 0;
2628 if ( id3->vbr ) {
2629 if ( id3->has_toc ) {
2630 /* calculate elapsed time using TOC */
2631 int i;
2632 unsigned int remainder, plen, relpos, nextpos;
2634 /* find wich percent we're at */
2635 for (i=0; i<100; i++ )
2636 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2637 break;
2639 i--;
2640 if (i < 0)
2641 i = 0;
2643 relpos = id3->toc[i];
2645 if (i < 99)
2646 nextpos = id3->toc[i+1];
2647 else
2648 nextpos = 256;
2650 remainder = offset - (relpos * (id3->filesize / 256));
2652 /* set time for this percent (divide before multiply to prevent
2653 overflow on long files. loss of precision is negligible on
2654 short files) */
2655 id3->elapsed = i * (id3->length / 100);
2657 /* calculate remainder time */
2658 plen = (nextpos - relpos) * (id3->filesize / 256);
2659 id3->elapsed += (((remainder * 100) / plen) *
2660 (id3->length / 10000));
2662 else {
2663 /* no TOC exists. set a rough estimate using average bitrate */
2664 int tpk = id3->length /
2665 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2666 1024);
2667 id3->elapsed = offset / 1024 * tpk;
2670 else
2672 /* constant bitrate, use exact calculation */
2673 if (id3->bitrate != 0)
2674 id3->elapsed = offset / (id3->bitrate / 8);
2678 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2680 char *trackname;
2681 off_t size;
2682 char msgbuf[80];
2684 /* Stop buffer filling if there is no free track entries.
2685 Don't fill up the last track entry (we wan't to store next track
2686 metadata there). */
2687 if (!audio_have_free_tracks())
2689 logf("No free tracks");
2690 return false;
2693 if (current_fd >= 0)
2695 logf("Nonzero fd in alt");
2696 close(current_fd);
2697 current_fd = -1;
2700 last_peek_offset++;
2701 peek_again:
2702 logf("Buffering track:%d/%d", track_widx, track_ridx);
2703 /* Get track name from current playlist read position. */
2704 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2706 /* Handle broken playlists. */
2707 current_fd = open(trackname, O_RDONLY);
2708 if (current_fd < 0)
2710 logf("Open failed");
2711 /* Skip invalid entry from playlist. */
2712 playlist_skip_entry(NULL, last_peek_offset);
2714 else
2715 break;
2718 if (!trackname)
2720 logf("End-of-playlist");
2721 playlist_end = true;
2722 return false;
2725 /* Initialize track entry. */
2726 size = filesize(current_fd);
2727 tracks[track_widx].filerem = size;
2728 tracks[track_widx].filesize = size;
2729 tracks[track_widx].available = 0;
2731 /* Set default values */
2732 if (start_play)
2734 int last_codec = current_codec;
2736 set_current_codec(CODEC_IDX_AUDIO);
2737 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2738 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2739 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2740 dsp_configure(DSP_RESET, 0);
2741 set_current_codec(last_codec);
2744 /* Get track metadata if we don't already have it. */
2745 if (!tracks[track_widx].taginfo_ready)
2747 if (get_metadata(&(tracks[track_widx].id3),current_fd,trackname,v1first))
2749 tracks[track_widx].taginfo_ready = true;
2750 if (start_play)
2752 track_changed = true;
2753 playlist_update_resume_info(audio_current_track());
2756 else
2758 logf("mde:%s!",trackname);
2760 /* Set filesize to zero to indicate no file was loaded. */
2761 tracks[track_widx].filesize = 0;
2762 tracks[track_widx].filerem = 0;
2763 close(current_fd);
2764 current_fd = -1;
2766 /* Skip invalid entry from playlist. */
2767 playlist_skip_entry(NULL, last_peek_offset);
2768 tracks[track_widx].taginfo_ready = false;
2769 goto peek_again;
2774 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2776 char cuepath[MAX_PATH];
2778 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2780 if (look_for_cuesheet_file(trackname, cuepath) &&
2781 parse_cuesheet(cuepath, cue))
2783 strcpy((cue)->audio_filename, trackname);
2784 if (start_play)
2785 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2789 /* Load the codec. */
2790 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2791 if (!audio_loadcodec(start_play))
2793 /* Set filesize to zero to indicate no file was loaded. */
2794 tracks[track_widx].filesize = 0;
2795 tracks[track_widx].filerem = 0;
2796 close(current_fd);
2797 current_fd = -1;
2799 if (tracks[track_widx].codecsize)
2801 /* No space for codec on buffer, not an error */
2802 tracks[track_widx].codecsize = 0;
2803 return false;
2806 /* This is an error condition, either no codec was found, or reading
2807 * the codec file failed part way through, either way, skip the track */
2808 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2809 /* We should not use gui_syncplash from audio thread! */
2810 gui_syncsplash(HZ*2, msgbuf);
2811 /* Skip invalid entry from playlist. */
2812 playlist_skip_entry(NULL, last_peek_offset);
2813 tracks[track_widx].taginfo_ready = false;
2814 goto peek_again;
2817 tracks[track_widx].start_pos = 0;
2818 set_filebuf_watermark(buffer_margin);
2819 tracks[track_widx].id3.elapsed = 0;
2821 if (offset > 0)
2823 switch (tracks[track_widx].id3.codectype) {
2824 case AFMT_MPA_L1:
2825 case AFMT_MPA_L2:
2826 case AFMT_MPA_L3:
2827 lseek(current_fd, offset, SEEK_SET);
2828 tracks[track_widx].id3.offset = offset;
2829 audio_set_elapsed(&tracks[track_widx].id3);
2830 tracks[track_widx].filerem = size - offset;
2831 ci.curpos = offset;
2832 tracks[track_widx].start_pos = offset;
2833 break;
2835 case AFMT_WAVPACK:
2836 lseek(current_fd, offset, SEEK_SET);
2837 tracks[track_widx].id3.offset = offset;
2838 tracks[track_widx].id3.elapsed =
2839 tracks[track_widx].id3.length / 2;
2840 tracks[track_widx].filerem = size - offset;
2841 ci.curpos = offset;
2842 tracks[track_widx].start_pos = offset;
2843 break;
2845 case AFMT_OGG_VORBIS:
2846 case AFMT_SPEEX:
2847 case AFMT_FLAC:
2848 case AFMT_PCM_WAV:
2849 case AFMT_A52:
2850 case AFMT_AAC:
2851 case AFMT_MPC:
2852 case AFMT_APE:
2853 tracks[track_widx].id3.offset = offset;
2854 break;
2858 logf("alt:%s", trackname);
2859 tracks[track_widx].buf_idx = buf_widx;
2861 return audio_read_file(rebuffer);
2864 static bool audio_read_next_metadata(void)
2866 int fd;
2867 char *trackname;
2868 int next_idx;
2869 int status;
2871 next_idx = track_widx;
2872 if (tracks[next_idx].taginfo_ready)
2874 next_idx++;
2875 next_idx &= MAX_TRACK_MASK;
2877 if (tracks[next_idx].taginfo_ready)
2878 return true;
2881 trackname = playlist_peek(last_peek_offset + 1);
2882 if (!trackname)
2883 return false;
2885 fd = open(trackname, O_RDONLY);
2886 if (fd < 0)
2887 return false;
2889 status = get_metadata(&(tracks[next_idx].id3),fd,trackname,v1first);
2890 /* Preload the glyphs in the tags */
2891 if (status)
2893 tracks[next_idx].taginfo_ready = true;
2894 if (tracks[next_idx].id3.title)
2895 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2896 if (tracks[next_idx].id3.artist)
2897 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2898 if (tracks[next_idx].id3.album)
2899 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2901 close(fd);
2903 return status;
2906 /* Send callback events to notify about new tracks. */
2907 static void audio_generate_postbuffer_events(void)
2909 int cur_idx;
2910 int last_idx = -1;
2912 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2914 if (audio_have_tracks())
2916 cur_idx = track_ridx;
2918 while (1) {
2919 if (!tracks[cur_idx].event_sent)
2921 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2923 /* Mark the event 'sent' even if we don't really send one */
2924 tracks[last_idx].event_sent = true;
2925 if (track_buffer_callback)
2926 track_buffer_callback(&tracks[last_idx].id3, false);
2928 last_idx = cur_idx;
2930 if (cur_idx == track_widx)
2931 break;
2932 cur_idx++;
2933 cur_idx &= MAX_TRACK_MASK;
2936 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2938 tracks[last_idx].event_sent = true;
2939 if (track_buffer_callback)
2940 track_buffer_callback(&tracks[last_idx].id3, true);
2945 static bool audio_initialize_buffer_fill(bool clear_tracks)
2947 /* Don't initialize if we're already initialized */
2948 if (filling)
2949 return true;
2951 logf("Starting buffer fill");
2953 /* Set the filling flag true before calling audio_clear_tracks as that
2954 * function can yield and we start looping. */
2955 filling = true;
2957 if (clear_tracks)
2958 audio_clear_track_entries(false);
2960 /* Save the current resume position once. */
2961 playlist_update_resume_info(audio_current_track());
2963 return true;
2966 static void audio_fill_file_buffer(
2967 bool start_play, bool rebuffer, size_t offset)
2969 bool had_next_track = audio_next_track() != NULL;
2970 bool continue_buffering;
2972 /* Must reset the buffer before use if trashed or voice only - voice
2973 file size shouldn't have changed so we can go straight from
2974 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2975 if (buffer_state != BUFFER_STATE_INITIALIZED)
2976 audio_reset_buffer();
2978 if (!audio_initialize_buffer_fill(!start_play))
2979 return ;
2981 /* If we have a partially buffered track, continue loading,
2982 * otherwise load a new track */
2983 if (tracks[track_widx].filesize > 0)
2984 continue_buffering = audio_read_file(rebuffer);
2985 else
2986 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2988 if (!had_next_track && audio_next_track())
2989 track_changed = true;
2991 /* If we're done buffering */
2992 if (!continue_buffering)
2994 audio_read_next_metadata();
2996 audio_generate_postbuffer_events();
2997 filling = false;
2999 #ifndef SIMULATOR
3000 ata_sleep();
3001 #endif
3005 static void audio_rebuffer(void)
3007 logf("Forcing rebuffer");
3009 /* Stop in progress fill, and clear open file descriptor */
3010 if (current_fd >= 0)
3012 close(current_fd);
3013 current_fd = -1;
3015 filling = false;
3017 /* Reset buffer and track pointers */
3018 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3019 track_widx = track_ridx;
3020 audio_clear_track_entries(true);
3021 CUR_TI->available = 0;
3023 /* Fill the buffer */
3024 last_peek_offset = -1;
3025 CUR_TI->filesize = 0;
3026 CUR_TI->start_pos = 0;
3027 ci.curpos = 0;
3029 if (!CUR_TI->taginfo_ready)
3030 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
3032 audio_fill_file_buffer(false, true, 0);
3035 static int audio_check_new_track(void)
3037 int track_count = audio_track_count();
3038 int old_track_ridx = track_ridx;
3039 bool forward;
3041 if (dir_skip)
3043 dir_skip = false;
3044 if (playlist_next_dir(ci.new_track))
3046 ci.new_track = 0;
3047 CUR_TI->taginfo_ready = false;
3048 audio_rebuffer();
3049 goto skip_done;
3051 else
3053 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3054 return Q_CODEC_REQUEST_FAILED;
3058 if (new_playlist)
3059 ci.new_track = 0;
3061 /* If the playlist isn't that big */
3062 if (!playlist_check(ci.new_track))
3064 if (ci.new_track >= 0)
3066 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3067 return Q_CODEC_REQUEST_FAILED;
3069 /* Find the beginning backward if the user over-skips it */
3070 while (!playlist_check(++ci.new_track))
3071 if (ci.new_track >= 0)
3073 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3074 return Q_CODEC_REQUEST_FAILED;
3077 /* Update the playlist */
3078 last_peek_offset -= ci.new_track;
3080 if (playlist_next(ci.new_track) < 0)
3082 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3083 return Q_CODEC_REQUEST_FAILED;
3086 if (new_playlist)
3088 ci.new_track = 1;
3089 new_playlist = false;
3092 /* Save the old track */
3093 prev_ti = CUR_TI;
3095 /* Move to the new track */
3096 track_ridx += ci.new_track;
3097 track_ridx &= MAX_TRACK_MASK;
3099 if (automatic_skip)
3100 playlist_end = false;
3102 track_changed = !automatic_skip;
3104 /* If it is not safe to even skip this many track entries */
3105 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3107 ci.new_track = 0;
3108 CUR_TI->taginfo_ready = false;
3109 audio_rebuffer();
3110 goto skip_done;
3113 forward = ci.new_track > 0;
3114 ci.new_track = 0;
3116 /* If the target track is clearly not in memory */
3117 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3119 audio_rebuffer();
3120 goto skip_done;
3123 /* The track may be in memory, see if it really is */
3124 if (forward)
3126 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3127 audio_rebuffer();
3129 else
3131 int cur_idx = track_ridx;
3132 bool taginfo_ready = true;
3133 bool wrap = track_ridx > old_track_ridx;
3135 while (1)
3137 cur_idx++;
3138 cur_idx &= MAX_TRACK_MASK;
3139 if (!(wrap || cur_idx < old_track_ridx))
3140 break;
3142 /* If we hit a track in between without valid tag info, bail */
3143 if (!tracks[cur_idx].taginfo_ready)
3145 taginfo_ready = false;
3146 break;
3149 tracks[cur_idx].available = tracks[cur_idx].filesize;
3150 if (tracks[cur_idx].codecsize)
3151 tracks[cur_idx].has_codec = true;
3153 if (taginfo_ready)
3155 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3156 audio_rebuffer();
3158 else
3160 CUR_TI->taginfo_ready = false;
3161 audio_rebuffer();
3165 skip_done:
3166 audio_update_trackinfo();
3167 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3168 return Q_CODEC_REQUEST_COMPLETE;
3171 static int audio_rebuffer_and_seek(size_t newpos)
3173 size_t real_preseek;
3174 int fd;
3175 char *trackname;
3177 /* (Re-)open current track's file handle. */
3178 trackname = playlist_peek(0);
3179 fd = open(trackname, O_RDONLY);
3180 if (fd < 0)
3182 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3183 return Q_CODEC_REQUEST_FAILED;
3186 if (current_fd >= 0)
3187 close(current_fd);
3188 current_fd = fd;
3190 playlist_end = false;
3192 ci.curpos = newpos;
3194 /* Clear codec buffer. */
3195 track_widx = track_ridx;
3196 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3198 last_peek_offset = 0;
3199 filling = false;
3200 audio_initialize_buffer_fill(true);
3202 /* This may have been tweaked by the id3v1 code */
3203 CUR_TI->filesize=filesize(fd);
3204 if (newpos > conf_preseek)
3206 CUR_TI->start_pos = newpos - conf_preseek;
3207 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3208 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3209 real_preseek = conf_preseek;
3211 else
3213 CUR_TI->start_pos = 0;
3214 CUR_TI->filerem = CUR_TI->filesize;
3215 real_preseek = newpos;
3218 CUR_TI->available = 0;
3220 audio_read_file(real_preseek);
3222 /* Account for the data we just read that is 'behind' us now */
3223 CUR_TI->available -= real_preseek;
3225 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3227 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3228 return Q_CODEC_REQUEST_COMPLETE;
3231 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3232 bool last_track))
3234 track_buffer_callback = handler;
3237 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3238 bool last_track))
3240 track_unbuffer_callback = handler;
3243 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3245 track_changed_callback = handler;
3248 unsigned long audio_prev_elapsed(void)
3250 return prev_track_elapsed;
3253 static void audio_stop_codec_flush(void)
3255 ci.stop_codec = true;
3256 pcmbuf_pause(true);
3258 while (audio_codec_loaded)
3259 yield();
3261 /* If the audio codec is not loaded any more, and the audio is still
3262 * playing, it is now and _only_ now safe to call this function from the
3263 * audio thread */
3264 if (pcm_is_playing())
3265 pcmbuf_play_stop();
3266 pcmbuf_pause(paused);
3269 static void audio_stop_playback(void)
3271 /* If we were playing, save resume information */
3272 if (playing)
3274 struct mp3entry *id3 = NULL;
3276 if (!playlist_end || !ci.stop_codec)
3278 /* Set this early, the outside code yields and may allow the codec
3279 to try to wait for a reply on a buffer wait */
3280 ci.stop_codec = true;
3281 id3 = audio_current_track();
3284 /* Save the current playing spot, or NULL if the playlist has ended */
3285 playlist_update_resume_info(id3);
3287 prev_track_elapsed = CUR_TI->id3.elapsed;
3289 /* Increment index so runtime info is saved in audio_clear_track_entries().
3290 * Done here, as audio_stop_playback() may be called more than once.
3291 * Don't update runtime unless playback is stopped because of end of playlist.
3292 * Updating runtime when manually stopping a tracks, can destroy autoscores
3293 * and playcounts.
3295 if (playlist_end)
3297 track_ridx++;
3298 track_ridx &= MAX_TRACK_MASK;
3302 filling = false;
3303 paused = false;
3304 audio_stop_codec_flush();
3305 playing = false;
3307 if (current_fd >= 0)
3309 close(current_fd);
3310 current_fd = -1;
3313 /* Mark all entries null. */
3314 audio_clear_track_entries(false);
3317 static void audio_play_start(size_t offset)
3319 #if INPUT_SRC_CAPS != 0
3320 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3321 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3322 #endif
3324 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3325 paused = false;
3326 audio_stop_codec_flush();
3328 track_changed = true;
3329 playlist_end = false;
3331 playing = true;
3333 ci.new_track = 0;
3334 ci.seek_time = 0;
3335 wps_offset = 0;
3337 if (current_fd >= 0)
3339 close(current_fd);
3340 current_fd = -1;
3343 sound_set_volume(global_settings.volume);
3344 track_widx = track_ridx = 0;
3345 buf_ridx = buf_widx = 0;
3347 /* Mark all entries null. */
3348 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3350 last_peek_offset = -1;
3352 /* Officially playing */
3353 queue_reply(&audio_queue, 1);
3355 audio_fill_file_buffer(true, false, offset);
3357 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3358 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3362 /* Invalidates all but currently playing track. */
3363 static void audio_invalidate_tracks(void)
3365 if (audio_have_tracks())
3367 last_peek_offset = 0;
3368 playlist_end = false;
3369 track_widx = track_ridx;
3371 /* Mark all other entries null (also buffered wrong metadata). */
3372 audio_clear_track_entries(true);
3374 /* If the current track is fully buffered, advance the write pointer */
3375 if (tracks[track_widx].filerem == 0)
3376 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3378 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3380 audio_read_next_metadata();
3384 static void audio_new_playlist(void)
3386 /* Prepare to start a new fill from the beginning of the playlist */
3387 last_peek_offset = -1;
3388 if (audio_have_tracks())
3390 if (paused)
3391 skipped_during_pause = true;
3392 playlist_end = false;
3393 track_widx = track_ridx;
3394 audio_clear_track_entries(true);
3396 track_widx++;
3397 track_widx &= MAX_TRACK_MASK;
3399 /* Stop reading the current track */
3400 CUR_TI->filerem = 0;
3401 close(current_fd);
3402 current_fd = -1;
3404 /* Mark the current track as invalid to prevent skipping back to it */
3405 CUR_TI->taginfo_ready = false;
3407 /* Invalidate the buffer other than the playing track */
3408 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3411 /* Signal the codec to initiate a track change forward */
3412 new_playlist = true;
3413 ci.new_track = 1;
3415 /* Officially playing */
3416 queue_reply(&audio_queue, 1);
3418 audio_fill_file_buffer(false, true, 0);
3421 static void audio_initiate_track_change(long direction)
3423 playlist_end = false;
3424 ci.new_track += direction;
3425 wps_offset -= direction;
3426 if (paused)
3427 skipped_during_pause = true;
3430 static void audio_initiate_dir_change(long direction)
3432 playlist_end = false;
3433 dir_skip = true;
3434 ci.new_track = direction;
3435 if (paused)
3436 skipped_during_pause = true;
3440 * Layout audio buffer as follows - iram buffer depends on target:
3441 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3443 static void audio_reset_buffer(void)
3445 /* see audio_get_recording_buffer if this is modified */
3446 logf("audio_reset_buffer");
3448 /* If the setup of anything allocated before the file buffer is
3449 changed, do check the adjustments after the buffer_alloc call
3450 as it will likely be affected and need sliding over */
3452 /* Initially set up file buffer as all space available */
3453 malloc_buf = audiobuf + talk_get_bufsize();
3454 /* Align the malloc buf to line size. Especially important to cf
3455 targets that do line reads/writes. */
3456 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3457 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3458 filebuflen = audiobufend - filebuf;
3460 /* Allow for codec swap space at end of audio buffer */
3461 if (talk_voice_required())
3463 /* Layout of swap buffer:
3464 * #ifdef IRAM_STEAL (dedicated iram_buf):
3465 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3466 * #else:
3467 * audiobuf...|dram_buf|iram_buf|audiobufend
3469 #ifdef PLAYBACK_VOICE
3470 /* Check for an absolutely nasty situation which should never,
3471 ever happen - frankly should just panic */
3472 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3474 logf("buffer reset with voice swapped");
3476 /* line align length which line aligns the calculations below since
3477 all sizes are also at least line aligned - needed for memswap128 */
3478 filebuflen &= ~15;
3479 #ifdef IRAM_STEAL
3480 filebuflen -= CODEC_SIZE;
3481 #else
3482 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3483 #endif
3484 /* Allocate buffers for swapping voice <=> audio */
3485 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3486 and out of the way of buffer usage or else a call to audio_get_buffer
3487 and subsequent buffer use might trash the swap space. A plugin
3488 initializing IRAM after getting the full buffer would present similar
3489 problem. Options include: failing the request if the other buffer
3490 has been obtained already or never allowing use of the voice IRAM
3491 buffer within the audio buffer. Using buffer_alloc basically
3492 implements the second in a more convenient way. */
3493 dram_buf = filebuf + filebuflen;
3495 #ifdef IRAM_STEAL
3496 /* Allocate voice IRAM swap buffer once */
3497 if (iram_buf == NULL)
3499 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3500 /* buffer_alloc moves audiobuf; this is safe because only the end
3501 * has been touched so far in this function and the address of
3502 * filebuf + filebuflen is not changed */
3503 malloc_buf += CODEC_IRAM_SIZE;
3504 filebuf += CODEC_IRAM_SIZE;
3505 filebuflen -= CODEC_IRAM_SIZE;
3507 #else
3508 /* Allocate iram_buf after dram_buf */
3509 iram_buf = dram_buf + CODEC_SIZE;
3510 #endif /* IRAM_STEAL */
3511 #endif /* PLAYBACK_VOICE */
3513 else
3515 #ifdef PLAYBACK_VOICE
3516 /* No swap buffers needed */
3517 iram_buf = NULL;
3518 dram_buf = NULL;
3519 #endif
3522 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3523 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3525 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3526 will already be line aligned */
3527 filebuflen &= ~3;
3529 /* Set the high watermark as 75% full...or 25% empty :) */
3530 #if MEM > 8
3531 high_watermark = 3*filebuflen / 4;
3532 #endif
3534 /* Clear any references to the file buffer */
3535 buffer_state = BUFFER_STATE_INITIALIZED;
3537 #ifdef ROCKBOX_HAS_LOGF
3538 /* Make sure everything adds up - yes, some info is a bit redundant but
3539 aids viewing and the sumation of certain variables should add up to
3540 the location of others. */
3542 size_t pcmbufsize;
3543 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3544 logf("mabuf: %08X", (unsigned)malloc_buf);
3545 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3546 logf("fbuf: %08X", (unsigned)filebuf);
3547 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3548 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3549 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3550 logf("pcmb: %08X", (unsigned)pcmbuf);
3551 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3552 if (dram_buf)
3554 logf("dramb: %08X", (unsigned)dram_buf);
3555 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3557 if (iram_buf)
3559 logf("iramb: %08X", (unsigned)iram_buf);
3560 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3563 #endif
3566 #if MEM > 8
3567 /* we dont want this rebuffering on targets with little ram
3568 because the disk may never spin down */
3569 static bool ata_fillbuffer_callback(void)
3571 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3572 return true;
3574 #endif
3576 static void audio_thread(void)
3578 struct event ev;
3580 pcm_postinit();
3582 #ifdef PLAYBACK_VOICE
3583 /* Unlock mutex that init stage locks before creating this thread */
3584 mutex_unlock(&mutex_codecthread);
3586 /* Buffers must be set up by now - should panic - really */
3587 if (buffer_state != BUFFER_STATE_INITIALIZED)
3589 logf("audio_thread start: no buffer");
3592 /* Have to wait for voice to load up or else the codec swap will be
3593 invalid when an audio codec is loaded */
3594 wait_for_voice_swap_in();
3595 #endif
3597 while (1)
3599 intptr_t result = 0;
3601 if (filling)
3603 queue_wait_w_tmo(&audio_queue, &ev, 0);
3604 if (ev.id == SYS_TIMEOUT)
3605 ev.id = Q_AUDIO_FILL_BUFFER;
3607 else
3609 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3610 #if MEM > 8
3611 if (playing && (ev.id == SYS_TIMEOUT) &&
3612 (FILEBUFUSED < high_watermark))
3613 register_ata_idle_func(ata_fillbuffer_callback);
3614 #endif
3617 switch (ev.id) {
3618 #if MEM > 8
3619 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3620 /* only fill if the disk is still spining */
3621 #ifndef SIMULATOR
3622 if (!ata_disk_is_active())
3623 break;
3624 #endif
3625 #endif /* MEM > 8 */
3626 /* else fall through to Q_AUDIO_FILL_BUFFER */
3627 case Q_AUDIO_FILL_BUFFER:
3628 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3629 if (!filling)
3630 if (!playing || playlist_end || ci.stop_codec)
3631 break;
3632 audio_fill_file_buffer(false, false, 0);
3633 break;
3635 case Q_AUDIO_PLAY:
3636 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3637 if (playing && ev.data <= 0)
3638 audio_new_playlist();
3639 else
3641 audio_stop_playback();
3642 audio_play_start((size_t)ev.data);
3644 break;
3646 case Q_AUDIO_STOP:
3647 LOGFQUEUE("audio < Q_AUDIO_STOP");
3648 if (playing)
3649 audio_stop_playback();
3650 if (ev.data != 0)
3651 queue_clear(&audio_queue);
3652 break;
3654 case Q_AUDIO_PAUSE:
3655 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3656 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3657 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3658 skipped_during_pause = false;
3659 if (!playing)
3660 break;
3661 pcmbuf_pause((bool)ev.data);
3662 paused = (bool)ev.data;
3663 break;
3665 case Q_AUDIO_SKIP:
3666 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3667 audio_initiate_track_change((long)ev.data);
3668 break;
3670 case Q_AUDIO_PRE_FF_REWIND:
3671 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3672 if (!playing)
3673 break;
3674 pcmbuf_pause(true);
3675 break;
3677 case Q_AUDIO_FF_REWIND:
3678 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3679 if (!playing)
3680 break;
3681 ci.seek_time = (long)ev.data+1;
3682 break;
3684 case Q_AUDIO_REBUFFER_SEEK:
3685 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3686 result = audio_rebuffer_and_seek(ev.data);
3687 break;
3689 case Q_AUDIO_CHECK_NEW_TRACK:
3690 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3691 result = audio_check_new_track();
3692 break;
3694 case Q_AUDIO_DIR_SKIP:
3695 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3696 playlist_end = false;
3697 audio_initiate_dir_change(ev.data);
3698 break;
3700 case Q_AUDIO_FLUSH:
3701 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3702 audio_invalidate_tracks();
3703 break;
3705 case Q_AUDIO_TRACK_CHANGED:
3706 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3707 if (track_changed_callback)
3708 track_changed_callback(&CUR_TI->id3);
3709 track_changed = true;
3710 playlist_update_resume_info(audio_current_track());
3711 break;
3713 #ifndef SIMULATOR
3714 case SYS_USB_CONNECTED:
3715 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3716 if (playing)
3717 audio_stop_playback();
3718 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3719 usb_wait_for_disconnect(&audio_queue);
3720 break;
3721 #endif
3723 case SYS_TIMEOUT:
3724 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3725 break;
3727 default:
3728 LOGFQUEUE("audio < default");
3729 } /* end switch */
3731 queue_reply(&audio_queue, result);
3732 } /* end while */
3735 #ifdef ROCKBOX_HAS_LOGF
3736 static void audio_test_track_changed_event(struct mp3entry *id3)
3738 (void)id3;
3740 logf("tce:%s", id3->path);
3742 #endif
3744 /* Initialize the audio system - called from init() in main.c.
3745 * Last function because of all the references to internal symbols
3747 void audio_init(void)
3749 #ifdef PLAYBACK_VOICE
3750 static bool voicetagtrue = true;
3751 static struct mp3entry id3_voice;
3752 #endif
3754 /* Can never do this twice */
3755 if (audio_is_initialized)
3757 logf("audio: already initialized");
3758 return;
3761 logf("audio: initializing");
3763 /* Initialize queues before giving control elsewhere in case it likes
3764 to send messages. Thread creation will be delayed however so nothing
3765 starts running until ready if something yields such as talk_init. */
3766 #ifdef PLAYBACK_VOICE
3767 mutex_init(&mutex_codecthread);
3768 /* Take ownership of lock to prevent playback of anything before audio
3769 hardware is initialized - audio thread unlocks it after final init
3770 stage */
3771 mutex_lock(&mutex_codecthread);
3772 #endif
3773 queue_init(&audio_queue, true);
3774 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3775 queue_init(&codec_queue, true);
3777 pcm_init();
3779 #ifdef ROCKBOX_HAS_LOGF
3780 audio_set_track_changed_event(audio_test_track_changed_event);
3781 #endif
3783 /* Initialize codec api. */
3784 ci.read_filebuf = codec_filebuf_callback;
3785 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3786 ci.get_codec_memory = codec_get_memory_callback;
3787 ci.request_buffer = codec_request_buffer_callback;
3788 ci.advance_buffer = codec_advance_buffer_callback;
3789 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3790 ci.request_next_track = codec_request_next_track_callback;
3791 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3792 ci.seek_buffer = codec_seek_buffer_callback;
3793 ci.seek_complete = codec_seek_complete_callback;
3794 ci.set_elapsed = codec_set_elapsed_callback;
3795 ci.set_offset = codec_set_offset_callback;
3796 ci.configure = codec_configure_callback;
3797 ci.discard_codec = codec_discard_codec_callback;
3799 /* Initialize voice codec api. */
3800 #ifdef PLAYBACK_VOICE
3801 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3802 memset(&id3_voice, 0, sizeof(id3_voice));
3803 ci_voice.read_filebuf = voice_filebuf_callback;
3804 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3805 ci_voice.get_codec_memory = voice_get_memory_callback;
3806 ci_voice.request_buffer = voice_request_buffer_callback;
3807 ci_voice.advance_buffer = voice_advance_buffer_callback;
3808 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3809 ci_voice.request_next_track = voice_request_next_track_callback;
3810 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3811 ci_voice.seek_buffer = voice_seek_buffer_callback;
3812 ci_voice.seek_complete = voice_do_nothing;
3813 ci_voice.set_elapsed = voice_set_elapsed_callback;
3814 ci_voice.set_offset = voice_set_offset_callback;
3815 ci_voice.configure = voice_configure_callback;
3816 ci_voice.discard_codec = voice_do_nothing;
3817 ci_voice.taginfo_ready = &voicetagtrue;
3818 ci_voice.id3 = &id3_voice;
3819 id3_voice.frequency = 11200;
3820 id3_voice.length = 1000000L;
3821 #endif
3823 /* initialize the buffer */
3824 filebuf = audiobuf;
3826 /* audio_reset_buffer must to know the size of voice buffer so init
3827 talk first */
3828 talk_init();
3830 /* Create the threads late now that we shouldn't be yielding again before
3831 returning */
3832 codec_thread_p = create_thread(
3833 codec_thread, codec_stack, sizeof(codec_stack),
3834 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3835 IF_COP(, CPU, true));
3837 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
3838 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3839 IF_COP(, CPU, false));
3841 #ifdef PLAYBACK_VOICE
3842 /* TODO: Change this around when various speech codecs can be used */
3843 if (talk_voice_required())
3845 logf("Starting voice codec");
3846 queue_init(&voice_queue, true);
3847 create_thread(voice_thread, voice_stack,
3848 sizeof(voice_stack), voice_thread_name
3849 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU, false));
3851 #endif
3853 /* Set crossfade setting for next buffer init which should be about... */
3854 pcmbuf_crossfade_enable(global_settings.crossfade);
3856 /* ...now! Set up the buffers */
3857 audio_reset_buffer();
3859 /* Probably safe to say */
3860 audio_is_initialized = true;
3862 sound_settings_apply();
3863 #ifdef HAVE_WM8758
3864 eq_hw_enable(global_settings.eq_hw_enabled);
3865 #endif
3866 #ifndef HAVE_FLASH_STORAGE
3867 audio_set_buffer_margin(global_settings.buffer_margin);
3868 #endif
3869 } /* audio_init */