Rename getptr to bufgetcodec and make it ensure the codec is ready to load
[Rockbox.git] / apps / playback.c
blob120a9722402cbb6bc2aa6ee862f1b5bbf3690dfb
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 "buffering.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 /* Define LOGF_ENABLE to enable logf output in this file */
92 /*#define LOGF_ENABLE*/
93 #include "logf.h"
95 /* macros to enable logf for queues
96 logging on SYS_TIMEOUT can be disabled */
97 #ifdef SIMULATOR
98 /* Define this for logf output of all queuing except SYS_TIMEOUT */
99 #define PLAYBACK_LOGQUEUES
100 /* Define this to logf SYS_TIMEOUT messages */
101 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
102 #endif
104 #ifdef PLAYBACK_LOGQUEUES
105 #define LOGFQUEUE logf
106 #else
107 #define LOGFQUEUE(...)
108 #endif
110 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
111 #define LOGFQUEUE_SYS_TIMEOUT logf
112 #else
113 #define LOGFQUEUE_SYS_TIMEOUT(...)
114 #endif
117 /* Define one constant that includes recording related functionality */
118 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
119 #define AUDIO_HAVE_RECORDING
120 #endif
122 enum {
123 Q_AUDIO_PLAY = 1,
124 Q_AUDIO_STOP,
125 Q_AUDIO_PAUSE,
126 Q_AUDIO_SKIP,
127 Q_AUDIO_PRE_FF_REWIND,
128 Q_AUDIO_FF_REWIND,
129 /* Q_AUDIO_REBUFFER_SEEK, */
130 Q_AUDIO_CHECK_NEW_TRACK,
131 Q_AUDIO_FLUSH,
132 Q_AUDIO_TRACK_CHANGED,
133 Q_AUDIO_DIR_SKIP,
134 Q_AUDIO_POSTINIT,
135 Q_AUDIO_FILL_BUFFER,
136 #if MEM > 8
137 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
138 #endif
139 Q_CODEC_REQUEST_COMPLETE,
140 Q_CODEC_REQUEST_FAILED,
142 Q_VOICE_PLAY,
143 Q_VOICE_STOP,
145 Q_CODEC_LOAD,
146 Q_CODEC_LOAD_DISK,
148 #ifdef AUDIO_HAVE_RECORDING
149 Q_ENCODER_LOAD_DISK,
150 Q_ENCODER_RECORD,
151 #endif
154 /* As defined in plugins/lib/xxx2wav.h */
155 #if MEM > 1
156 #define MALLOC_BUFSIZE (512*1024)
157 #define GUARD_BUFSIZE (32*1024)
158 #else
159 #define MALLOC_BUFSIZE (100*1024)
160 #define GUARD_BUFSIZE (8*1024)
161 #endif
163 /* As defined in plugin.lds */
164 #if defined(CPU_PP)
165 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
166 #define CODEC_IRAM_SIZE ((size_t)0xc000)
167 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
168 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
169 #define CODEC_IRAM_SIZE ((size_t)0x10000)
170 #else
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #endif
175 #ifndef IBSS_ATTR_VOICE_STACK
176 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
177 #endif
179 bool audio_is_initialized = false;
181 /* Variables are commented with the threads that use them: *
182 * A=audio, C=codec, V=voice. A suffix of - indicates that *
183 * the variable is read but not updated on that thread. */
184 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
186 /* Main state control */
187 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
188 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
189 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
190 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
192 /* Ring buffer where compressed audio and codecs are loaded */
193 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
194 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
195 /* FIXME: make filebuflen static */
196 size_t filebuflen = 0; /* Size of buffer (A/C-) */
197 /* FIXME: make buf_ridx (C/A-) */
199 /* Possible arrangements of the buffer */
200 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
201 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
202 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
203 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
205 static struct mp3entry curtrack_id3;
206 static struct mp3entry nexttrack_id3;
208 /* Track info structure about songs in the file buffer (A/C-) */
209 struct track_info {
210 int audio_hid; /* The ID for the track's buffer handle */
211 int id3_hid; /* The ID for the track's metadata handle */
212 int codec_hid; /* The ID for the track's codec handle */
214 size_t codecsize; /* Codec length in bytes */
215 size_t filesize; /* File total length */
217 bool taginfo_ready; /* Is metadata read */
219 bool event_sent; /* Was this track's buffered event sent */
222 static struct track_info tracks[MAX_TRACK];
223 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
224 static int track_widx = 0; /* Track being buffered (A) */
226 #if 0
227 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
228 #endif
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;
240 /* Scrobbler support */
241 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
243 /* Track change controls */
244 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
245 static bool playlist_end = false; /* Has the current playlist ended? (A) */
246 static bool dir_skip = false; /* Is a directory skip pending? (A) */
247 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
248 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
249 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
251 /* Callbacks which applications or plugins may set */
252 /* When the playing track has changed from the user's perspective */
253 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
254 /* When a track has been buffered */
255 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
256 /* When a track's buffer has been overwritten or cleared */
257 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
259 /* Configuration */
260 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
261 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
262 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
263 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
264 #if MEM > 8
265 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
266 #endif
268 /* Multiple threads */
269 static void set_current_codec(int codec_idx);
270 /* Set the watermark to trigger buffer fill (A/C) FIXME */
271 static void set_filebuf_watermark(int seconds);
273 /* Audio thread */
274 static struct event_queue audio_queue NOCACHEBSS_ATTR;
275 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
276 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
277 static const char audio_thread_name[] = "audio";
279 static void audio_thread(void);
280 static void audio_initiate_track_change(long direction);
281 static bool audio_have_tracks(void);
282 static void audio_reset_buffer(void);
284 /* Codec thread */
285 extern struct codec_api ci;
286 static struct event_queue codec_queue NOCACHEBSS_ATTR;
287 static struct queue_sender_list codec_queue_sender_list;
288 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
289 IBSS_ATTR;
290 static const char codec_thread_name[] = "codec";
291 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
293 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
295 /* Buffering thread */
296 void buffering_thread(void);
297 static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
298 static const char buffering_thread_name[] = "buffering";
299 struct thread_entry *buffering_thread_p;
301 /* Voice thread */
302 #ifdef PLAYBACK_VOICE
304 extern struct codec_api ci_voice;
306 static struct thread_entry *voice_thread_p = NULL;
307 static struct event_queue voice_queue NOCACHEBSS_ATTR;
308 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
309 IBSS_ATTR_VOICE_STACK;
310 static const char voice_thread_name[] = "voice codec";
312 /* Voice codec swapping control */
313 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
315 #ifdef SIMULATOR
316 /* IRAM codec swap buffer for sim*/
317 static unsigned char sim_iram[CODEC_IRAM_SIZE];
318 #undef CODEC_IRAM_ORIGIN
319 #define CODEC_IRAM_ORIGIN sim_iram
320 #endif
322 /* iram_buf and dram_buf are either both NULL or both non-NULL */
323 /* Pointer to IRAM buffer for codec swapping */
324 static unsigned char *iram_buf = NULL;
325 /* Pointer to DRAM buffer for codec swapping */
326 static unsigned char *dram_buf = NULL;
327 /* Parity of swap_codec calls - needed because one codec swapping itself in
328 automatically swaps in the other and the swap when unlocking should not
329 happen if the parity is even.
331 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
332 /* Locking to control which codec (normal/voice) is running */
333 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
334 static struct event event_codecthread NOCACHEBSS_ATTR;
336 /* Voice state */
337 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
338 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
339 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
340 static unsigned char *voicebuf = NULL;
341 static size_t voice_remaining = 0;
343 #ifdef IRAM_STEAL
344 /* Voice IRAM has been stolen for other use */
345 static bool voice_iram_stolen = false;
346 #endif
348 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
350 struct voice_info {
351 void (*callback)(unsigned char **start, size_t* size);
352 size_t size;
353 unsigned char *buf;
355 static void voice_thread(void);
356 static void voice_stop(void);
358 #endif /* PLAYBACK_VOICE */
361 /* --- Helper functions --- */
363 struct mp3entry *bufgetid3(int handle_id)
365 if (handle_id < 0)
366 return NULL;
368 struct mp3entry *id3;
369 ssize_t ret = bufgetdata(handle_id, 0, (unsigned char **)&id3);
371 if (ret < 0 || ret != sizeof(struct mp3entry))
372 return NULL;
374 return id3;
377 unsigned char *bufgetcodec(struct track_info *track)
379 unsigned char *ptr;
380 ssize_t ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
382 if (ret == -2) {
383 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
384 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
387 while (ret == -2) {
388 sleep(1);
389 ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
392 if (ret < 0)
393 return NULL;
394 else
395 return ptr;
398 void clear_track_info(struct track_info *track)
400 if (!track)
401 return;
403 if (track->codec_hid > 0) {
404 bufclose(track->codec_hid);
407 if (track->id3_hid > 0) {
408 bufclose(track->id3_hid);
411 if (track->audio_hid > 0) {
412 bufclose(track->audio_hid);
415 memset(track, 0, sizeof(struct track_info));
418 /* --- External interfaces --- */
420 void mp3_play_data(const unsigned char* start, int size,
421 void (*get_more)(unsigned char** start, size_t* size))
423 #ifdef PLAYBACK_VOICE
424 static struct voice_info voice_clip;
425 voice_clip.callback = get_more;
426 voice_clip.buf = (unsigned char*)start;
427 voice_clip.size = size;
428 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
429 queue_post(&voice_queue, Q_VOICE_STOP, 0);
430 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
431 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
432 voice_thread_start = true;
433 trigger_cpu_boost();
434 #else
435 (void) start;
436 (void) size;
437 (void) get_more;
438 #endif
441 void mp3_play_stop(void)
443 #ifdef PLAYBACK_VOICE
444 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
445 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
446 queue_post(&voice_queue, Q_VOICE_STOP, 1);
447 #endif
450 void mp3_play_pause(bool play)
452 /* a dummy */
453 (void)play;
456 bool mp3_is_playing(void)
458 #ifdef PLAYBACK_VOICE
459 return voice_is_playing;
460 #else
461 return false;
462 #endif
465 /* If voice could be swapped out - wait for it to return
466 * Used by buffer claming functions.
468 static void wait_for_voice_swap_in(void)
470 #ifdef PLAYBACK_VOICE
471 if (NULL == iram_buf)
472 return;
474 event_wait(&event_codecthread, STATE_NONSIGNALED);
475 #endif /* PLAYBACK_VOICE */
478 /* This sends a stop message and the audio thread will dump all it's
479 subsequenct messages */
480 static void audio_hard_stop(void)
482 /* Stop playback */
483 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
484 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
487 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
489 unsigned char *buf, *end;
491 if (audio_is_initialized)
493 audio_hard_stop();
494 wait_for_voice_swap_in();
495 #ifdef PLAYBACK_VOICE
496 voice_stop();
497 #endif
499 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
501 if (buffer_size == NULL)
503 /* Special case for talk_init to use since it already knows it's
504 trashed */
505 buffer_state = BUFFER_STATE_TRASHED;
506 return NULL;
509 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
510 || !talk_voice_required())
512 logf("get buffer: talk, audio");
513 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
514 the talk buffer is not needed because voice isn't being used, or
515 could be BUFFER_STATE_TRASHED already. If state is
516 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
517 without the caller knowing what's going on. Changing certain settings
518 may move it to a worse condition but the memory in use by something
519 else will remain undisturbed.
521 if (buffer_state != BUFFER_STATE_TRASHED)
523 talk_buffer_steal();
524 buffer_state = BUFFER_STATE_TRASHED;
527 buf = audiobuf;
528 end = audiobufend;
530 else
532 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
533 still BUFFER_STATE_INITIALIZED */
534 /* Skip talk buffer and move pcm buffer to end to maximize available
535 contiguous memory - no audio running means voice will not need the
536 swap space */
537 logf("get buffer: audio");
538 buf = audiobuf + talk_get_bufsize();
539 end = audiobufend - pcmbuf_init(audiobufend);
540 buffer_state = BUFFER_STATE_VOICED_ONLY;
543 *buffer_size = end - buf;
545 return buf;
548 #ifdef IRAM_STEAL
549 void audio_iram_steal(void)
551 /* We need to stop audio playback in order to use codec IRAM */
552 audio_hard_stop();
554 #ifdef PLAYBACK_VOICE
555 if (NULL != iram_buf)
557 /* Can't already be stolen */
558 if (voice_iram_stolen)
559 return;
561 /* Must wait for voice to be current again if it is swapped which
562 would cause the caller's buffer to get clobbered when voice locks
563 and runs - we'll wait for it to lock and yield again then make sure
564 the ride has come to a complete stop */
565 wait_for_voice_swap_in();
566 voice_stop();
568 /* Save voice IRAM but just memcpy - safe to do here since voice
569 is current and no audio codec is loaded */
570 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
571 voice_iram_stolen = true;
573 else
575 /* Nothing much to do if no voice */
576 voice_iram_stolen = false;
578 #endif
580 #endif /* IRAM_STEAL */
582 #ifdef HAVE_RECORDING
583 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
585 /* Don't allow overwrite of voice swap area or we'll trash the
586 swapped-out voice codec but can use whole thing if none */
587 unsigned char *end;
589 /* Stop audio and voice. Wait for voice to swap in and be clear
590 of pending events to ensure trouble-free operation of encoders */
591 audio_hard_stop();
592 wait_for_voice_swap_in();
593 #ifdef PLAYBACK_VOICE
594 voice_stop();
595 #endif
596 talk_buffer_steal();
598 #ifdef PLAYBACK_VOICE
599 /* If no dram_buf, swap space not used and recording gets more
600 memory. Codec swap areas will remain unaffected by the next init
601 since they're allocated at the end of the buffer and their sizes
602 don't change between calls */
603 end = dram_buf;
604 if (NULL == end)
605 #endif /* PLAYBACK_VOICE */
606 end = audiobufend;
608 buffer_state = BUFFER_STATE_TRASHED;
610 *buffer_size = end - audiobuf;
612 return (unsigned char *)audiobuf;
615 bool audio_load_encoder(int afmt)
617 #ifndef SIMULATOR
618 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
619 if (!enc_fn)
620 return false;
622 audio_remove_encoder();
623 ci.enc_codec_loaded = 0; /* clear any previous error condition */
625 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
626 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
628 while (ci.enc_codec_loaded == 0)
629 yield();
631 logf("codec loaded: %d", ci.enc_codec_loaded);
633 return ci.enc_codec_loaded > 0;
634 #else
635 (void)afmt;
636 return true;
637 #endif
638 } /* audio_load_encoder */
640 void audio_remove_encoder(void)
642 #ifndef SIMULATOR
643 /* force encoder codec unload (if currently loaded) */
644 if (ci.enc_codec_loaded <= 0)
645 return;
647 ci.stop_encoder = true;
648 while (ci.enc_codec_loaded > 0)
649 yield();
650 #endif
651 } /* audio_remove_encoder */
653 #endif /* HAVE_RECORDING */
655 struct mp3entry* audio_current_track(void)
657 const char *filename;
658 const char *p;
659 static struct mp3entry temp_id3;
660 int cur_idx;
661 int offset = ci.new_track + wps_offset;
663 cur_idx = track_ridx + offset;
664 cur_idx &= MAX_TRACK_MASK;
666 if (tracks[cur_idx].id3_hid > 0)
667 return &curtrack_id3;
669 memset(&temp_id3, 0, sizeof(struct mp3entry));
671 filename = playlist_peek(0);
672 if (!filename)
673 filename = "No file!";
675 #ifdef HAVE_TC_RAMCACHE
676 if (tagcache_fill_tags(&temp_id3, filename))
677 return &temp_id3;
678 #endif
680 p = strrchr(filename, '/');
681 if (!p)
682 p = filename;
683 else
684 p++;
686 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
687 temp_id3.title = &temp_id3.path[0];
689 return &temp_id3;
692 struct mp3entry* audio_next_track(void)
694 int next_idx = track_ridx;
696 if (!audio_have_tracks())
697 return NULL;
699 next_idx++;
700 next_idx &= MAX_TRACK_MASK;
702 if (tracks[next_idx].id3_hid <= 0)
703 return NULL;
705 return &nexttrack_id3;
708 bool audio_has_changed_track(void)
710 if (track_changed)
712 track_changed = false;
713 return true;
716 return false;
719 void audio_play(long offset)
721 logf("audio_play");
723 #ifdef PLAYBACK_VOICE
724 /* Truncate any existing voice output so we don't have spelling
725 * etc. over the first part of the played track */
726 talk_force_shutup();
727 #endif
729 /* Start playback */
730 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
731 /* Don't return until playback has actually started */
732 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
735 void audio_stop(void)
737 /* Stop playback */
738 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
739 /* Don't return until playback has actually stopped */
740 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
743 void audio_pause(void)
745 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
746 /* Don't return until playback has actually paused */
747 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
750 void audio_resume(void)
752 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
753 /* Don't return until playback has actually resumed */
754 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
757 void audio_next(void)
759 if (playlist_check(ci.new_track + wps_offset + 1))
761 if (global_settings.beep)
762 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
764 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
765 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
766 /* Update wps while our message travels inside deep playback queues. */
767 wps_offset++;
768 track_changed = true;
770 else
772 /* No more tracks. */
773 if (global_settings.beep)
774 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
778 void audio_prev(void)
780 if (playlist_check(ci.new_track + wps_offset - 1))
782 if (global_settings.beep)
783 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
785 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
786 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
787 /* Update wps while our message travels inside deep playback queues. */
788 wps_offset--;
789 track_changed = true;
791 else
793 /* No more tracks. */
794 if (global_settings.beep)
795 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
799 void audio_next_dir(void)
801 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
802 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
805 void audio_prev_dir(void)
807 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
808 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
811 void audio_pre_ff_rewind(void)
813 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
814 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
817 void audio_ff_rewind(long newpos)
819 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
820 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
823 void audio_flush_and_reload_tracks(void)
825 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
826 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
829 void audio_error_clear(void)
831 #ifdef AUDIO_HAVE_RECORDING
832 pcm_rec_error_clear();
833 #endif
836 int audio_status(void)
838 int ret = 0;
840 if (playing)
841 ret |= AUDIO_STATUS_PLAY;
843 if (paused)
844 ret |= AUDIO_STATUS_PAUSE;
846 #ifdef HAVE_RECORDING
847 /* Do this here for constitency with mpeg.c version */
848 ret |= pcm_rec_status();
849 #endif
851 return ret;
854 int audio_get_file_pos(void)
856 return 0;
859 #ifndef HAVE_FLASH_STORAGE
860 void audio_set_buffer_margin(int setting)
862 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
863 buffer_margin = lookup[setting];
864 logf("buffer margin: %d", buffer_margin);
865 set_filebuf_watermark(buffer_margin);
867 #endif
869 /* Take nescessary steps to enable or disable the crossfade setting */
870 void audio_set_crossfade(int enable)
872 size_t offset;
873 bool was_playing;
874 size_t size;
876 /* Tell it the next setting to use */
877 pcmbuf_crossfade_enable(enable);
879 /* Return if size hasn't changed or this is too early to determine
880 which in the second case there's no way we could be playing
881 anything at all */
882 if (pcmbuf_is_same_size())
884 /* This function is a copout and just syncs some variables -
885 to be removed at a later date */
886 pcmbuf_crossfade_enable_finished();
887 return;
890 offset = 0;
891 was_playing = playing;
893 /* Playback has to be stopped before changing the buffer size */
894 if (was_playing)
896 /* Store the track resume position */
897 offset = curtrack_id3.offset;
898 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
901 /* Blast it - audio buffer will have to be setup again next time
902 something plays */
903 audio_get_buffer(true, &size);
905 /* Restart playback if audio was running previously */
906 if (was_playing)
907 audio_play(offset);
910 /* --- Routines called from multiple threads --- */
911 static void set_current_codec(int codec_idx)
913 current_codec = codec_idx;
914 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
917 #ifdef PLAYBACK_VOICE
918 static void swap_codec(void)
920 int my_codec;
922 /* Swap nothing if no swap buffers exist */
923 if (dram_buf == NULL)
925 logf("swap: no swap buffers");
926 return;
929 my_codec = current_codec;
931 logf("swapping out codec: %d", my_codec);
933 /* Invert this when a codec thread enters and leaves */
934 swap_codec_parity = !swap_codec_parity;
936 /* If this is true, an odd number of calls has occurred and there's
937 no codec thread waiting to swap us out when it locks and runs. This
938 occurs when playback is stopped or when just starting playback and
939 the audio thread is loading a codec; parities should always be even
940 on entry when a thread calls this during playback */
941 if (swap_codec_parity)
943 /* Save our current IRAM and DRAM */
944 #ifdef IRAM_STEAL
945 if (voice_iram_stolen)
947 logf("swap: iram restore");
948 voice_iram_stolen = false;
949 /* Don't swap trashed data into buffer as the voice IRAM will
950 already be swapped out - should _always_ be the case if
951 voice_iram_stolen is true since the voice has been swapped
952 in beforehand */
953 if (my_codec == CODEC_IDX_VOICE)
955 logf("voice iram already swapped");
956 goto skip_iram_swap;
959 #endif
961 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
963 #ifdef IRAM_STEAL
964 skip_iram_swap:
965 #endif
967 memswap128(dram_buf, codecbuf, CODEC_SIZE);
968 /* No cache invalidation needed; it will be done in codec_load_ram
969 or we won't be here otherwise */
972 /* Release my semaphore */
973 semaphore_release(&sem_codecthread);
974 logf("unlocked: %d", my_codec);
976 /* Wait for other codec */
977 event_wait(&event_codecthread,
978 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
980 /* Wait for other codec to unlock */
981 logf("waiting for lock: %d", my_codec);
982 semaphore_wait(&sem_codecthread);
984 /* Take control */
985 set_current_codec(my_codec);
986 event_set_state(&event_codecthread,
987 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
989 /* Reload our IRAM and DRAM */
990 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
991 memswap128(dram_buf, codecbuf, CODEC_SIZE);
992 invalidate_icache();
994 /* Flip parity again */
995 swap_codec_parity = !swap_codec_parity;
997 logf("resuming codec: %d", my_codec);
1000 /* This function is meant to be used by the buffer stealing functions to
1001 ensure the codec is no longer active and so voice will be swapped-in
1002 before it is called */
1003 static void voice_stop(void)
1005 /* Must have a voice codec loaded or we'll hang forever here */
1006 if (!voice_codec_loaded)
1007 return;
1009 talk_force_shutup();
1011 /* Loop until voice empties it's queue, stops and picks up on the new
1012 track; the voice thread must be stopped and waiting for messages
1013 outside the codec */
1014 while (voice_is_playing || !queue_empty(&voice_queue) ||
1015 ci_voice.new_track)
1016 yield();
1018 if (!playing)
1019 pcmbuf_play_stop();
1020 } /* voice_stop */
1022 /* Is voice still speaking */
1023 /* Unfortunately only reliable when music is not also playing. */
1024 static bool is_voice_speaking(void)
1026 return is_voice_queued()
1027 || voice_is_playing
1028 || (!playing && pcm_is_playing());
1031 #endif /* PLAYBACK_VOICE */
1033 /* Wait for voice to finish speaking. */
1034 /* Also only reliable when music is not also playing. */
1035 void voice_wait(void)
1037 #ifdef PLAYBACK_VOICE
1038 while (is_voice_speaking())
1039 sleep(HZ/10);
1040 #endif
1043 static void set_filebuf_watermark(int seconds)
1045 size_t bytes;
1047 if (!filebuf)
1048 return; /* Audio buffers not yet set up */
1050 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), conf_watermark);
1051 bytes = MIN(bytes, filebuflen / 2);
1052 conf_watermark = bytes;
1055 const char * get_codec_filename(int cod_spec)
1057 const char *fname;
1059 #ifdef HAVE_RECORDING
1060 /* Can choose decoder or encoder if one available */
1061 int type = cod_spec & CODEC_TYPE_MASK;
1062 int afmt = cod_spec & CODEC_AFMT_MASK;
1064 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1065 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1067 fname = (type == CODEC_TYPE_ENCODER) ?
1068 audio_formats[afmt].codec_enc_root_fn :
1069 audio_formats[afmt].codec_root_fn;
1071 logf("%s: %d - %s",
1072 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1073 afmt, fname ? fname : "<unknown>");
1074 #else /* !HAVE_RECORDING */
1075 /* Always decoder */
1076 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1077 cod_spec = AFMT_UNKNOWN;
1078 fname = audio_formats[cod_spec].codec_root_fn;
1079 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1080 #endif /* HAVE_RECORDING */
1082 return fname;
1083 } /* get_codec_filename */
1086 /* --- Voice thread --- */
1088 #ifdef PLAYBACK_VOICE
1090 static bool voice_pcmbuf_insert_callback(
1091 const void *ch1, const void *ch2, int count)
1093 const char *src[2] = { ch1, ch2 };
1095 while (count > 0)
1097 int out_count = dsp_output_count(count);
1098 int inp_count;
1099 char *dest;
1101 while ((dest = pcmbuf_request_voice_buffer(
1102 &out_count, playing)) == NULL)
1104 if (playing && audio_codec_loaded)
1105 swap_codec();
1106 else
1107 yield();
1110 /* Get the real input_size for output_size bytes, guarding
1111 * against resampling buffer overflows. */
1112 inp_count = dsp_input_count(out_count);
1114 if (inp_count <= 0)
1115 return true;
1117 /* Input size has grown, no error, just don't write more than length */
1118 if (inp_count > count)
1119 inp_count = count;
1121 out_count = dsp_process(dest, src, inp_count);
1123 if (out_count <= 0)
1124 return true;
1126 if (playing)
1128 pcmbuf_mix_voice(out_count);
1129 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1130 audio_codec_loaded)
1131 swap_codec();
1133 else
1134 pcmbuf_write_complete(out_count);
1136 count -= inp_count;
1139 return true;
1140 } /* voice_pcmbuf_insert_callback */
1142 static void* voice_get_memory_callback(size_t *size)
1144 /* Voice should have no use for this. If it did, we'd have to
1145 swap the malloc buffer as well. */
1146 *size = 0;
1147 return NULL;
1150 static void voice_set_elapsed_callback(unsigned int value)
1152 (void)value;
1155 static void voice_set_offset_callback(size_t value)
1157 (void)value;
1160 static void voice_configure_callback(int setting, intptr_t value)
1162 if (!dsp_configure(setting, value))
1164 logf("Illegal key:%d", setting);
1168 static size_t voice_filebuf_callback(void *ptr, size_t size)
1170 (void)ptr;
1171 (void)size;
1173 return 0;
1176 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1177 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1179 if (aborting && !playing)
1181 /* Aborting: Slight hack - flush PCM buffer if
1182 only being used for voice */
1183 pcmbuf_play_stop();
1186 if (voice_is_playing)
1188 /* Clear the current buffer */
1189 voice_is_playing = false;
1190 voice_getmore = NULL;
1191 voice_remaining = 0;
1192 voicebuf = NULL;
1194 /* Cancel any automatic boost if no more clips requested. */
1195 if (!playing || !voice_thread_start)
1196 sleep(0);
1198 /* Force the codec to think it's changing tracks */
1199 ci_voice.new_track = 1;
1201 *realsize = 0;
1202 return true; /* Yes, change tracks */
1205 return false;
1208 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1210 struct queue_event ev;
1212 if (ci_voice.new_track)
1214 *realsize = 0;
1215 return NULL;
1218 while (1)
1220 if (voice_is_playing || playing)
1222 queue_wait_w_tmo(&voice_queue, &ev, 0);
1223 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1224 ev.id = Q_AUDIO_PLAY;
1226 else
1228 queue_wait(&voice_queue, &ev);
1231 switch (ev.id) {
1232 case Q_AUDIO_PLAY:
1233 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1234 if (playing)
1236 if (audio_codec_loaded)
1237 swap_codec();
1238 yield();
1240 break;
1242 #ifdef AUDIO_HAVE_RECORDING
1243 case Q_ENCODER_RECORD:
1244 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1245 swap_codec();
1246 break;
1247 #endif
1249 case Q_VOICE_STOP:
1250 LOGFQUEUE("voice < Q_VOICE_STOP");
1251 if (voice_on_voice_stop(ev.data, realsize))
1252 return NULL;
1253 break;
1255 case SYS_USB_CONNECTED:
1257 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1258 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1259 /* Voice is obviously current so let us swap ourselves away if
1260 playing so audio may stop itself - audio_codec_loaded can
1261 only be true in this case if we're here even if the codec
1262 is only about to load */
1263 if (audio_codec_loaded)
1264 swap_codec();
1265 /* Playback should be finished by now - ack and wait */
1266 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1267 usb_wait_for_disconnect(&voice_queue);
1268 if (change_tracks)
1269 return NULL;
1270 break;
1273 case Q_VOICE_PLAY:
1274 LOGFQUEUE("voice < Q_VOICE_PLAY");
1275 if (!voice_is_playing)
1277 /* Set up new voice data */
1278 struct voice_info *voice_data;
1279 #ifdef IRAM_STEAL
1280 if (voice_iram_stolen)
1282 /* Voice is the first to run again and is currently
1283 loaded */
1284 logf("voice: iram restore");
1285 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1286 voice_iram_stolen = false;
1288 #endif
1289 /* Must reset the buffer before any playback begins if
1290 needed */
1291 if (buffer_state == BUFFER_STATE_TRASHED)
1292 audio_reset_buffer();
1294 voice_is_playing = true;
1295 trigger_cpu_boost();
1296 voice_data = (struct voice_info *)ev.data;
1297 voice_remaining = voice_data->size;
1298 voicebuf = voice_data->buf;
1299 voice_getmore = voice_data->callback;
1301 goto voice_play_clip; /* To exit both switch and while */
1303 case SYS_TIMEOUT:
1304 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1305 goto voice_play_clip;
1307 default:
1308 LOGFQUEUE("voice < default");
1312 voice_play_clip:
1314 if (voice_remaining == 0 || voicebuf == NULL)
1316 if (voice_getmore)
1317 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1319 /* If this clip is done */
1320 if (voice_remaining == 0)
1322 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1323 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1324 /* Force pcm playback. */
1325 if (!pcm_is_playing())
1326 pcmbuf_play_start();
1330 *realsize = MIN(voice_remaining, reqsize);
1332 if (*realsize == 0)
1333 return NULL;
1335 return voicebuf;
1336 } /* voice_request_buffer_callback */
1338 static void voice_advance_buffer_callback(size_t amount)
1340 amount = MIN(amount, voice_remaining);
1341 voicebuf += amount;
1342 voice_remaining -= amount;
1345 static void voice_advance_buffer_loc_callback(void *ptr)
1347 size_t amount = (size_t)ptr - (size_t)voicebuf;
1349 voice_advance_buffer_callback(amount);
1352 static off_t voice_mp3_get_filepos_callback(int newtime)
1354 (void)newtime;
1356 return 0;
1359 static void voice_do_nothing(void)
1361 return;
1364 static bool voice_seek_buffer_callback(size_t newpos)
1366 (void)newpos;
1368 return false;
1371 static bool voice_request_next_track_callback(void)
1373 ci_voice.new_track = 0;
1374 return true;
1377 static void voice_thread(void)
1379 logf("Loading voice codec");
1380 voice_codec_loaded = true;
1381 semaphore_wait(&sem_codecthread);
1382 event_set_state(&event_codecthread, false);
1383 set_current_codec(CODEC_IDX_VOICE);
1384 dsp_configure(DSP_RESET, 0);
1385 voice_remaining = 0;
1386 voice_getmore = NULL;
1388 /* FIXME: If we being starting the voice thread without reboot, the
1389 voice_queue could be full of old stuff and we must flush it. */
1390 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1392 logf("Voice codec finished");
1393 voice_codec_loaded = false;
1394 voice_thread_p = NULL;
1395 semaphore_release(&sem_codecthread);
1396 } /* voice_thread */
1398 #endif /* PLAYBACK_VOICE */
1400 /* --- Codec thread --- */
1401 static bool codec_pcmbuf_insert_callback(
1402 const void *ch1, const void *ch2, int count)
1404 const char *src[2] = { ch1, ch2 };
1406 while (count > 0)
1408 int out_count = dsp_output_count(count);
1409 int inp_count;
1410 char *dest;
1412 /* Prevent audio from a previous track from playing */
1413 if (ci.new_track || ci.stop_codec)
1414 return true;
1416 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1418 sleep(1);
1419 if (ci.seek_time || ci.new_track || ci.stop_codec)
1420 return true;
1423 /* Get the real input_size for output_size bytes, guarding
1424 * against resampling buffer overflows. */
1425 inp_count = dsp_input_count(out_count);
1427 if (inp_count <= 0)
1428 return true;
1430 /* Input size has grown, no error, just don't write more than length */
1431 if (inp_count > count)
1432 inp_count = count;
1434 out_count = dsp_process(dest, src, inp_count);
1436 if (out_count <= 0)
1437 return true;
1439 pcmbuf_write_complete(out_count);
1441 #ifdef PLAYBACK_VOICE
1442 if ((voice_is_playing || voice_thread_start)
1443 && pcm_is_playing() && voice_codec_loaded &&
1444 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1446 voice_thread_start = false;
1447 swap_codec();
1449 #endif
1451 count -= inp_count;
1454 return true;
1455 } /* codec_pcmbuf_insert_callback */
1457 static void* codec_get_memory_callback(size_t *size)
1459 *size = MALLOC_BUFSIZE;
1460 return malloc_buf;
1463 #if 0
1464 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1465 static void codec_pcmbuf_position_callback(size_t size)
1467 /* This is called from an ISR, so be quick */
1468 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1469 prev_ti->id3.elapsed;
1471 if (time >= prev_ti->id3.length)
1473 pcmbuf_set_position_callback(NULL);
1474 prev_ti->id3.elapsed = prev_ti->id3.length;
1476 else
1477 prev_ti->id3.elapsed = time;
1479 #endif
1481 static void codec_set_elapsed_callback(unsigned int value)
1483 unsigned int latency;
1484 if (ci.seek_time)
1485 return;
1487 #ifdef AB_REPEAT_ENABLE
1488 ab_position_report(value);
1489 #endif
1491 latency = pcmbuf_get_latency();
1492 if (value < latency)
1493 curtrack_id3.elapsed = 0;
1494 else if (value - latency > curtrack_id3.elapsed ||
1495 value - latency < curtrack_id3.elapsed - 2)
1497 curtrack_id3.elapsed = value - latency;
1501 static void codec_set_offset_callback(size_t value)
1503 unsigned int latency;
1505 if (ci.seek_time)
1506 return;
1508 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1509 if (value < latency)
1510 curtrack_id3.offset = 0;
1511 else
1512 curtrack_id3.offset = value - latency;
1515 /* copy up-to size bytes into ptr and return the actual size copied */
1516 static size_t codec_filebuf_callback(void *ptr, size_t size)
1518 ssize_t copy_n;
1520 if (ci.stop_codec || !playing)
1521 return 0;
1523 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1525 /* Nothing requested OR nothing left */
1526 if (copy_n == 0)
1527 return 0;
1530 if (copy_n == -2)
1532 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
1533 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
1536 /* Let the disk buffer catch fill until enough data is available */
1537 while (copy_n == -2)
1539 sleep(1);
1541 if (ci.stop_codec || ci.new_track)
1542 return 0;
1544 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1547 /* Update read and other position pointers */
1548 bufadvance(CUR_TI->audio_hid, copy_n);
1549 ci.curpos += copy_n;
1551 /* Return the actual amount of data copied to the buffer */
1552 return copy_n;
1553 } /* codec_filebuf_callback */
1555 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1557 size_t copy_n = reqsize;
1558 ssize_t ret;
1559 char *ptr;
1561 if (!playing)
1563 *realsize = 0;
1564 return NULL;
1567 ret = bufgetdata(CUR_TI->audio_hid, reqsize, (unsigned char **)&ptr);
1568 if (ret >= 0)
1569 copy_n = MIN((size_t)ret, reqsize);
1571 if (copy_n == 0)
1573 *realsize = 0;
1574 return NULL;
1577 if (ret == -2)
1579 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
1580 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
1583 /* Let the disk buffer catch fill until enough data is available */
1584 while (ret == -2)
1586 sleep(1);
1588 if (ci.stop_codec || ci.new_track)
1590 *realsize = 0;
1591 return NULL;
1593 ret = bufgetdata(CUR_TI->audio_hid, reqsize, (unsigned char **)&ptr);
1595 copy_n = MIN((size_t)ret, reqsize);
1597 *realsize = copy_n;
1599 return ptr;
1600 } /* codec_request_buffer_callback */
1602 static int get_codec_base_type(int type)
1604 switch (type) {
1605 case AFMT_MPA_L1:
1606 case AFMT_MPA_L2:
1607 case AFMT_MPA_L3:
1608 return AFMT_MPA_L3;
1611 return type;
1614 static void codec_advance_buffer_callback(size_t amount)
1616 #if 0
1617 int ret;
1619 while ((ret = bufadvance(CUR_TI->audio_hid, amount) == -2) && filling)
1620 sleep(1);
1622 if (ret == -2)
1624 intptr_t result = Q_CODEC_REQUEST_FAILED;
1626 if (!ci.stop_codec)
1628 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1629 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1630 ci.curpos + amount);
1633 switch (result)
1635 case Q_CODEC_REQUEST_FAILED:
1636 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1637 ci.stop_codec = true;
1638 return;
1640 case Q_CODEC_REQUEST_COMPLETE:
1641 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1642 return;
1644 default:
1645 LOGFQUEUE("codec |< default");
1646 ci.stop_codec = true;
1647 return;
1651 /* Start buffer filling as necessary. */
1652 if (!pcmbuf_is_lowdata() && !filling)
1654 if (bufused() < conf_watermark && playing && !playlist_end)
1656 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1657 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1660 #endif
1662 bufadvance(CUR_TI->audio_hid, amount);
1664 ci.curpos += amount;
1665 codec_set_offset_callback(ci.curpos);
1668 static void codec_advance_buffer_loc_callback(void *ptr)
1670 size_t amount = get_offset(CUR_TI->audio_hid, ptr);
1672 codec_advance_buffer_callback(amount);
1675 /* Copied from mpeg.c. Should be moved somewhere else. */
1676 static int codec_get_file_pos(void)
1678 int pos = -1;
1679 struct mp3entry *id3 = audio_current_track();
1681 if (id3->vbr)
1683 if (id3->has_toc)
1685 /* Use the TOC to find the new position */
1686 unsigned int percent, remainder;
1687 int curtoc, nexttoc, plen;
1689 percent = (id3->elapsed*100)/id3->length;
1690 if (percent > 99)
1691 percent = 99;
1693 curtoc = id3->toc[percent];
1695 if (percent < 99)
1696 nexttoc = id3->toc[percent+1];
1697 else
1698 nexttoc = 256;
1700 pos = (id3->filesize/256)*curtoc;
1702 /* Use the remainder to get a more accurate position */
1703 remainder = (id3->elapsed*100)%id3->length;
1704 remainder = (remainder*100)/id3->length;
1705 plen = (nexttoc - curtoc)*(id3->filesize/256);
1706 pos += (plen/100)*remainder;
1708 else
1710 /* No TOC exists, estimate the new position */
1711 pos = (id3->filesize / (id3->length / 1000)) *
1712 (id3->elapsed / 1000);
1715 else if (id3->bitrate)
1716 pos = id3->elapsed * (id3->bitrate / 8);
1717 else
1718 return -1;
1720 pos += id3->first_frame_offset;
1722 /* Don't seek right to the end of the file so that we can
1723 transition properly to the next song */
1724 if (pos >= (int)(id3->filesize - id3->id3v1len))
1725 pos = id3->filesize - id3->id3v1len - 1;
1727 return pos;
1730 static off_t codec_mp3_get_filepos_callback(int newtime)
1732 off_t newpos;
1734 curtrack_id3.elapsed = newtime;
1735 newpos = codec_get_file_pos();
1737 return newpos;
1740 static void codec_seek_complete_callback(void)
1742 logf("seek_complete");
1743 if (pcm_is_paused())
1745 /* If this is not a seamless seek, clear the buffer */
1746 pcmbuf_play_stop();
1747 dsp_configure(DSP_FLUSH, 0);
1749 /* If playback was not 'deliberately' paused, unpause now */
1750 if (!paused)
1751 pcmbuf_pause(false);
1753 ci.seek_time = 0;
1756 static bool codec_seek_buffer_callback(size_t newpos)
1758 int difference;
1760 logf("codec_seek_buffer_callback");
1762 if (newpos >= CUR_TI->filesize)
1763 newpos = CUR_TI->filesize - 1;
1765 difference = newpos - ci.curpos;
1766 if (difference >= 0)
1768 /* Seeking forward */
1769 logf("seek: +%d", difference);
1770 codec_advance_buffer_callback(difference);
1771 return true;
1774 /* Seeking backward */
1775 difference = -difference;
1776 if (ci.curpos - difference < 0)
1777 difference = ci.curpos;
1779 #if 0
1780 /* We need to reload the song. */
1781 if (newpos < CUR_TI->start_pos)
1783 intptr_t result = Q_CODEC_REQUEST_FAILED;
1785 if (!ci.stop_codec)
1787 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1788 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1789 newpos);
1792 switch (result)
1794 case Q_CODEC_REQUEST_COMPLETE:
1795 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1796 return true;
1798 case Q_CODEC_REQUEST_FAILED:
1799 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1800 ci.stop_codec = true;
1801 return false;
1803 default:
1804 LOGFQUEUE("codec |< default");
1805 return false;
1808 #endif
1810 /* Seeking inside buffer space. */
1811 logf("seek: -%d", difference);
1812 bufadvance(CUR_TI->audio_hid, -difference);
1813 ci.curpos -= difference;
1814 return true;
1817 static void codec_configure_callback(int setting, intptr_t value)
1819 switch (setting) {
1820 case CODEC_SET_FILEBUF_WATERMARK:
1821 conf_watermark = value;
1822 set_filebuf_watermark(buffer_margin);
1823 break;
1825 case CODEC_SET_FILEBUF_CHUNKSIZE:
1826 conf_filechunk = value;
1827 break;
1829 case CODEC_SET_FILEBUF_PRESEEK:
1830 conf_preseek = value;
1831 break;
1833 default:
1834 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1838 static void codec_track_changed(void)
1840 automatic_skip = false;
1841 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1842 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1845 static void codec_pcmbuf_track_changed_callback(void)
1847 pcmbuf_set_position_callback(NULL);
1848 codec_track_changed();
1851 static void codec_discard_codec_callback(void)
1853 if (CUR_TI->codec_hid > 0)
1855 bufclose(CUR_TI->codec_hid);
1856 CUR_TI->codec_hid = 0;
1857 CUR_TI->codecsize = 0;
1860 #if 0
1861 /* Check if a buffer desync has happened, log it and stop playback. */
1862 if (buf_ridx != CUR_TI->buf_idx)
1864 int offset = CUR_TI->buf_idx - buf_ridx;
1865 size_t new_used = bufused() - offset;
1867 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1868 logf("Used off:%d",bufused() - new_used);
1870 /* This is a fatal internal error and it's not safe to
1871 * continue playback. */
1872 ci.stop_codec = true;
1873 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1875 #endif
1878 static inline void codec_gapless_track_change(void) {
1879 /* callback keeps the progress bar moving while the pcmbuf empties */
1880 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1881 /* set the pcmbuf callback for when the track really changes */
1882 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1885 static inline void codec_crossfade_track_change(void) {
1886 /* Initiate automatic crossfade mode */
1887 pcmbuf_crossfade_init(false);
1888 /* Notify the wps that the track change starts now */
1889 codec_track_changed();
1892 static void codec_track_skip_done(bool was_manual)
1894 int crossfade_mode = global_settings.crossfade;
1896 /* Manual track change (always crossfade or flush audio). */
1897 if (was_manual)
1899 pcmbuf_crossfade_init(true);
1900 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1901 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1903 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1904 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1905 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1907 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1909 if (global_settings.playlist_shuffle)
1910 /* shuffle mode is on, so crossfade: */
1911 codec_crossfade_track_change();
1912 else
1913 /* shuffle mode is off, so do a gapless track change */
1914 codec_gapless_track_change();
1916 else
1917 /* normal crossfade: */
1918 codec_crossfade_track_change();
1920 else
1921 /* normal gapless playback. */
1922 codec_gapless_track_change();
1925 static bool codec_load_next_track(void)
1927 intptr_t result = Q_CODEC_REQUEST_FAILED;
1929 prev_track_elapsed = curtrack_id3.elapsed;
1931 if (ci.seek_time)
1932 codec_seek_complete_callback();
1934 #ifdef AB_REPEAT_ENABLE
1935 ab_end_of_track_report();
1936 #endif
1938 logf("Request new track");
1940 if (ci.new_track == 0)
1942 ci.new_track++;
1943 automatic_skip = true;
1946 if (!ci.stop_codec)
1948 trigger_cpu_boost();
1949 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1950 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1953 switch (result)
1955 case Q_CODEC_REQUEST_COMPLETE:
1956 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1957 codec_track_skip_done(!automatic_skip);
1958 return true;
1960 case Q_CODEC_REQUEST_FAILED:
1961 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1962 ci.new_track = 0;
1963 ci.stop_codec = true;
1964 return false;
1966 default:
1967 LOGFQUEUE("codec |< default");
1968 ci.stop_codec = true;
1969 return false;
1973 static bool codec_request_next_track_callback(void)
1975 int prev_codectype;
1977 if (ci.stop_codec || !playing)
1978 return false;
1980 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1982 if (!codec_load_next_track())
1983 return false;
1985 /* Check if the next codec is the same file. */
1986 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1988 logf("New track loaded");
1989 codec_discard_codec_callback();
1990 return true;
1992 else
1994 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1995 return false;
1999 static void codec_thread(void)
2001 struct queue_event ev;
2002 int status;
2003 size_t wrap;
2005 while (1) {
2006 status = 0;
2007 queue_wait(&codec_queue, &ev);
2009 switch (ev.id) {
2010 case Q_CODEC_LOAD_DISK:
2011 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
2012 queue_reply(&codec_queue, 1);
2013 audio_codec_loaded = true;
2014 #ifdef PLAYBACK_VOICE
2015 /* Don't sent messages to voice codec if it's already swapped
2016 out or it will never get this */
2017 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2019 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2020 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2022 semaphore_wait(&sem_codecthread);
2023 event_set_state(&event_codecthread, true);
2024 #endif
2025 set_current_codec(CODEC_IDX_AUDIO);
2026 ci.stop_codec = false;
2027 status = codec_load_file((const char *)ev.data, &ci);
2028 DEBUGF("codec_load = %d\n", status);
2029 #ifdef PLAYBACK_VOICE
2030 semaphore_release(&sem_codecthread);
2031 #endif
2032 break;
2034 case Q_CODEC_LOAD:
2035 LOGFQUEUE("codec < Q_CODEC_LOAD");
2036 if (CUR_TI->codec_hid <= 0) {
2037 logf("Codec slot is empty!");
2038 /* Wait for the pcm buffer to go empty */
2039 while (pcm_is_playing())
2040 yield();
2041 /* This must be set to prevent an infinite loop */
2042 ci.stop_codec = true;
2043 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
2044 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
2045 break;
2048 audio_codec_loaded = true;
2049 #ifdef PLAYBACK_VOICE
2050 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2052 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2053 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2055 semaphore_wait(&sem_codecthread);
2056 event_set_state(&event_codecthread, true);
2057 #endif
2058 set_current_codec(CODEC_IDX_AUDIO);
2059 ci.stop_codec = false;
2060 wrap = (size_t)&filebuf[filebuflen] - (size_t)bufgetcodec(CUR_TI);
2061 status = codec_load_ram(bufgetcodec(CUR_TI), CUR_TI->codecsize,
2062 &filebuf[0], wrap, &ci);
2063 #ifdef PLAYBACK_VOICE
2064 semaphore_release(&sem_codecthread);
2065 #endif
2066 break;
2068 #ifdef AUDIO_HAVE_RECORDING
2069 case Q_ENCODER_LOAD_DISK:
2070 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2071 audio_codec_loaded = false; /* Not audio codec! */
2072 #ifdef PLAYBACK_VOICE
2073 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2075 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2076 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2078 semaphore_wait(&sem_codecthread);
2079 event_set_state(&event_codecthread, true);
2080 #endif
2081 logf("loading encoder");
2082 set_current_codec(CODEC_IDX_AUDIO);
2083 ci.stop_encoder = false;
2084 status = codec_load_file((const char *)ev.data, &ci);
2085 #ifdef PLAYBACK_VOICE
2086 semaphore_release(&sem_codecthread);
2087 #endif
2088 logf("encoder stopped");
2089 break;
2090 #endif /* AUDIO_HAVE_RECORDING */
2092 #ifndef SIMULATOR
2093 case SYS_USB_CONNECTED:
2094 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2095 queue_clear(&codec_queue);
2096 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2097 usb_wait_for_disconnect(&codec_queue);
2098 break;
2099 #endif
2101 default:
2102 LOGFQUEUE("codec < default");
2105 if (audio_codec_loaded)
2107 if (ci.stop_codec)
2109 status = CODEC_OK;
2110 if (!playing)
2111 pcmbuf_play_stop();
2114 audio_codec_loaded = false;
2117 switch (ev.id) {
2118 case Q_CODEC_LOAD_DISK:
2119 case Q_CODEC_LOAD:
2120 LOGFQUEUE("codec < Q_CODEC_LOAD");
2121 if (playing)
2123 if (ci.new_track || status != CODEC_OK)
2125 if (!ci.new_track)
2127 logf("Codec failure");
2128 gui_syncsplash(HZ*2, "Codec failure");
2131 if (!codec_load_next_track())
2133 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2134 /* End of playlist */
2135 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2136 break;
2139 else
2141 logf("Codec finished");
2142 if (ci.stop_codec)
2144 /* Wait for the audio to stop playing before
2145 * triggering the WPS exit */
2146 while(pcm_is_playing())
2148 curtrack_id3.elapsed =
2149 curtrack_id3.length - pcmbuf_get_latency();
2150 sleep(1);
2152 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2153 /* End of playlist */
2154 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2155 break;
2159 if (CUR_TI->codec_hid > 0)
2161 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2162 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2164 else
2166 const char *codec_fn =
2167 get_codec_filename(curtrack_id3.codectype);
2168 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2169 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2170 (intptr_t)codec_fn);
2173 break;
2175 #ifdef AUDIO_HAVE_RECORDING
2176 case Q_ENCODER_LOAD_DISK:
2177 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2179 if (status == CODEC_OK)
2180 break;
2182 logf("Encoder failure");
2183 gui_syncsplash(HZ*2, "Encoder failure");
2185 if (ci.enc_codec_loaded < 0)
2186 break;
2188 logf("Encoder failed to load");
2189 ci.enc_codec_loaded = -1;
2190 break;
2191 #endif /* AUDIO_HAVE_RECORDING */
2193 default:
2194 LOGFQUEUE("codec < default");
2196 } /* end switch */
2201 /* --- Audio thread --- */
2203 #if 0
2204 static bool audio_filebuf_is_lowdata(void)
2206 return bufused() < AUDIO_FILEBUF_CRITICAL;
2208 #endif
2210 static bool audio_have_tracks(void)
2212 return track_ridx != track_widx || CUR_TI->filesize;
2215 static bool audio_have_free_tracks(void)
2217 if (track_widx < track_ridx)
2218 return track_widx + 1 < track_ridx;
2219 else if (track_ridx == 0)
2220 return track_widx < MAX_TRACK - 1;
2222 return true;
2225 int audio_track_count(void)
2227 if (audio_have_tracks())
2229 int relative_track_widx = track_widx;
2231 if (track_ridx > track_widx)
2232 relative_track_widx += MAX_TRACK;
2234 return relative_track_widx - track_ridx + 1;
2237 return 0;
2240 long audio_filebufused(void)
2242 return (long) bufused();
2245 #if 0
2246 /* Count the data BETWEEN the selected tracks */
2247 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2249 size_t amount = 0;
2250 bool need_wrap = to_track < from_track;
2252 while (1)
2254 if (++from_track >= MAX_TRACK)
2256 from_track -= MAX_TRACK;
2257 need_wrap = false;
2260 if (from_track >= to_track && !need_wrap)
2261 break;
2263 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2265 return amount;
2267 #endif
2269 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2271 (void)new_track_ridx;
2272 (void)old_track_ridx;
2273 #if 0
2274 size_t amount;
2276 /* Start with the remainder of the previously playing track */
2277 amount = tracks[old_track_ridx].filesize - ci.curpos;
2278 /* Then collect all data from tracks in between them */
2279 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2280 logf("bwf:%ldB", (long) amount);
2282 if (amount > bufused())
2283 return false;
2285 /* Wind the buffer to the beginning of the target track or its codec */
2286 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2287 #endif
2288 return true;
2291 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2293 (void)new_track_ridx;
2294 (void)old_track_ridx;
2295 #if 0
2296 /* Available buffer data */
2297 size_t buf_back;
2298 /* Start with the previously playing track's data and our data */
2299 size_t amount;
2301 amount = ci.curpos;
2302 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2304 /* If we're not just resetting the current track */
2305 if (new_track_ridx != old_track_ridx)
2307 /* Need to wind to before the old track's codec and our filesize */
2308 amount += tracks[old_track_ridx].codecsize;
2309 amount += tracks[new_track_ridx].filesize;
2311 /* Rewind the old track to its beginning */
2312 tracks[old_track_ridx].available =
2313 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2316 /* If the codec was ever buffered */
2317 if (tracks[new_track_ridx].codecsize)
2319 /* Add the codec to the needed size */
2320 amount += tracks[new_track_ridx].codecsize;
2321 tracks[new_track_ridx].has_codec = true;
2324 /* Then collect all data from tracks between new and old */
2325 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2327 /* Do we have space to make this skip? */
2328 if (amount > buf_back)
2329 return false;
2331 logf("bwb:%ldB",amount);
2333 /* Rewind the buffer to the beginning of the target track or its codec */
2334 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2336 /* Reset to the beginning of the new track */
2337 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2338 #endif
2339 return true;
2342 static void audio_update_trackinfo(void)
2344 ci.filesize = CUR_TI->filesize;
2345 curtrack_id3.elapsed = 0;
2346 curtrack_id3.offset = 0;
2347 ci.id3 = &curtrack_id3;
2348 ci.curpos = 0;
2349 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2352 #if 0
2353 /* Yield to codecs for as long as possible if they are in need of data
2354 * return true if the caller should break to let the audio thread process
2355 * new events */
2356 static bool audio_yield_codecs(void)
2358 yield();
2360 if (!queue_empty(&audio_queue))
2361 return true;
2363 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2364 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2366 if (filling)
2367 yield();
2368 else
2369 sleep(2);
2371 if (!queue_empty(&audio_queue))
2372 return true;
2375 return false;
2377 #endif
2379 static void audio_clear_track_entries(bool clear_unbuffered)
2381 int cur_idx = track_widx;
2382 int last_idx = -1;
2384 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2386 /* Loop over all tracks from write-to-read */
2387 while (1)
2389 cur_idx++;
2390 cur_idx &= MAX_TRACK_MASK;
2392 if (cur_idx == track_ridx)
2393 break;
2395 /* If the track is buffered, conditionally clear/notify,
2396 * otherwise clear the track if that option is selected */
2397 if (tracks[cur_idx].event_sent)
2399 if (last_idx >= 0)
2401 /* If there is an unbuffer callback, call it, otherwise,
2402 * just clear the track */
2403 if (track_unbuffer_callback)
2404 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2406 clear_track_info(&tracks[last_idx]);
2408 last_idx = cur_idx;
2410 else if (clear_unbuffered)
2411 clear_track_info(&tracks[cur_idx]);
2414 /* We clear the previous instance of a buffered track throughout
2415 * the above loop to facilitate 'last' detection. Clear/notify
2416 * the last track here */
2417 if (last_idx >= 0)
2419 if (track_unbuffer_callback)
2420 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2421 clear_track_info(&tracks[last_idx]);
2425 static void audio_release_tracks(void)
2427 int cur_idx = track_ridx;
2429 logf("releasing all tracks");
2431 while (1)
2433 clear_track_info(&tracks[cur_idx]);
2435 cur_idx++;
2436 cur_idx &= MAX_TRACK_MASK;
2438 if (cur_idx == track_widx)
2439 break;
2443 #if 0
2444 /* FIXME: This code should be made more generic and move to metadata.c */
2445 static void audio_strip_tags(void)
2447 int i;
2448 static const unsigned char tag[] = "TAG";
2449 static const unsigned char apetag[] = "APETAGEX";
2450 size_t tag_idx;
2451 size_t cur_idx;
2452 size_t len, version;
2454 tag_idx = RINGBUF_SUB(buf_widx, 128);
2456 if (bufused() > 128 && tag_idx > buf_ridx)
2458 cur_idx = tag_idx;
2459 for(i = 0;i < 3;i++)
2461 if(filebuf[cur_idx] != tag[i])
2462 goto strip_ape_tag;
2464 cur_idx = RINGBUF_ADD(cur_idx, 1);
2467 /* Skip id3v1 tag */
2468 logf("Skipping ID3v1 tag");
2469 buf_widx = tag_idx;
2470 tracks[track_widx].available -= 128;
2471 tracks[track_widx].filesize -= 128;
2474 strip_ape_tag:
2475 /* Check for APE tag (look for the APE tag footer) */
2476 tag_idx = RINGBUF_SUB(buf_widx, 32);
2478 if (bufused() > 32 && tag_idx > buf_ridx)
2480 cur_idx = tag_idx;
2481 for(i = 0;i < 8;i++)
2483 if(filebuf[cur_idx] != apetag[i])
2484 return;
2486 cur_idx = RINGBUF_ADD(cur_idx, 1);
2489 /* Read the version and length from the footer */
2490 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2491 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2492 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2493 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2494 if (version == 2000)
2495 len += 32; /* APEv2 has a 32 byte header */
2497 /* Skip APE tag */
2498 if (bufused() > len)
2500 logf("Skipping APE tag (%ldB)", len);
2501 buf_widx = RINGBUF_SUB(buf_widx, len);
2502 tracks[track_widx].available -= len;
2503 tracks[track_widx].filesize -= len;
2507 #endif
2509 #if 0
2510 /* Returns true if a whole file is read, false otherwise */
2511 static bool audio_read_file(size_t minimum)
2513 bool ret_val = false;
2515 /* If we're called and no file is open, this is an error */
2516 if (current_fd < 0)
2518 logf("Bad fd in arf");
2519 /* Give some hope of miraculous recovery by forcing a track reload */
2520 tracks[track_widx].filesize = 0;
2521 /* Stop this buffering run */
2522 return ret_val;
2525 trigger_cpu_boost();
2526 while (tracks[track_widx].filerem > 0)
2528 size_t copy_n;
2529 int overlap;
2530 int rc;
2532 /* copy_n is the largest chunk that is safe to read */
2533 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2535 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2536 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2537 break;
2539 /* rc is the actual amount read */
2540 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2542 if (rc < 0)
2544 logf("File ended %ldB early", tracks[track_widx].filerem);
2545 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2546 tracks[track_widx].filerem = 0;
2547 break;
2550 /* How much of the playing track did we overwrite */
2551 if (buf_widx == CUR_TI->buf_idx)
2553 /* Special handling; zero or full overlap? */
2554 if (track_widx == track_ridx && CUR_TI->available == 0)
2555 overlap = 0;
2556 else
2557 overlap = rc;
2559 else
2560 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2562 if ((unsigned)rc > tracks[track_widx].filerem)
2564 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2565 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2566 tracks[track_widx].filerem = rc;
2569 /* Advance buffer */
2570 buf_widx = RINGBUF_ADD(buf_widx, rc);
2571 tracks[track_widx].available += rc;
2572 tracks[track_widx].filerem -= rc;
2574 /* If we write into the playing track, adjust it's buffer info */
2575 if (overlap > 0)
2577 CUR_TI->buf_idx += overlap;
2578 CUR_TI->start_pos += overlap;
2581 /* For a rebuffer, fill at least this minimum */
2582 if (minimum > (unsigned)rc)
2583 minimum -= rc;
2584 /* Let the codec process up to the watermark */
2585 /* Break immediately if this is a quick buffer, or there is an event */
2586 else if (minimum || audio_yield_codecs())
2588 /* Exit quickly, but don't stop the overall buffering process */
2589 ret_val = true;
2590 break;
2594 if (tracks[track_widx].filerem == 0)
2596 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2597 close(current_fd);
2598 current_fd = -1;
2599 audio_strip_tags();
2601 track_widx++;
2602 track_widx &= MAX_TRACK_MASK;
2604 tracks[track_widx].filesize = 0;
2605 return true;
2607 else
2609 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2610 tracks[track_widx].filesize - tracks[track_widx].filerem);
2611 return ret_val;
2614 #endif
2616 static bool audio_loadcodec(bool start_play)
2618 int fd;
2619 int prev_track;
2620 char codec_path[MAX_PATH]; /* Full path to codec */
2622 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play ? "true" : "false");
2624 if (tracks[track_widx].id3_hid <= 0) {
2625 DEBUGF("track ID3 info not ready\n");
2626 return false;
2629 const char * codec_fn =
2630 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2631 if (codec_fn == NULL)
2632 return false;
2634 tracks[track_widx].codec_hid = 0;
2636 if (start_play)
2638 /* Load the codec directly from disk and save some memory. */
2639 track_ridx = track_widx;
2640 ci.filesize = CUR_TI->filesize;
2641 ci.id3 = &curtrack_id3;
2642 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2643 ci.curpos = 0;
2644 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2645 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2646 return true;
2648 else
2650 /* If we already have another track than this one buffered */
2651 if (track_widx != track_ridx)
2653 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2655 /* If the previous codec is the same as this one, there is no need
2656 * to put another copy of it on the file buffer */
2657 if (get_codec_base_type(
2658 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2659 get_codec_base_type(
2660 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2661 && audio_codec_loaded)
2663 logf("Reusing prev. codec");
2664 return true;
2669 codec_get_full_path(codec_path, codec_fn);
2671 fd = open(codec_path, O_RDONLY);
2672 if (fd < 0)
2674 logf("Codec doesn't exist!");
2675 return false;
2678 tracks[track_widx].codecsize = filesize(fd);
2680 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2681 if (tracks[track_widx].codec_hid < 0)
2683 logf("Not enough space");
2684 close(fd);
2685 return false;
2688 close(fd);
2689 logf("Loaded codec");
2691 return true;
2694 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2695 static void audio_set_elapsed(struct mp3entry* id3)
2697 unsigned long offset = id3->offset > id3->first_frame_offset ?
2698 id3->offset - id3->first_frame_offset : 0;
2700 if ( id3->vbr ) {
2701 if ( id3->has_toc ) {
2702 /* calculate elapsed time using TOC */
2703 int i;
2704 unsigned int remainder, plen, relpos, nextpos;
2706 /* find wich percent we're at */
2707 for (i=0; i<100; i++ )
2708 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2709 break;
2711 i--;
2712 if (i < 0)
2713 i = 0;
2715 relpos = id3->toc[i];
2717 if (i < 99)
2718 nextpos = id3->toc[i+1];
2719 else
2720 nextpos = 256;
2722 remainder = offset - (relpos * (id3->filesize / 256));
2724 /* set time for this percent (divide before multiply to prevent
2725 overflow on long files. loss of precision is negligible on
2726 short files) */
2727 id3->elapsed = i * (id3->length / 100);
2729 /* calculate remainder time */
2730 plen = (nextpos - relpos) * (id3->filesize / 256);
2731 id3->elapsed += (((remainder * 100) / plen) *
2732 (id3->length / 10000));
2734 else {
2735 /* no TOC exists. set a rough estimate using average bitrate */
2736 int tpk = id3->length /
2737 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2738 1024);
2739 id3->elapsed = offset / 1024 * tpk;
2742 else
2744 /* constant bitrate, use exact calculation */
2745 if (id3->bitrate != 0)
2746 id3->elapsed = offset / (id3->bitrate / 8);
2750 /* Load one track by making the appropriate bufopen calls. Return true if
2751 everything required was loaded correctly, false if not. */
2752 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2754 (void)rebuffer;
2755 char *trackname;
2756 char msgbuf[80];
2757 int fd;
2758 int file_offset = 0;
2759 struct mp3entry id3;
2761 /* Stop buffer filling if there is no free track entries.
2762 Don't fill up the last track entry (we wan't to store next track
2763 metadata there). */
2764 if (!audio_have_free_tracks())
2766 logf("No free tracks");
2767 return false;
2770 last_peek_offset++;
2771 peek_again:
2772 logf("Buffering track:%d/%d", track_widx, track_ridx);
2773 /* Get track name from current playlist read position. */
2774 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2776 /* Handle broken playlists. */
2777 fd = open(trackname, O_RDONLY);
2778 if (fd < 0)
2780 logf("Open failed");
2781 /* Skip invalid entry from playlist. */
2782 playlist_skip_entry(NULL, last_peek_offset);
2784 else
2785 break;
2788 if (!trackname)
2790 logf("End-of-playlist");
2791 playlist_end = true;
2792 return false;
2795 tracks[track_widx].filesize = filesize(fd);
2797 /* Set default values */
2798 if (start_play)
2800 int last_codec = current_codec;
2802 set_current_codec(CODEC_IDX_AUDIO);
2803 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2804 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2805 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2806 dsp_configure(DSP_RESET, 0);
2807 set_current_codec(last_codec);
2809 track_changed = true;
2810 playlist_update_resume_info(audio_current_track());
2813 /* Get track metadata if we don't already have it. */
2814 if (tracks[track_widx].id3_hid <= 0)
2816 if (get_metadata(&id3, fd, trackname))
2818 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2819 TYPE_ID3);
2820 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2822 if (tracks[track_widx].id3_hid <= 0)
2824 DEBUGF("failed to allocate space for metadata\n");
2825 last_peek_offset--;
2826 close(fd);
2827 return false;
2830 if (track_widx == track_ridx)
2831 copy_mp3entry(&curtrack_id3, &id3);
2832 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2833 copy_mp3entry(&nexttrack_id3, &id3);
2835 if (start_play)
2837 track_changed = true;
2838 playlist_update_resume_info(audio_current_track());
2841 else
2843 logf("mde:%s!",trackname);
2845 /* Skip invalid entry from playlist. */
2846 playlist_skip_entry(NULL, last_peek_offset);
2847 tracks[track_widx].taginfo_ready = false;
2848 goto peek_again;
2853 close(fd);
2855 #if 0
2856 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2858 char cuepath[MAX_PATH];
2860 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2862 if (look_for_cuesheet_file(trackname, cuepath) &&
2863 parse_cuesheet(cuepath, cue))
2865 strcpy((cue)->audio_filename, trackname);
2866 if (start_play)
2867 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2870 #endif
2872 /* Load the codec. */
2873 if (!audio_loadcodec(start_play))
2875 if (tracks[track_widx].codecsize)
2877 /* No space for codec on buffer, not an error */
2878 tracks[track_widx].codecsize = 0;
2879 return false;
2882 /* This is an error condition, either no codec was found, or reading
2883 * the codec file failed part way through, either way, skip the track */
2884 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2885 /* We should not use gui_syncplash from audio thread! */
2886 gui_syncsplash(HZ*2, msgbuf);
2887 /* Skip invalid entry from playlist. */
2888 playlist_skip_entry(NULL, last_peek_offset);
2889 tracks[track_widx].taginfo_ready = false;
2890 goto peek_again;
2893 struct mp3entry *track_id3;
2895 if (track_widx == track_ridx)
2896 track_id3 = &curtrack_id3;
2897 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2898 track_id3 = &nexttrack_id3;
2899 else
2900 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2902 set_filebuf_watermark(buffer_margin);
2903 track_id3->elapsed = 0;
2905 if (offset > 0)
2907 switch (track_id3->codectype) {
2908 case AFMT_MPA_L1:
2909 case AFMT_MPA_L2:
2910 case AFMT_MPA_L3:
2911 file_offset = offset;
2912 track_id3->offset = offset;
2913 audio_set_elapsed(track_id3);
2914 ci.curpos = offset;
2915 break;
2917 case AFMT_WAVPACK:
2918 file_offset = offset;
2919 track_id3->offset = offset;
2920 track_id3->elapsed = track_id3->length / 2;
2921 ci.curpos = offset;
2922 break;
2924 case AFMT_OGG_VORBIS:
2925 case AFMT_SPEEX:
2926 case AFMT_FLAC:
2927 case AFMT_PCM_WAV:
2928 case AFMT_A52:
2929 case AFMT_AAC:
2930 case AFMT_MPC:
2931 case AFMT_APE:
2932 track_id3->offset = offset;
2933 break;
2937 logf("alt:%s", trackname);
2939 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, TYPE_AUDIO);
2941 if (tracks[track_widx].audio_hid <= 0)
2942 return false;
2944 if (start_play)
2946 LOGFQUEUE("audio >| buffering Q_BUFFER_HANDLE");
2947 queue_send(&buffering_queue, Q_BUFFER_HANDLE, tracks[track_widx].audio_hid);
2950 track_widx++;
2951 track_widx &= MAX_TRACK_MASK;
2953 return true;
2956 #if 0
2957 static bool audio_read_next_metadata(void)
2959 int fd;
2960 char *trackname;
2961 int next_idx;
2962 int status;
2964 next_idx = track_widx;
2965 if (tracks[next_idx].id3_hid > 0)
2967 next_idx++;
2968 next_idx &= MAX_TRACK_MASK;
2970 if (tracks[next_idx].id3_hid > 0)
2971 return true;
2974 trackname = playlist_peek(last_peek_offset + 1);
2975 if (!trackname)
2976 return false;
2978 fd = open(trackname, O_RDONLY);
2979 if (fd < 0)
2980 return false;
2982 struct mp3entry id3;
2984 status = get_metadata(&id3, fd, trackname);
2985 /* Preload the glyphs in the tags */
2986 if (status)
2988 tracks[next_idx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
2990 if (tracks[next_idx].id3_hid > 0)
2992 tracks[next_idx].taginfo_ready = true;
2993 if (id3.title)
2994 lcd_getstringsize(id3.title, NULL, NULL);
2995 if (id3.artist)
2996 lcd_getstringsize(id3.artist, NULL, NULL);
2997 if (id3.album)
2998 lcd_getstringsize(id3.album, NULL, NULL);
3000 else
3001 status = false;
3003 close(fd);
3005 return status;
3007 #endif
3009 /* Send callback events to notify about new tracks. */
3010 static void audio_generate_postbuffer_events(void)
3012 int cur_idx;
3013 int last_idx = -1;
3015 logf("Postbuffer:%d/%d",track_ridx,track_widx);
3017 if (audio_have_tracks())
3019 cur_idx = track_ridx;
3021 while (1) {
3022 if (!tracks[cur_idx].event_sent)
3024 if (last_idx >= 0 && !tracks[last_idx].event_sent)
3026 /* Mark the event 'sent' even if we don't really send one */
3027 tracks[last_idx].event_sent = true;
3028 if (track_buffer_callback)
3029 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
3031 last_idx = cur_idx;
3033 if (cur_idx == track_widx)
3034 break;
3035 cur_idx++;
3036 cur_idx &= MAX_TRACK_MASK;
3039 if (last_idx >= 0 && !tracks[last_idx].event_sent)
3041 tracks[last_idx].event_sent = true;
3042 if (track_buffer_callback)
3043 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
3048 static bool audio_initialize_buffer_fill(bool clear_tracks)
3050 /* Don't initialize if we're already initialized */
3051 if (filling)
3052 return true;
3054 logf("Starting buffer fill");
3056 /* Set the filling flag true before calling audio_clear_tracks as that
3057 * function can yield and we start looping. */
3058 filling = true;
3060 if (clear_tracks)
3061 audio_clear_track_entries(false);
3063 /* Save the current resume position once. */
3064 playlist_update_resume_info(audio_current_track());
3066 return true;
3069 static void audio_fill_file_buffer(
3070 bool start_play, bool rebuffer, size_t offset)
3072 bool had_next_track = audio_next_track() != NULL;
3073 bool continue_buffering;
3075 /* Must reset the buffer before use if trashed or voice only - voice
3076 file size shouldn't have changed so we can go straight from
3077 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
3078 if (buffer_state != BUFFER_STATE_INITIALIZED)
3079 audio_reset_buffer();
3081 if (!audio_initialize_buffer_fill(!start_play))
3082 return ;
3084 continue_buffering = audio_load_track(offset, start_play, rebuffer);
3086 if (!had_next_track && audio_next_track())
3087 track_changed = true;
3089 /* If we're done buffering */
3090 if (!continue_buffering)
3092 //audio_read_next_metadata();
3094 audio_generate_postbuffer_events();
3095 filling = false;
3097 #ifndef SIMULATOR
3098 ata_sleep();
3099 #endif
3103 static void audio_rebuffer(void)
3105 logf("Forcing rebuffer");
3107 /* Reset track pointers */
3108 track_widx = track_ridx;
3109 audio_clear_track_entries(true);
3111 /* Fill the buffer */
3112 last_peek_offset = -1;
3113 CUR_TI->filesize = 0;
3114 ci.curpos = 0;
3116 if (!CUR_TI->taginfo_ready)
3117 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3119 audio_fill_file_buffer(false, true, 0);
3122 static int audio_check_new_track(void)
3124 DEBUGF("audio_check_new_track\n");
3126 int track_count = audio_track_count();
3127 int old_track_ridx = track_ridx;
3128 int next_idx;
3129 bool forward;
3131 if (dir_skip)
3133 dir_skip = false;
3134 if (playlist_next_dir(ci.new_track))
3136 ci.new_track = 0;
3137 CUR_TI->taginfo_ready = false;
3138 audio_rebuffer();
3139 goto skip_done;
3141 else
3143 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3144 return Q_CODEC_REQUEST_FAILED;
3148 if (new_playlist)
3149 ci.new_track = 0;
3151 /* If the playlist isn't that big */
3152 if (!playlist_check(ci.new_track))
3154 if (ci.new_track >= 0)
3156 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3157 return Q_CODEC_REQUEST_FAILED;
3159 /* Find the beginning backward if the user over-skips it */
3160 while (!playlist_check(++ci.new_track))
3161 if (ci.new_track >= 0)
3163 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3164 return Q_CODEC_REQUEST_FAILED;
3167 /* Update the playlist */
3168 last_peek_offset -= ci.new_track;
3170 if (playlist_next(ci.new_track) < 0)
3172 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3173 return Q_CODEC_REQUEST_FAILED;
3176 if (new_playlist)
3178 ci.new_track = 1;
3179 new_playlist = false;
3182 /* Save the old track */
3183 /* prev_ti = CUR_TI; */
3185 int i, idx;
3186 for (i = 0; i < ci.new_track; i++)
3188 idx = (track_ridx + i) & MAX_TRACK_MASK;
3189 clear_track_info(&tracks[idx]);
3192 /* Move to the new track */
3193 track_ridx += ci.new_track;
3194 track_ridx &= MAX_TRACK_MASK;
3196 if (CUR_TI->id3_hid > 0)
3197 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
3199 next_idx = track_ridx + 1;
3200 next_idx &= MAX_TRACK_MASK;
3202 if (tracks[next_idx].id3_hid > 0)
3203 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
3205 if (automatic_skip)
3206 playlist_end = false;
3208 track_changed = !automatic_skip;
3210 /* If it is not safe to even skip this many track entries */
3211 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3213 ci.new_track = 0;
3214 CUR_TI->taginfo_ready = false;
3215 audio_rebuffer();
3216 goto skip_done;
3219 forward = ci.new_track > 0;
3220 ci.new_track = 0;
3222 /* If the target track is clearly not in memory */
3223 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3225 audio_rebuffer();
3226 goto skip_done;
3229 /* The track may be in memory, see if it really is */
3230 if (forward)
3232 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3233 audio_rebuffer();
3235 else
3237 int cur_idx = track_ridx;
3238 bool taginfo_ready = true;
3239 bool wrap = track_ridx > old_track_ridx;
3241 while (1)
3243 cur_idx++;
3244 cur_idx &= MAX_TRACK_MASK;
3245 if (!(wrap || cur_idx < old_track_ridx))
3246 break;
3248 /* If we hit a track in between without valid tag info, bail */
3249 if (!tracks[cur_idx].taginfo_ready)
3251 taginfo_ready = false;
3252 break;
3255 tracks[cur_idx].available = tracks[cur_idx].filesize;
3256 if (tracks[cur_idx].codecsize)
3257 tracks[cur_idx].has_codec = true;*/
3259 if (taginfo_ready)
3261 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3262 audio_rebuffer();
3264 else
3266 CUR_TI->taginfo_ready = false;
3267 audio_rebuffer();
3271 skip_done:
3272 audio_update_trackinfo();
3273 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3274 return Q_CODEC_REQUEST_COMPLETE;
3277 #if 0
3278 static int audio_rebuffer_and_seek(size_t newpos)
3280 size_t real_preseek;
3281 int fd;
3282 char *trackname;
3284 /* (Re-)open current track's file handle. */
3285 trackname = playlist_peek(0);
3286 fd = open(trackname, O_RDONLY);
3287 if (fd < 0)
3289 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3290 return Q_CODEC_REQUEST_FAILED;
3293 if (current_fd >= 0)
3294 close(current_fd);
3295 current_fd = fd;
3297 playlist_end = false;
3299 ci.curpos = newpos;
3301 /* Clear codec buffer. */
3302 track_widx = track_ridx;
3303 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3305 last_peek_offset = 0;
3306 filling = false;
3307 audio_initialize_buffer_fill(true);
3309 /* This may have been tweaked by the id3v1 code */
3310 CUR_TI->filesize=filesize(fd);
3311 if (newpos > conf_preseek)
3313 CUR_TI->start_pos = newpos - conf_preseek;
3314 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3315 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3316 real_preseek = conf_preseek;
3318 else
3320 CUR_TI->start_pos = 0;
3321 CUR_TI->filerem = CUR_TI->filesize;
3322 real_preseek = newpos;
3325 CUR_TI->available = 0;
3327 audio_read_file(real_preseek);
3329 /* Account for the data we just read that is 'behind' us now */
3330 CUR_TI->available -= real_preseek;
3332 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3334 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3335 return Q_CODEC_REQUEST_COMPLETE;
3337 #endif
3339 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3340 bool last_track))
3342 track_buffer_callback = handler;
3345 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3346 bool last_track))
3348 track_unbuffer_callback = handler;
3351 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3353 track_changed_callback = handler;
3356 unsigned long audio_prev_elapsed(void)
3358 return prev_track_elapsed;
3361 static void audio_stop_codec_flush(void)
3363 ci.stop_codec = true;
3364 pcmbuf_pause(true);
3366 while (audio_codec_loaded)
3367 yield();
3369 /* If the audio codec is not loaded any more, and the audio is still
3370 * playing, it is now and _only_ now safe to call this function from the
3371 * audio thread */
3372 if (pcm_is_playing())
3373 pcmbuf_play_stop();
3374 pcmbuf_pause(paused);
3377 static void audio_stop_playback(void)
3379 /* If we were playing, save resume information */
3380 if (playing)
3382 struct mp3entry *id3 = NULL;
3384 if (!playlist_end || !ci.stop_codec)
3386 /* Set this early, the outside code yields and may allow the codec
3387 to try to wait for a reply on a buffer wait */
3388 ci.stop_codec = true;
3389 id3 = audio_current_track();
3392 /* Save the current playing spot, or NULL if the playlist has ended */
3393 playlist_update_resume_info(id3);
3395 prev_track_elapsed = curtrack_id3.elapsed;
3397 /* Increment index so runtime info is saved in audio_clear_track_entries().
3398 * Done here, as audio_stop_playback() may be called more than once.
3399 * Don't update runtime unless playback is stopped because of end of playlist.
3400 * Updating runtime when manually stopping a tracks, can destroy autoscores
3401 * and playcounts.
3403 if (playlist_end)
3405 track_ridx++;
3406 track_ridx &= MAX_TRACK_MASK;
3410 filling = false;
3411 paused = false;
3412 audio_stop_codec_flush();
3413 playing = false;
3415 /* Close all tracks */
3416 audio_release_tracks();
3418 /* Mark all entries null. */
3419 audio_clear_track_entries(false);
3422 static void audio_play_start(size_t offset)
3424 #if INPUT_SRC_CAPS != 0
3425 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3426 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3427 #endif
3429 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3430 paused = false;
3431 audio_stop_codec_flush();
3433 track_changed = true;
3434 playlist_end = false;
3436 playing = true;
3438 ci.new_track = 0;
3439 ci.seek_time = 0;
3440 wps_offset = 0;
3442 sound_set_volume(global_settings.volume);
3443 track_widx = track_ridx = 0;
3445 /* Mark all entries null. */
3446 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3448 last_peek_offset = -1;
3450 /* Officially playing */
3451 queue_reply(&audio_queue, 1);
3453 audio_fill_file_buffer(true, false, offset);
3455 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3456 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3460 /* Invalidates all but currently playing track. */
3461 static void audio_invalidate_tracks(void)
3463 #if 0
3464 if (audio_have_tracks())
3466 last_peek_offset = 0;
3467 playlist_end = false;
3468 track_widx = track_ridx;
3470 /* Mark all other entries null (also buffered wrong metadata). */
3471 audio_clear_track_entries(true);
3473 /* If the current track is fully buffered, advance the write pointer */
3474 if (tracks[track_widx].filerem == 0)
3475 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3477 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3479 audio_read_next_metadata();
3481 #endif
3484 static void audio_new_playlist(void)
3486 /* Prepare to start a new fill from the beginning of the playlist */
3487 last_peek_offset = -1;
3488 if (audio_have_tracks())
3490 if (paused)
3491 skipped_during_pause = true;
3492 playlist_end = false;
3493 track_widx = track_ridx;
3494 audio_clear_track_entries(true);
3496 track_widx++;
3497 track_widx &= MAX_TRACK_MASK;
3499 /* Mark the current track as invalid to prevent skipping back to it */
3500 CUR_TI->taginfo_ready = false;
3503 /* Signal the codec to initiate a track change forward */
3504 new_playlist = true;
3505 ci.new_track = 1;
3507 /* Officially playing */
3508 queue_reply(&audio_queue, 1);
3510 audio_fill_file_buffer(false, true, 0);
3513 static void audio_initiate_track_change(long direction)
3515 playlist_end = false;
3516 ci.new_track += direction;
3517 wps_offset -= direction;
3518 if (paused)
3519 skipped_during_pause = true;
3522 static void audio_initiate_dir_change(long direction)
3524 playlist_end = false;
3525 dir_skip = true;
3526 ci.new_track = direction;
3527 if (paused)
3528 skipped_during_pause = true;
3532 * Layout audio buffer as follows - iram buffer depends on target:
3533 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3535 static void audio_reset_buffer(void)
3537 /* see audio_get_recording_buffer if this is modified */
3538 logf("audio_reset_buffer");
3540 /* If the setup of anything allocated before the file buffer is
3541 changed, do check the adjustments after the buffer_alloc call
3542 as it will likely be affected and need sliding over */
3544 /* Initially set up file buffer as all space available */
3545 malloc_buf = audiobuf + talk_get_bufsize();
3546 /* Align the malloc buf to line size. Especially important to cf
3547 targets that do line reads/writes. */
3548 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3549 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3550 filebuflen = audiobufend - filebuf;
3552 /* Allow for codec swap space at end of audio buffer */
3553 if (talk_voice_required())
3555 /* Layout of swap buffer:
3556 * #ifdef IRAM_STEAL (dedicated iram_buf):
3557 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3558 * #else:
3559 * audiobuf...|dram_buf|iram_buf|audiobufend
3561 #ifdef PLAYBACK_VOICE
3562 /* Check for an absolutely nasty situation which should never,
3563 ever happen - frankly should just panic */
3564 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3566 logf("buffer reset with voice swapped");
3568 /* line align length which line aligns the calculations below since
3569 all sizes are also at least line aligned - needed for memswap128 */
3570 filebuflen &= ~15;
3571 #ifdef IRAM_STEAL
3572 filebuflen -= CODEC_SIZE;
3573 #else
3574 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3575 #endif
3576 /* Allocate buffers for swapping voice <=> audio */
3577 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3578 and out of the way of buffer usage or else a call to audio_get_buffer
3579 and subsequent buffer use might trash the swap space. A plugin
3580 initializing IRAM after getting the full buffer would present similar
3581 problem. Options include: failing the request if the other buffer
3582 has been obtained already or never allowing use of the voice IRAM
3583 buffer within the audio buffer. Using buffer_alloc basically
3584 implements the second in a more convenient way. */
3585 dram_buf = filebuf + filebuflen;
3587 #ifdef IRAM_STEAL
3588 /* Allocate voice IRAM swap buffer once */
3589 if (iram_buf == NULL)
3591 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3592 /* buffer_alloc moves audiobuf; this is safe because only the end
3593 * has been touched so far in this function and the address of
3594 * filebuf + filebuflen is not changed */
3595 malloc_buf += CODEC_IRAM_SIZE;
3596 filebuf += CODEC_IRAM_SIZE;
3597 filebuflen -= CODEC_IRAM_SIZE;
3599 #else
3600 /* Allocate iram_buf after dram_buf */
3601 iram_buf = dram_buf + CODEC_SIZE;
3602 #endif /* IRAM_STEAL */
3603 #endif /* PLAYBACK_VOICE */
3605 else
3607 #ifdef PLAYBACK_VOICE
3608 /* No swap buffers needed */
3609 iram_buf = NULL;
3610 dram_buf = NULL;
3611 #endif
3614 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3615 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3617 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3618 will already be line aligned */
3619 filebuflen &= ~3;
3621 /* Set the high watermark as 75% full...or 25% empty :) */
3622 #if MEM > 8
3623 high_watermark = 3*filebuflen / 4;
3624 #endif
3626 /* Clear any references to the file buffer */
3627 buffer_state = BUFFER_STATE_INITIALIZED;
3629 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3630 /* Make sure everything adds up - yes, some info is a bit redundant but
3631 aids viewing and the sumation of certain variables should add up to
3632 the location of others. */
3634 size_t pcmbufsize;
3635 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3636 logf("mabuf: %08X", (unsigned)malloc_buf);
3637 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3638 logf("fbuf: %08X", (unsigned)filebuf);
3639 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3640 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3641 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3642 logf("pcmb: %08X", (unsigned)pcmbuf);
3643 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3644 if (dram_buf)
3646 logf("dramb: %08X", (unsigned)dram_buf);
3647 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3649 if (iram_buf)
3651 logf("iramb: %08X", (unsigned)iram_buf);
3652 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3655 #endif
3658 #if MEM > 8
3659 /* we dont want this rebuffering on targets with little ram
3660 because the disk may never spin down */
3661 static bool ata_fillbuffer_callback(void)
3663 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3664 return true;
3666 #endif
3668 static void audio_thread(void)
3670 struct queue_event ev;
3672 pcm_postinit();
3674 #ifdef PLAYBACK_VOICE
3675 /* Unlock semaphore that init stage locks before creating this thread */
3676 semaphore_release(&sem_codecthread);
3678 /* Buffers must be set up by now - should panic - really */
3679 if (buffer_state != BUFFER_STATE_INITIALIZED)
3681 logf("audio_thread start: no buffer");
3684 /* Have to wait for voice to load up or else the codec swap will be
3685 invalid when an audio codec is loaded */
3686 wait_for_voice_swap_in();
3687 #endif
3689 while (1)
3691 if (filling)
3693 queue_wait_w_tmo(&audio_queue, &ev, 0);
3694 if (ev.id == SYS_TIMEOUT)
3695 ev.id = Q_AUDIO_FILL_BUFFER;
3697 else
3699 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3700 #if MEM > 8
3701 if (playing && (ev.id == SYS_TIMEOUT) &&
3702 (bufused() < high_watermark))
3703 register_ata_idle_func(ata_fillbuffer_callback);
3704 #endif
3707 switch (ev.id) {
3708 #if MEM > 8
3709 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3710 /* only fill if the disk is still spining */
3711 #ifndef SIMULATOR
3712 if (!ata_disk_is_active())
3713 break;
3714 #endif
3715 #endif /* MEM > 8 */
3716 /* else fall through to Q_AUDIO_FILL_BUFFER */
3717 case Q_AUDIO_FILL_BUFFER:
3718 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3719 if (!filling)
3720 if (!playing || playlist_end || ci.stop_codec)
3721 break;
3722 audio_fill_file_buffer(false, false, 0);
3723 break;
3725 case Q_AUDIO_PLAY:
3726 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3727 if (playing && ev.data <= 0)
3728 audio_new_playlist();
3729 else
3731 audio_stop_playback();
3732 audio_play_start((size_t)ev.data);
3734 break;
3736 case Q_AUDIO_STOP:
3737 LOGFQUEUE("audio < Q_AUDIO_STOP");
3738 if (playing)
3739 audio_stop_playback();
3740 if (ev.data != 0)
3741 queue_clear(&audio_queue);
3742 break;
3744 case Q_AUDIO_PAUSE:
3745 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3746 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3747 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3748 skipped_during_pause = false;
3749 if (!playing)
3750 break;
3751 pcmbuf_pause((bool)ev.data);
3752 paused = (bool)ev.data;
3753 break;
3755 case Q_AUDIO_SKIP:
3756 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3757 audio_initiate_track_change((long)ev.data);
3758 break;
3760 case Q_AUDIO_PRE_FF_REWIND:
3761 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3762 if (!playing)
3763 break;
3764 pcmbuf_pause(true);
3765 break;
3767 case Q_AUDIO_FF_REWIND:
3768 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3769 if (!playing)
3770 break;
3771 ci.seek_time = (long)ev.data+1;
3772 break;
3774 #if 0
3775 case Q_AUDIO_REBUFFER_SEEK:
3776 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3777 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3778 break;
3779 #endif
3781 case Q_AUDIO_CHECK_NEW_TRACK:
3782 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3783 queue_reply(&audio_queue, audio_check_new_track());
3784 break;
3786 case Q_AUDIO_DIR_SKIP:
3787 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3788 playlist_end = false;
3789 audio_initiate_dir_change(ev.data);
3790 break;
3792 case Q_AUDIO_FLUSH:
3793 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3794 audio_invalidate_tracks();
3795 break;
3797 case Q_AUDIO_TRACK_CHANGED:
3798 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3799 if (track_changed_callback)
3800 track_changed_callback(&curtrack_id3);
3801 track_changed = true;
3802 playlist_update_resume_info(audio_current_track());
3803 break;
3805 #ifndef SIMULATOR
3806 case SYS_USB_CONNECTED:
3807 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3808 if (playing)
3809 audio_stop_playback();
3810 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3811 usb_wait_for_disconnect(&audio_queue);
3812 break;
3813 #endif
3815 case SYS_TIMEOUT:
3816 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3817 break;
3819 default:
3820 //LOGFQUEUE("audio < default");
3821 break;
3822 } /* end switch */
3823 } /* end while */
3826 #ifdef ROCKBOX_HAS_LOGF
3827 static void audio_test_track_changed_event(struct mp3entry *id3)
3829 (void)id3;
3831 logf("tce:%s", id3->path);
3833 #endif
3835 /* Initialize the audio system - called from init() in main.c.
3836 * Last function because of all the references to internal symbols
3838 void audio_init(void)
3840 #ifdef PLAYBACK_VOICE
3841 static bool voicetagtrue = true;
3842 static struct mp3entry id3_voice;
3843 struct thread_entry *voice_thread_p = NULL;
3844 #endif
3845 struct thread_entry *audio_thread_p;
3847 /* Can never do this twice */
3848 if (audio_is_initialized)
3850 logf("audio: already initialized");
3851 return;
3854 logf("audio: initializing");
3856 /* Initialize queues before giving control elsewhere in case it likes
3857 to send messages. Thread creation will be delayed however so nothing
3858 starts running until ready if something yields such as talk_init. */
3859 #ifdef PLAYBACK_VOICE
3860 /* Take ownership of lock to prevent playback of anything before audio
3861 hardware is initialized - audio thread unlocks it after final init
3862 stage */
3863 semaphore_init(&sem_codecthread, 1, 0);
3864 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3865 #endif
3866 queue_init(&audio_queue, true);
3867 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3868 queue_init(&codec_queue, true);
3869 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3871 pcm_init();
3873 #ifdef ROCKBOX_HAS_LOGF
3874 audio_set_track_changed_event(audio_test_track_changed_event);
3875 #endif
3877 /* Initialize codec api. */
3878 ci.read_filebuf = codec_filebuf_callback;
3879 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3880 ci.get_codec_memory = codec_get_memory_callback;
3881 ci.request_buffer = codec_request_buffer_callback;
3882 ci.advance_buffer = codec_advance_buffer_callback;
3883 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3884 ci.request_next_track = codec_request_next_track_callback;
3885 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3886 ci.seek_buffer = codec_seek_buffer_callback;
3887 ci.seek_complete = codec_seek_complete_callback;
3888 ci.set_elapsed = codec_set_elapsed_callback;
3889 ci.set_offset = codec_set_offset_callback;
3890 ci.configure = codec_configure_callback;
3891 ci.discard_codec = codec_discard_codec_callback;
3893 /* Initialize voice codec api. */
3894 #ifdef PLAYBACK_VOICE
3895 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3896 memset(&id3_voice, 0, sizeof(id3_voice));
3897 ci_voice.read_filebuf = voice_filebuf_callback;
3898 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3899 ci_voice.get_codec_memory = voice_get_memory_callback;
3900 ci_voice.request_buffer = voice_request_buffer_callback;
3901 ci_voice.advance_buffer = voice_advance_buffer_callback;
3902 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3903 ci_voice.request_next_track = voice_request_next_track_callback;
3904 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3905 ci_voice.seek_buffer = voice_seek_buffer_callback;
3906 ci_voice.seek_complete = voice_do_nothing;
3907 ci_voice.set_elapsed = voice_set_elapsed_callback;
3908 ci_voice.set_offset = voice_set_offset_callback;
3909 ci_voice.configure = voice_configure_callback;
3910 ci_voice.discard_codec = voice_do_nothing;
3911 ci_voice.taginfo_ready = &voicetagtrue;
3912 ci_voice.id3 = &id3_voice;
3913 id3_voice.frequency = 11200;
3914 id3_voice.length = 1000000L;
3915 #endif
3917 /* initialize the buffer */
3918 filebuf = audiobuf;
3920 /* audio_reset_buffer must to know the size of voice buffer so init
3921 talk first */
3922 talk_init();
3924 codec_thread_p = create_thread(
3925 codec_thread, codec_stack, sizeof(codec_stack),
3926 CREATE_THREAD_FROZEN,
3927 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3928 IF_COP(, CPU));
3930 audio_thread_p = create_thread(audio_thread, audio_stack,
3931 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3932 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3933 IF_COP(, CPU));
3935 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
3936 sizeof(buffering_stack), CREATE_THREAD_FROZEN,
3937 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3938 IF_COP(, CPU, true));
3940 #ifdef PLAYBACK_VOICE
3941 /* TODO: Change this around when various speech codecs can be used */
3942 if (talk_voice_required())
3944 logf("Starting voice codec");
3945 queue_init(&voice_queue, true);
3946 voice_thread_p = create_thread(voice_thread, voice_stack,
3947 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3948 voice_thread_name
3949 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3951 #endif
3953 /* Set crossfade setting for next buffer init which should be about... */
3954 pcmbuf_crossfade_enable(global_settings.crossfade);
3956 /* ...now! Set up the buffers */
3957 audio_reset_buffer();
3959 buffering_init(filebuf, filebuflen);
3961 /* Probably safe to say */
3962 audio_is_initialized = true;
3964 sound_settings_apply();
3965 #ifdef HAVE_WM8758
3966 eq_hw_enable(global_settings.eq_hw_enabled);
3967 #endif
3968 #ifndef HAVE_FLASH_STORAGE
3969 audio_set_buffer_margin(global_settings.buffer_margin);
3970 #endif
3972 /* it's safe to let the threads run now */
3973 thread_thaw(codec_thread_p);
3974 #ifdef PLAYBACK_VOICE
3975 if (voice_thread_p)
3976 thread_thaw(voice_thread_p);
3977 #endif
3978 thread_thaw(audio_thread_p);
3979 thread_thaw(buffering_thread_p);
3980 } /* audio_init */