Fix tracks being forgotten about when there was no space to allocate an ID3 handle
[Rockbox.git] / apps / playback.c
blob893f38b74d97fbc2b6fe2542aadea187a2269c2e
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 struct mp3entry curtrack_id3;
206 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 *getptr(int handle_id)
379 unsigned char *ptr;
380 ssize_t ret = bufgetdata(handle_id, 0, &ptr);
382 if (ret < 0)
383 return 0;
385 return ptr;
388 void close_track_handles(struct track_info *track)
390 if (!track)
391 return;
393 if (track->codec_hid > 0) {
394 bufclose(track->codec_hid);
395 track->codec_hid = 0;
398 if (track->id3_hid > 0) {
399 bufclose(track->id3_hid);
400 track->id3_hid = 0;
403 if (track->audio_hid > 0) {
404 bufclose(track->audio_hid);
405 track->audio_hid = 0;
409 /* --- External interfaces --- */
411 void mp3_play_data(const unsigned char* start, int size,
412 void (*get_more)(unsigned char** start, size_t* size))
414 #ifdef PLAYBACK_VOICE
415 static struct voice_info voice_clip;
416 voice_clip.callback = get_more;
417 voice_clip.buf = (unsigned char*)start;
418 voice_clip.size = size;
419 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
420 queue_post(&voice_queue, Q_VOICE_STOP, 0);
421 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
422 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
423 voice_thread_start = true;
424 trigger_cpu_boost();
425 #else
426 (void) start;
427 (void) size;
428 (void) get_more;
429 #endif
432 void mp3_play_stop(void)
434 #ifdef PLAYBACK_VOICE
435 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
436 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
437 queue_post(&voice_queue, Q_VOICE_STOP, 1);
438 #endif
441 void mp3_play_pause(bool play)
443 /* a dummy */
444 (void)play;
447 bool mp3_is_playing(void)
449 #ifdef PLAYBACK_VOICE
450 return voice_is_playing;
451 #else
452 return false;
453 #endif
456 /* If voice could be swapped out - wait for it to return
457 * Used by buffer claming functions.
459 static void wait_for_voice_swap_in(void)
461 #ifdef PLAYBACK_VOICE
462 if (NULL == iram_buf)
463 return;
465 event_wait(&event_codecthread, STATE_NONSIGNALED);
466 #endif /* PLAYBACK_VOICE */
469 /* This sends a stop message and the audio thread will dump all it's
470 subsequenct messages */
471 static void audio_hard_stop(void)
473 /* Stop playback */
474 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
475 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
478 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
480 unsigned char *buf, *end;
482 if (audio_is_initialized)
484 audio_hard_stop();
485 wait_for_voice_swap_in();
486 #ifdef PLAYBACK_VOICE
487 voice_stop();
488 #endif
490 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
492 if (buffer_size == NULL)
494 /* Special case for talk_init to use since it already knows it's
495 trashed */
496 buffer_state = BUFFER_STATE_TRASHED;
497 return NULL;
500 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
501 || !talk_voice_required())
503 logf("get buffer: talk, audio");
504 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
505 the talk buffer is not needed because voice isn't being used, or
506 could be BUFFER_STATE_TRASHED already. If state is
507 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
508 without the caller knowing what's going on. Changing certain settings
509 may move it to a worse condition but the memory in use by something
510 else will remain undisturbed.
512 if (buffer_state != BUFFER_STATE_TRASHED)
514 talk_buffer_steal();
515 buffer_state = BUFFER_STATE_TRASHED;
518 buf = audiobuf;
519 end = audiobufend;
521 else
523 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
524 still BUFFER_STATE_INITIALIZED */
525 /* Skip talk buffer and move pcm buffer to end to maximize available
526 contiguous memory - no audio running means voice will not need the
527 swap space */
528 logf("get buffer: audio");
529 buf = audiobuf + talk_get_bufsize();
530 end = audiobufend - pcmbuf_init(audiobufend);
531 buffer_state = BUFFER_STATE_VOICED_ONLY;
534 *buffer_size = end - buf;
536 return buf;
539 #ifdef IRAM_STEAL
540 void audio_iram_steal(void)
542 /* We need to stop audio playback in order to use codec IRAM */
543 audio_hard_stop();
545 #ifdef PLAYBACK_VOICE
546 if (NULL != iram_buf)
548 /* Can't already be stolen */
549 if (voice_iram_stolen)
550 return;
552 /* Must wait for voice to be current again if it is swapped which
553 would cause the caller's buffer to get clobbered when voice locks
554 and runs - we'll wait for it to lock and yield again then make sure
555 the ride has come to a complete stop */
556 wait_for_voice_swap_in();
557 voice_stop();
559 /* Save voice IRAM but just memcpy - safe to do here since voice
560 is current and no audio codec is loaded */
561 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
562 voice_iram_stolen = true;
564 else
566 /* Nothing much to do if no voice */
567 voice_iram_stolen = false;
569 #endif
571 #endif /* IRAM_STEAL */
573 #ifdef HAVE_RECORDING
574 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
576 /* Don't allow overwrite of voice swap area or we'll trash the
577 swapped-out voice codec but can use whole thing if none */
578 unsigned char *end;
580 /* Stop audio and voice. Wait for voice to swap in and be clear
581 of pending events to ensure trouble-free operation of encoders */
582 audio_hard_stop();
583 wait_for_voice_swap_in();
584 #ifdef PLAYBACK_VOICE
585 voice_stop();
586 #endif
587 talk_buffer_steal();
589 #ifdef PLAYBACK_VOICE
590 /* If no dram_buf, swap space not used and recording gets more
591 memory. Codec swap areas will remain unaffected by the next init
592 since they're allocated at the end of the buffer and their sizes
593 don't change between calls */
594 end = dram_buf;
595 if (NULL == end)
596 #endif /* PLAYBACK_VOICE */
597 end = audiobufend;
599 buffer_state = BUFFER_STATE_TRASHED;
601 *buffer_size = end - audiobuf;
603 return (unsigned char *)audiobuf;
606 bool audio_load_encoder(int afmt)
608 #ifndef SIMULATOR
609 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
610 if (!enc_fn)
611 return false;
613 audio_remove_encoder();
614 ci.enc_codec_loaded = 0; /* clear any previous error condition */
616 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
617 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
619 while (ci.enc_codec_loaded == 0)
620 yield();
622 logf("codec loaded: %d", ci.enc_codec_loaded);
624 return ci.enc_codec_loaded > 0;
625 #else
626 (void)afmt;
627 return true;
628 #endif
629 } /* audio_load_encoder */
631 void audio_remove_encoder(void)
633 #ifndef SIMULATOR
634 /* force encoder codec unload (if currently loaded) */
635 if (ci.enc_codec_loaded <= 0)
636 return;
638 ci.stop_encoder = true;
639 while (ci.enc_codec_loaded > 0)
640 yield();
641 #endif
642 } /* audio_remove_encoder */
644 #endif /* HAVE_RECORDING */
646 struct mp3entry* audio_current_track(void)
648 const char *filename;
649 const char *p;
650 static struct mp3entry temp_id3;
651 int cur_idx;
652 int offset = ci.new_track + wps_offset;
654 cur_idx = track_ridx + offset;
655 cur_idx &= MAX_TRACK_MASK;
657 if (tracks[cur_idx].id3_hid > 0)
658 return &curtrack_id3;
660 memset(&temp_id3, 0, sizeof(struct mp3entry));
662 filename = playlist_peek(0);
663 if (!filename)
664 filename = "No file!";
666 #ifdef HAVE_TC_RAMCACHE
667 if (tagcache_fill_tags(&temp_id3, filename))
668 return &temp_id3;
669 #endif
671 p = strrchr(filename, '/');
672 if (!p)
673 p = filename;
674 else
675 p++;
677 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
678 temp_id3.title = &temp_id3.path[0];
680 return &temp_id3;
683 struct mp3entry* audio_next_track(void)
685 int next_idx = track_ridx;
687 if (!audio_have_tracks())
688 return NULL;
690 next_idx++;
691 next_idx &= MAX_TRACK_MASK;
693 if (tracks[next_idx].id3_hid <= 0)
694 return NULL;
696 return &nexttrack_id3;
699 bool audio_has_changed_track(void)
701 if (track_changed)
703 track_changed = false;
704 return true;
707 return false;
710 void audio_play(long offset)
712 logf("audio_play");
714 #ifdef PLAYBACK_VOICE
715 /* Truncate any existing voice output so we don't have spelling
716 * etc. over the first part of the played track */
717 talk_force_shutup();
718 #endif
720 /* Start playback */
721 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
722 /* Don't return until playback has actually started */
723 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
726 void audio_stop(void)
728 /* Stop playback */
729 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
730 /* Don't return until playback has actually stopped */
731 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
734 void audio_pause(void)
736 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
737 /* Don't return until playback has actually paused */
738 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
741 void audio_resume(void)
743 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
744 /* Don't return until playback has actually resumed */
745 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
748 void audio_next(void)
750 if (playlist_check(ci.new_track + wps_offset + 1))
752 if (global_settings.beep)
753 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
755 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
756 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
757 /* Update wps while our message travels inside deep playback queues. */
758 wps_offset++;
759 track_changed = true;
761 else
763 /* No more tracks. */
764 if (global_settings.beep)
765 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
769 void audio_prev(void)
771 if (playlist_check(ci.new_track + wps_offset - 1))
773 if (global_settings.beep)
774 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
776 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
777 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
778 /* Update wps while our message travels inside deep playback queues. */
779 wps_offset--;
780 track_changed = true;
782 else
784 /* No more tracks. */
785 if (global_settings.beep)
786 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
790 void audio_next_dir(void)
792 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
793 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
796 void audio_prev_dir(void)
798 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
799 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
802 void audio_pre_ff_rewind(void)
804 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
805 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
808 void audio_ff_rewind(long newpos)
810 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
811 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
814 void audio_flush_and_reload_tracks(void)
816 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
817 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
820 void audio_error_clear(void)
822 #ifdef AUDIO_HAVE_RECORDING
823 pcm_rec_error_clear();
824 #endif
827 int audio_status(void)
829 int ret = 0;
831 if (playing)
832 ret |= AUDIO_STATUS_PLAY;
834 if (paused)
835 ret |= AUDIO_STATUS_PAUSE;
837 #ifdef HAVE_RECORDING
838 /* Do this here for constitency with mpeg.c version */
839 ret |= pcm_rec_status();
840 #endif
842 return ret;
845 int audio_get_file_pos(void)
847 return 0;
850 #ifndef HAVE_FLASH_STORAGE
851 void audio_set_buffer_margin(int setting)
853 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
854 buffer_margin = lookup[setting];
855 logf("buffer margin: %d", buffer_margin);
856 set_filebuf_watermark(buffer_margin);
858 #endif
860 /* Take nescessary steps to enable or disable the crossfade setting */
861 void audio_set_crossfade(int enable)
863 size_t offset;
864 bool was_playing;
865 size_t size;
867 /* Tell it the next setting to use */
868 pcmbuf_crossfade_enable(enable);
870 /* Return if size hasn't changed or this is too early to determine
871 which in the second case there's no way we could be playing
872 anything at all */
873 if (pcmbuf_is_same_size())
875 /* This function is a copout and just syncs some variables -
876 to be removed at a later date */
877 pcmbuf_crossfade_enable_finished();
878 return;
881 offset = 0;
882 was_playing = playing;
884 /* Playback has to be stopped before changing the buffer size */
885 if (was_playing)
887 /* Store the track resume position */
888 offset = curtrack_id3.offset;
889 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
892 /* Blast it - audio buffer will have to be setup again next time
893 something plays */
894 audio_get_buffer(true, &size);
896 /* Restart playback if audio was running previously */
897 if (was_playing)
898 audio_play(offset);
901 /* --- Routines called from multiple threads --- */
902 static void set_current_codec(int codec_idx)
904 current_codec = codec_idx;
905 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
908 #ifdef PLAYBACK_VOICE
909 static void swap_codec(void)
911 int my_codec;
913 /* Swap nothing if no swap buffers exist */
914 if (dram_buf == NULL)
916 logf("swap: no swap buffers");
917 return;
920 my_codec = current_codec;
922 logf("swapping out codec: %d", my_codec);
924 /* Invert this when a codec thread enters and leaves */
925 swap_codec_parity = !swap_codec_parity;
927 /* If this is true, an odd number of calls has occurred and there's
928 no codec thread waiting to swap us out when it locks and runs. This
929 occurs when playback is stopped or when just starting playback and
930 the audio thread is loading a codec; parities should always be even
931 on entry when a thread calls this during playback */
932 if (swap_codec_parity)
934 /* Save our current IRAM and DRAM */
935 #ifdef IRAM_STEAL
936 if (voice_iram_stolen)
938 logf("swap: iram restore");
939 voice_iram_stolen = false;
940 /* Don't swap trashed data into buffer as the voice IRAM will
941 already be swapped out - should _always_ be the case if
942 voice_iram_stolen is true since the voice has been swapped
943 in beforehand */
944 if (my_codec == CODEC_IDX_VOICE)
946 logf("voice iram already swapped");
947 goto skip_iram_swap;
950 #endif
952 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
954 #ifdef IRAM_STEAL
955 skip_iram_swap:
956 #endif
958 memswap128(dram_buf, codecbuf, CODEC_SIZE);
959 /* No cache invalidation needed; it will be done in codec_load_ram
960 or we won't be here otherwise */
963 /* Release my semaphore */
964 semaphore_release(&sem_codecthread);
965 logf("unlocked: %d", my_codec);
967 /* Wait for other codec */
968 event_wait(&event_codecthread,
969 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
971 /* Wait for other codec to unlock */
972 logf("waiting for lock: %d", my_codec);
973 semaphore_wait(&sem_codecthread);
975 /* Take control */
976 set_current_codec(my_codec);
977 event_set_state(&event_codecthread,
978 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
980 /* Reload our IRAM and DRAM */
981 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
982 memswap128(dram_buf, codecbuf, CODEC_SIZE);
983 invalidate_icache();
985 /* Flip parity again */
986 swap_codec_parity = !swap_codec_parity;
988 logf("resuming codec: %d", my_codec);
991 /* This function is meant to be used by the buffer stealing functions to
992 ensure the codec is no longer active and so voice will be swapped-in
993 before it is called */
994 static void voice_stop(void)
996 /* Must have a voice codec loaded or we'll hang forever here */
997 if (!voice_codec_loaded)
998 return;
1000 talk_force_shutup();
1002 /* Loop until voice empties it's queue, stops and picks up on the new
1003 track; the voice thread must be stopped and waiting for messages
1004 outside the codec */
1005 while (voice_is_playing || !queue_empty(&voice_queue) ||
1006 ci_voice.new_track)
1007 yield();
1009 if (!playing)
1010 pcmbuf_play_stop();
1011 } /* voice_stop */
1013 /* Is voice still speaking */
1014 /* Unfortunately only reliable when music is not also playing. */
1015 static bool is_voice_speaking(void)
1017 return is_voice_queued()
1018 || voice_is_playing
1019 || (!playing && pcm_is_playing());
1022 #endif /* PLAYBACK_VOICE */
1024 /* Wait for voice to finish speaking. */
1025 /* Also only reliable when music is not also playing. */
1026 void voice_wait(void)
1028 #ifdef PLAYBACK_VOICE
1029 while (is_voice_speaking())
1030 sleep(HZ/10);
1031 #endif
1034 static void set_filebuf_watermark(int seconds)
1036 size_t bytes;
1038 if (!filebuf)
1039 return; /* Audio buffers not yet set up */
1041 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), conf_watermark);
1042 bytes = MIN(bytes, filebuflen / 2);
1043 conf_watermark = bytes;
1046 const char * get_codec_filename(int cod_spec)
1048 const char *fname;
1050 #ifdef HAVE_RECORDING
1051 /* Can choose decoder or encoder if one available */
1052 int type = cod_spec & CODEC_TYPE_MASK;
1053 int afmt = cod_spec & CODEC_AFMT_MASK;
1055 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1056 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1058 fname = (type == CODEC_TYPE_ENCODER) ?
1059 audio_formats[afmt].codec_enc_root_fn :
1060 audio_formats[afmt].codec_root_fn;
1062 logf("%s: %d - %s",
1063 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1064 afmt, fname ? fname : "<unknown>");
1065 #else /* !HAVE_RECORDING */
1066 /* Always decoder */
1067 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1068 cod_spec = AFMT_UNKNOWN;
1069 fname = audio_formats[cod_spec].codec_root_fn;
1070 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1071 #endif /* HAVE_RECORDING */
1073 return fname;
1074 } /* get_codec_filename */
1077 /* --- Voice thread --- */
1079 #ifdef PLAYBACK_VOICE
1081 static bool voice_pcmbuf_insert_callback(
1082 const void *ch1, const void *ch2, int count)
1084 const char *src[2] = { ch1, ch2 };
1086 while (count > 0)
1088 int out_count = dsp_output_count(count);
1089 int inp_count;
1090 char *dest;
1092 while ((dest = pcmbuf_request_voice_buffer(
1093 &out_count, playing)) == NULL)
1095 if (playing && audio_codec_loaded)
1096 swap_codec();
1097 else
1098 yield();
1101 /* Get the real input_size for output_size bytes, guarding
1102 * against resampling buffer overflows. */
1103 inp_count = dsp_input_count(out_count);
1105 if (inp_count <= 0)
1106 return true;
1108 /* Input size has grown, no error, just don't write more than length */
1109 if (inp_count > count)
1110 inp_count = count;
1112 out_count = dsp_process(dest, src, inp_count);
1114 if (out_count <= 0)
1115 return true;
1117 if (playing)
1119 pcmbuf_mix_voice(out_count);
1120 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1121 audio_codec_loaded)
1122 swap_codec();
1124 else
1125 pcmbuf_write_complete(out_count);
1127 count -= inp_count;
1130 return true;
1131 } /* voice_pcmbuf_insert_callback */
1133 static void* voice_get_memory_callback(size_t *size)
1135 /* Voice should have no use for this. If it did, we'd have to
1136 swap the malloc buffer as well. */
1137 *size = 0;
1138 return NULL;
1141 static void voice_set_elapsed_callback(unsigned int value)
1143 (void)value;
1146 static void voice_set_offset_callback(size_t value)
1148 (void)value;
1151 static void voice_configure_callback(int setting, intptr_t value)
1153 if (!dsp_configure(setting, value))
1155 logf("Illegal key:%d", setting);
1159 static size_t voice_filebuf_callback(void *ptr, size_t size)
1161 (void)ptr;
1162 (void)size;
1164 return 0;
1167 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1168 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1170 if (aborting && !playing)
1172 /* Aborting: Slight hack - flush PCM buffer if
1173 only being used for voice */
1174 pcmbuf_play_stop();
1177 if (voice_is_playing)
1179 /* Clear the current buffer */
1180 voice_is_playing = false;
1181 voice_getmore = NULL;
1182 voice_remaining = 0;
1183 voicebuf = NULL;
1185 /* Cancel any automatic boost if no more clips requested. */
1186 if (!playing || !voice_thread_start)
1187 sleep(0);
1189 /* Force the codec to think it's changing tracks */
1190 ci_voice.new_track = 1;
1192 *realsize = 0;
1193 return true; /* Yes, change tracks */
1196 return false;
1199 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1201 struct queue_event ev;
1203 if (ci_voice.new_track)
1205 *realsize = 0;
1206 return NULL;
1209 while (1)
1211 if (voice_is_playing || playing)
1213 queue_wait_w_tmo(&voice_queue, &ev, 0);
1214 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1215 ev.id = Q_AUDIO_PLAY;
1217 else
1219 queue_wait(&voice_queue, &ev);
1222 switch (ev.id) {
1223 case Q_AUDIO_PLAY:
1224 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1225 if (playing)
1227 if (audio_codec_loaded)
1228 swap_codec();
1229 yield();
1231 break;
1233 #ifdef AUDIO_HAVE_RECORDING
1234 case Q_ENCODER_RECORD:
1235 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1236 swap_codec();
1237 break;
1238 #endif
1240 case Q_VOICE_STOP:
1241 LOGFQUEUE("voice < Q_VOICE_STOP");
1242 if (voice_on_voice_stop(ev.data, realsize))
1243 return NULL;
1244 break;
1246 case SYS_USB_CONNECTED:
1248 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1249 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1250 /* Voice is obviously current so let us swap ourselves away if
1251 playing so audio may stop itself - audio_codec_loaded can
1252 only be true in this case if we're here even if the codec
1253 is only about to load */
1254 if (audio_codec_loaded)
1255 swap_codec();
1256 /* Playback should be finished by now - ack and wait */
1257 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1258 usb_wait_for_disconnect(&voice_queue);
1259 if (change_tracks)
1260 return NULL;
1261 break;
1264 case Q_VOICE_PLAY:
1265 LOGFQUEUE("voice < Q_VOICE_PLAY");
1266 if (!voice_is_playing)
1268 /* Set up new voice data */
1269 struct voice_info *voice_data;
1270 #ifdef IRAM_STEAL
1271 if (voice_iram_stolen)
1273 /* Voice is the first to run again and is currently
1274 loaded */
1275 logf("voice: iram restore");
1276 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1277 voice_iram_stolen = false;
1279 #endif
1280 /* Must reset the buffer before any playback begins if
1281 needed */
1282 if (buffer_state == BUFFER_STATE_TRASHED)
1283 audio_reset_buffer();
1285 voice_is_playing = true;
1286 trigger_cpu_boost();
1287 voice_data = (struct voice_info *)ev.data;
1288 voice_remaining = voice_data->size;
1289 voicebuf = voice_data->buf;
1290 voice_getmore = voice_data->callback;
1292 goto voice_play_clip; /* To exit both switch and while */
1294 case SYS_TIMEOUT:
1295 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1296 goto voice_play_clip;
1298 default:
1299 LOGFQUEUE("voice < default");
1303 voice_play_clip:
1305 if (voice_remaining == 0 || voicebuf == NULL)
1307 if (voice_getmore)
1308 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1310 /* If this clip is done */
1311 if (voice_remaining == 0)
1313 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1314 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1315 /* Force pcm playback. */
1316 if (!pcm_is_playing())
1317 pcmbuf_play_start();
1321 *realsize = MIN(voice_remaining, reqsize);
1323 if (*realsize == 0)
1324 return NULL;
1326 return voicebuf;
1327 } /* voice_request_buffer_callback */
1329 static void voice_advance_buffer_callback(size_t amount)
1331 amount = MIN(amount, voice_remaining);
1332 voicebuf += amount;
1333 voice_remaining -= amount;
1336 static void voice_advance_buffer_loc_callback(void *ptr)
1338 size_t amount = (size_t)ptr - (size_t)voicebuf;
1340 voice_advance_buffer_callback(amount);
1343 static off_t voice_mp3_get_filepos_callback(int newtime)
1345 (void)newtime;
1347 return 0;
1350 static void voice_do_nothing(void)
1352 return;
1355 static bool voice_seek_buffer_callback(size_t newpos)
1357 (void)newpos;
1359 return false;
1362 static bool voice_request_next_track_callback(void)
1364 ci_voice.new_track = 0;
1365 return true;
1368 static void voice_thread(void)
1370 logf("Loading voice codec");
1371 voice_codec_loaded = true;
1372 semaphore_wait(&sem_codecthread);
1373 event_set_state(&event_codecthread, false);
1374 set_current_codec(CODEC_IDX_VOICE);
1375 dsp_configure(DSP_RESET, 0);
1376 voice_remaining = 0;
1377 voice_getmore = NULL;
1379 /* FIXME: If we being starting the voice thread without reboot, the
1380 voice_queue could be full of old stuff and we must flush it. */
1381 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1383 logf("Voice codec finished");
1384 voice_codec_loaded = false;
1385 voice_thread_p = NULL;
1386 semaphore_release(&sem_codecthread);
1387 } /* voice_thread */
1389 #endif /* PLAYBACK_VOICE */
1391 /* --- Codec thread --- */
1392 static bool codec_pcmbuf_insert_callback(
1393 const void *ch1, const void *ch2, int count)
1395 const char *src[2] = { ch1, ch2 };
1397 while (count > 0)
1399 int out_count = dsp_output_count(count);
1400 int inp_count;
1401 char *dest;
1403 /* Prevent audio from a previous track from playing */
1404 if (ci.new_track || ci.stop_codec)
1405 return true;
1407 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1409 sleep(1);
1410 if (ci.seek_time || ci.new_track || ci.stop_codec)
1411 return true;
1414 /* Get the real input_size for output_size bytes, guarding
1415 * against resampling buffer overflows. */
1416 inp_count = dsp_input_count(out_count);
1418 if (inp_count <= 0)
1419 return true;
1421 /* Input size has grown, no error, just don't write more than length */
1422 if (inp_count > count)
1423 inp_count = count;
1425 out_count = dsp_process(dest, src, inp_count);
1427 if (out_count <= 0)
1428 return true;
1430 pcmbuf_write_complete(out_count);
1432 #ifdef PLAYBACK_VOICE
1433 if ((voice_is_playing || voice_thread_start)
1434 && pcm_is_playing() && voice_codec_loaded &&
1435 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1437 voice_thread_start = false;
1438 swap_codec();
1440 #endif
1442 count -= inp_count;
1445 return true;
1446 } /* codec_pcmbuf_insert_callback */
1448 static void* codec_get_memory_callback(size_t *size)
1450 *size = MALLOC_BUFSIZE;
1451 return malloc_buf;
1454 #if 0
1455 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1456 static void codec_pcmbuf_position_callback(size_t size)
1458 /* This is called from an ISR, so be quick */
1459 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1460 prev_ti->id3.elapsed;
1462 if (time >= prev_ti->id3.length)
1464 pcmbuf_set_position_callback(NULL);
1465 prev_ti->id3.elapsed = prev_ti->id3.length;
1467 else
1468 prev_ti->id3.elapsed = time;
1470 #endif
1472 static void codec_set_elapsed_callback(unsigned int value)
1474 unsigned int latency;
1475 if (ci.seek_time)
1476 return;
1478 #ifdef AB_REPEAT_ENABLE
1479 ab_position_report(value);
1480 #endif
1482 latency = pcmbuf_get_latency();
1483 if (value < latency)
1484 curtrack_id3.elapsed = 0;
1485 else if (value - latency > curtrack_id3.elapsed ||
1486 value - latency < curtrack_id3.elapsed - 2)
1488 curtrack_id3.elapsed = value - latency;
1492 static void codec_set_offset_callback(size_t value)
1494 unsigned int latency;
1496 if (ci.seek_time)
1497 return;
1499 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1500 if (value < latency)
1501 curtrack_id3.offset = 0;
1502 else
1503 curtrack_id3.offset = value - latency;
1506 /* copy up-to size bytes into ptr and return the actual size copied */
1507 static size_t codec_filebuf_callback(void *ptr, size_t size)
1509 ssize_t copy_n;
1511 if (ci.stop_codec || !playing)
1512 return 0;
1514 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1516 /* Nothing requested OR nothing left */
1517 if (copy_n == 0)
1518 return 0;
1520 /* Let the disk buffer catch fill until enough data is available */
1521 while (copy_n == -2)
1523 #if 0
1524 if (!filling)
1526 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1527 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1529 #endif
1531 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
1532 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
1534 if (ci.stop_codec || ci.new_track)
1535 return 0;
1537 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1540 /* Update read and other position pointers */
1541 bufadvance(CUR_TI->audio_hid, copy_n);
1542 ci.curpos += copy_n;
1544 /* Return the actual amount of data copied to the buffer */
1545 return copy_n;
1546 } /* codec_filebuf_callback */
1548 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1550 size_t copy_n;
1551 ssize_t ret;
1552 char *ptr;
1554 if (!playing)
1556 *realsize = 0;
1557 return NULL;
1560 ret = bufgetdata(CUR_TI->audio_hid, reqsize, (unsigned char **)&ptr);
1561 if (ret >= 0)
1562 copy_n = MIN((size_t)ret, reqsize);
1564 if (copy_n == 0)
1566 *realsize = 0;
1567 return NULL;
1570 while (ret == -2)
1572 #if 0
1573 if (!filling)
1575 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1576 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1578 #endif
1580 LOGFQUEUE("codec >| buffering Q_BUFFER_HANDLE");
1581 queue_send(&buffering_queue, Q_BUFFER_HANDLE, CUR_TI->audio_hid);
1583 sleep(1);
1585 if (ci.stop_codec || ci.new_track)
1587 *realsize = 0;
1588 return NULL;
1590 ret = bufgetdata(CUR_TI->audio_hid, reqsize, (unsigned char **)&ptr);
1592 copy_n = MIN((size_t)ret, reqsize);
1594 *realsize = copy_n;
1596 return ptr;
1597 } /* codec_request_buffer_callback */
1599 static int get_codec_base_type(int type)
1601 switch (type) {
1602 case AFMT_MPA_L1:
1603 case AFMT_MPA_L2:
1604 case AFMT_MPA_L3:
1605 return AFMT_MPA_L3;
1608 return type;
1611 static void codec_advance_buffer_callback(size_t amount)
1613 int ret;
1615 while ((ret = bufadvance(CUR_TI->audio_hid, amount) == -2) && filling)
1616 sleep(1);
1618 if (ret == -2)
1620 intptr_t result = Q_CODEC_REQUEST_FAILED;
1622 if (!ci.stop_codec)
1624 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1625 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1626 ci.curpos + amount);
1629 switch (result)
1631 case Q_CODEC_REQUEST_FAILED:
1632 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1633 ci.stop_codec = true;
1634 return;
1636 case Q_CODEC_REQUEST_COMPLETE:
1637 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1638 return;
1640 default:
1641 LOGFQUEUE("codec |< default");
1642 ci.stop_codec = true;
1643 return;
1647 /* Start buffer filling as necessary. */
1648 if (!pcmbuf_is_lowdata() && !filling)
1650 if (bufused() < conf_watermark && playing && !playlist_end)
1652 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1653 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1657 ci.curpos += amount;
1658 codec_set_offset_callback(ci.curpos);
1661 static void codec_advance_buffer_loc_callback(void *ptr)
1663 size_t amount = get_offset(CUR_TI->audio_hid, ptr);
1665 codec_advance_buffer_callback(amount);
1668 /* Copied from mpeg.c. Should be moved somewhere else. */
1669 static int codec_get_file_pos(void)
1671 int pos = -1;
1672 struct mp3entry *id3 = audio_current_track();
1674 if (id3->vbr)
1676 if (id3->has_toc)
1678 /* Use the TOC to find the new position */
1679 unsigned int percent, remainder;
1680 int curtoc, nexttoc, plen;
1682 percent = (id3->elapsed*100)/id3->length;
1683 if (percent > 99)
1684 percent = 99;
1686 curtoc = id3->toc[percent];
1688 if (percent < 99)
1689 nexttoc = id3->toc[percent+1];
1690 else
1691 nexttoc = 256;
1693 pos = (id3->filesize/256)*curtoc;
1695 /* Use the remainder to get a more accurate position */
1696 remainder = (id3->elapsed*100)%id3->length;
1697 remainder = (remainder*100)/id3->length;
1698 plen = (nexttoc - curtoc)*(id3->filesize/256);
1699 pos += (plen/100)*remainder;
1701 else
1703 /* No TOC exists, estimate the new position */
1704 pos = (id3->filesize / (id3->length / 1000)) *
1705 (id3->elapsed / 1000);
1708 else if (id3->bitrate)
1709 pos = id3->elapsed * (id3->bitrate / 8);
1710 else
1711 return -1;
1713 pos += id3->first_frame_offset;
1715 /* Don't seek right to the end of the file so that we can
1716 transition properly to the next song */
1717 if (pos >= (int)(id3->filesize - id3->id3v1len))
1718 pos = id3->filesize - id3->id3v1len - 1;
1720 return pos;
1723 static off_t codec_mp3_get_filepos_callback(int newtime)
1725 off_t newpos;
1727 curtrack_id3.elapsed = newtime;
1728 newpos = codec_get_file_pos();
1730 return newpos;
1733 static void codec_seek_complete_callback(void)
1735 logf("seek_complete");
1736 if (pcm_is_paused())
1738 /* If this is not a seamless seek, clear the buffer */
1739 pcmbuf_play_stop();
1740 dsp_configure(DSP_FLUSH, 0);
1742 /* If playback was not 'deliberately' paused, unpause now */
1743 if (!paused)
1744 pcmbuf_pause(false);
1746 ci.seek_time = 0;
1749 static bool codec_seek_buffer_callback(size_t newpos)
1751 int difference;
1753 logf("codec_seek_buffer_callback");
1755 if (newpos >= CUR_TI->filesize)
1756 newpos = CUR_TI->filesize - 1;
1758 difference = newpos - ci.curpos;
1759 if (difference >= 0)
1761 /* Seeking forward */
1762 logf("seek: +%d", difference);
1763 codec_advance_buffer_callback(difference);
1764 return true;
1767 /* Seeking backward */
1768 difference = -difference;
1769 if (ci.curpos - difference < 0)
1770 difference = ci.curpos;
1772 #if 0
1773 /* We need to reload the song. */
1774 if (newpos < CUR_TI->start_pos)
1776 intptr_t result = Q_CODEC_REQUEST_FAILED;
1778 if (!ci.stop_codec)
1780 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1781 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1782 newpos);
1785 switch (result)
1787 case Q_CODEC_REQUEST_COMPLETE:
1788 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1789 return true;
1791 case Q_CODEC_REQUEST_FAILED:
1792 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1793 ci.stop_codec = true;
1794 return false;
1796 default:
1797 LOGFQUEUE("codec |< default");
1798 return false;
1801 #endif
1803 /* Seeking inside buffer space. */
1804 logf("seek: -%d", difference);
1805 bufadvance(CUR_TI->audio_hid, -difference);
1806 ci.curpos -= difference;
1808 return true;
1811 static void codec_configure_callback(int setting, intptr_t value)
1813 switch (setting) {
1814 case CODEC_SET_FILEBUF_WATERMARK:
1815 conf_watermark = value;
1816 set_filebuf_watermark(buffer_margin);
1817 break;
1819 case CODEC_SET_FILEBUF_CHUNKSIZE:
1820 conf_filechunk = value;
1821 break;
1823 case CODEC_SET_FILEBUF_PRESEEK:
1824 conf_preseek = value;
1825 break;
1827 default:
1828 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1832 static void codec_track_changed(void)
1834 automatic_skip = false;
1835 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1836 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1839 static void codec_pcmbuf_track_changed_callback(void)
1841 pcmbuf_set_position_callback(NULL);
1842 codec_track_changed();
1845 static void codec_discard_codec_callback(void)
1847 if (CUR_TI->codec_hid > 0)
1849 bufclose(CUR_TI->codec_hid);
1850 CUR_TI->codec_hid = 0;
1853 #if 0
1854 /* Check if a buffer desync has happened, log it and stop playback. */
1855 if (buf_ridx != CUR_TI->buf_idx)
1857 int offset = CUR_TI->buf_idx - buf_ridx;
1858 size_t new_used = bufused() - offset;
1860 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1861 logf("Used off:%d",bufused() - new_used);
1863 /* This is a fatal internal error and it's not safe to
1864 * continue playback. */
1865 ci.stop_codec = true;
1866 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1868 #endif
1871 static inline void codec_gapless_track_change(void) {
1872 /* callback keeps the progress bar moving while the pcmbuf empties */
1873 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1874 /* set the pcmbuf callback for when the track really changes */
1875 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1878 static inline void codec_crossfade_track_change(void) {
1879 /* Initiate automatic crossfade mode */
1880 pcmbuf_crossfade_init(false);
1881 /* Notify the wps that the track change starts now */
1882 codec_track_changed();
1885 static void codec_track_skip_done(bool was_manual)
1887 int crossfade_mode = global_settings.crossfade;
1889 /* Manual track change (always crossfade or flush audio). */
1890 if (was_manual)
1892 pcmbuf_crossfade_init(true);
1893 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1894 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1896 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1897 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1898 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1900 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1902 if (global_settings.playlist_shuffle)
1903 /* shuffle mode is on, so crossfade: */
1904 codec_crossfade_track_change();
1905 else
1906 /* shuffle mode is off, so do a gapless track change */
1907 codec_gapless_track_change();
1909 else
1910 /* normal crossfade: */
1911 codec_crossfade_track_change();
1913 else
1914 /* normal gapless playback. */
1915 codec_gapless_track_change();
1918 static bool codec_load_next_track(void)
1920 intptr_t result = Q_CODEC_REQUEST_FAILED;
1922 prev_track_elapsed = curtrack_id3.elapsed;
1924 if (ci.seek_time)
1925 codec_seek_complete_callback();
1927 #ifdef AB_REPEAT_ENABLE
1928 ab_end_of_track_report();
1929 #endif
1931 logf("Request new track");
1933 if (ci.new_track == 0)
1935 ci.new_track++;
1936 automatic_skip = true;
1939 if (!ci.stop_codec)
1941 trigger_cpu_boost();
1942 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1943 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1946 switch (result)
1948 case Q_CODEC_REQUEST_COMPLETE:
1949 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1950 codec_track_skip_done(!automatic_skip);
1951 return true;
1953 case Q_CODEC_REQUEST_FAILED:
1954 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1955 ci.new_track = 0;
1956 ci.stop_codec = true;
1957 return false;
1959 default:
1960 LOGFQUEUE("codec |< default");
1961 ci.stop_codec = true;
1962 return false;
1966 static bool codec_request_next_track_callback(void)
1968 int prev_codectype;
1970 if (ci.stop_codec || !playing)
1971 return false;
1973 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1975 if (!codec_load_next_track())
1976 return false;
1978 /* Check if the next codec is the same file. */
1979 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1981 logf("New track loaded");
1982 codec_discard_codec_callback();
1983 return true;
1985 else
1987 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1988 return false;
1992 static void codec_thread(void)
1994 struct queue_event ev;
1995 int status;
1996 size_t wrap;
1998 while (1) {
1999 status = 0;
2000 queue_wait(&codec_queue, &ev);
2002 switch (ev.id) {
2003 case Q_CODEC_LOAD_DISK:
2004 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
2005 queue_reply(&codec_queue, 1);
2006 audio_codec_loaded = true;
2007 #ifdef PLAYBACK_VOICE
2008 /* Don't sent messages to voice codec if it's already swapped
2009 out or it will never get this */
2010 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2012 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2013 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2015 semaphore_wait(&sem_codecthread);
2016 event_set_state(&event_codecthread, true);
2017 #endif
2018 set_current_codec(CODEC_IDX_AUDIO);
2019 ci.stop_codec = false;
2020 status = codec_load_file((const char *)ev.data, &ci);
2021 DEBUGF("codec_load = %d\n", status);
2022 #ifdef PLAYBACK_VOICE
2023 semaphore_release(&sem_codecthread);
2024 #endif
2025 break;
2027 case Q_CODEC_LOAD:
2028 LOGFQUEUE("codec < Q_CODEC_LOAD");
2029 if (CUR_TI->codec_hid <= 0) {
2030 logf("Codec slot is empty!");
2031 /* Wait for the pcm buffer to go empty */
2032 while (pcm_is_playing())
2033 yield();
2034 /* This must be set to prevent an infinite loop */
2035 ci.stop_codec = true;
2036 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
2037 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
2038 break;
2041 audio_codec_loaded = true;
2042 #ifdef PLAYBACK_VOICE
2043 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2045 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2046 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2048 semaphore_wait(&sem_codecthread);
2049 event_set_state(&event_codecthread, true);
2050 #endif
2051 set_current_codec(CODEC_IDX_AUDIO);
2052 ci.stop_codec = false;
2053 wrap = (size_t)&filebuf[filebuflen] - (size_t)getptr(CUR_TI->codec_hid);
2054 status = codec_load_ram(getptr(CUR_TI->codec_hid), CUR_TI->codecsize,
2055 &filebuf[0], wrap, &ci);
2056 #ifdef PLAYBACK_VOICE
2057 semaphore_release(&sem_codecthread);
2058 #endif
2059 break;
2061 #ifdef AUDIO_HAVE_RECORDING
2062 case Q_ENCODER_LOAD_DISK:
2063 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2064 audio_codec_loaded = false; /* Not audio codec! */
2065 #ifdef PLAYBACK_VOICE
2066 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2068 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2069 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2071 semaphore_wait(&sem_codecthread);
2072 event_set_state(&event_codecthread, true);
2073 #endif
2074 logf("loading encoder");
2075 set_current_codec(CODEC_IDX_AUDIO);
2076 ci.stop_encoder = false;
2077 status = codec_load_file((const char *)ev.data, &ci);
2078 #ifdef PLAYBACK_VOICE
2079 semaphore_release(&sem_codecthread);
2080 #endif
2081 logf("encoder stopped");
2082 break;
2083 #endif /* AUDIO_HAVE_RECORDING */
2085 #ifndef SIMULATOR
2086 case SYS_USB_CONNECTED:
2087 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2088 queue_clear(&codec_queue);
2089 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2090 usb_wait_for_disconnect(&codec_queue);
2091 break;
2092 #endif
2094 default:
2095 LOGFQUEUE("codec < default");
2098 if (audio_codec_loaded)
2100 if (ci.stop_codec)
2102 status = CODEC_OK;
2103 if (!playing)
2104 pcmbuf_play_stop();
2107 audio_codec_loaded = false;
2110 switch (ev.id) {
2111 case Q_CODEC_LOAD_DISK:
2112 case Q_CODEC_LOAD:
2113 LOGFQUEUE("codec < Q_CODEC_LOAD");
2114 if (playing)
2116 if (ci.new_track || status != CODEC_OK)
2118 if (!ci.new_track)
2120 logf("Codec failure");
2121 gui_syncsplash(HZ*2, "Codec failure");
2124 if (!codec_load_next_track())
2126 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2127 /* End of playlist */
2128 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2129 break;
2132 else
2134 logf("Codec finished");
2135 if (ci.stop_codec)
2137 /* Wait for the audio to stop playing before
2138 * triggering the WPS exit */
2139 while(pcm_is_playing())
2141 curtrack_id3.elapsed =
2142 curtrack_id3.length - pcmbuf_get_latency();
2143 sleep(1);
2145 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2146 /* End of playlist */
2147 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2148 break;
2152 if (CUR_TI->codec_hid > 0)
2154 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2155 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2157 else
2159 const char *codec_fn =
2160 get_codec_filename(curtrack_id3.codectype);
2161 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2162 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2163 (intptr_t)codec_fn);
2166 break;
2168 #ifdef AUDIO_HAVE_RECORDING
2169 case Q_ENCODER_LOAD_DISK:
2170 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2172 if (status == CODEC_OK)
2173 break;
2175 logf("Encoder failure");
2176 gui_syncsplash(HZ*2, "Encoder failure");
2178 if (ci.enc_codec_loaded < 0)
2179 break;
2181 logf("Encoder failed to load");
2182 ci.enc_codec_loaded = -1;
2183 break;
2184 #endif /* AUDIO_HAVE_RECORDING */
2186 default:
2187 LOGFQUEUE("codec < default");
2189 } /* end switch */
2194 /* --- Audio thread --- */
2196 static bool audio_filebuf_is_lowdata(void)
2198 return bufused() < AUDIO_FILEBUF_CRITICAL;
2201 static bool audio_have_tracks(void)
2203 return track_ridx != track_widx || CUR_TI->filesize;
2206 static bool audio_have_free_tracks(void)
2208 if (track_widx < track_ridx)
2209 return track_widx + 1 < track_ridx;
2210 else if (track_ridx == 0)
2211 return track_widx < MAX_TRACK - 1;
2213 return true;
2216 int audio_track_count(void)
2218 if (audio_have_tracks())
2220 int relative_track_widx = track_widx;
2222 if (track_ridx > track_widx)
2223 relative_track_widx += MAX_TRACK;
2225 return relative_track_widx - track_ridx + 1;
2228 return 0;
2231 long audio_filebufused(void)
2233 return (long) bufused();
2236 /* Count the data BETWEEN the selected tracks */
2237 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2239 size_t amount = 0;
2240 bool need_wrap = to_track < from_track;
2242 while (1)
2244 if (++from_track >= MAX_TRACK)
2246 from_track -= MAX_TRACK;
2247 need_wrap = false;
2250 if (from_track >= to_track && !need_wrap)
2251 break;
2253 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2255 return amount;
2258 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2260 (void)new_track_ridx;
2261 (void)old_track_ridx;
2262 #if 0
2263 size_t amount;
2265 /* Start with the remainder of the previously playing track */
2266 amount = tracks[old_track_ridx].filesize - ci.curpos;
2267 /* Then collect all data from tracks in between them */
2268 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2269 logf("bwf:%ldB", (long) amount);
2271 if (amount > bufused())
2272 return false;
2274 /* Wind the buffer to the beginning of the target track or its codec */
2275 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2276 #endif
2277 return true;
2280 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2282 (void)new_track_ridx;
2283 (void)old_track_ridx;
2284 #if 0
2285 /* Available buffer data */
2286 size_t buf_back;
2287 /* Start with the previously playing track's data and our data */
2288 size_t amount;
2290 amount = ci.curpos;
2291 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2293 /* If we're not just resetting the current track */
2294 if (new_track_ridx != old_track_ridx)
2296 /* Need to wind to before the old track's codec and our filesize */
2297 amount += tracks[old_track_ridx].codecsize;
2298 amount += tracks[new_track_ridx].filesize;
2300 /* Rewind the old track to its beginning */
2301 tracks[old_track_ridx].available =
2302 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2305 /* If the codec was ever buffered */
2306 if (tracks[new_track_ridx].codecsize)
2308 /* Add the codec to the needed size */
2309 amount += tracks[new_track_ridx].codecsize;
2310 tracks[new_track_ridx].has_codec = true;
2313 /* Then collect all data from tracks between new and old */
2314 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2316 /* Do we have space to make this skip? */
2317 if (amount > buf_back)
2318 return false;
2320 logf("bwb:%ldB",amount);
2322 /* Rewind the buffer to the beginning of the target track or its codec */
2323 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2325 /* Reset to the beginning of the new track */
2326 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2327 #endif
2328 return true;
2331 static void audio_update_trackinfo(void)
2333 ci.filesize = CUR_TI->filesize;
2334 curtrack_id3.elapsed = 0;
2335 curtrack_id3.offset = 0;
2336 ci.id3 = &curtrack_id3;
2337 ci.curpos = 0;
2338 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2341 /* Yield to codecs for as long as possible if they are in need of data
2342 * return true if the caller should break to let the audio thread process
2343 * new events */
2344 static bool audio_yield_codecs(void)
2346 yield();
2348 if (!queue_empty(&audio_queue))
2349 return true;
2351 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2352 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2354 if (filling)
2355 yield();
2356 else
2357 sleep(2);
2359 if (!queue_empty(&audio_queue))
2360 return true;
2363 return false;
2366 static void audio_clear_track_entries(bool clear_unbuffered)
2368 int cur_idx = track_widx;
2369 int last_idx = -1;
2371 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2373 /* Loop over all tracks from write-to-read */
2374 while (1)
2376 cur_idx++;
2377 cur_idx &= MAX_TRACK_MASK;
2379 if (cur_idx == track_ridx)
2380 break;
2382 /* If the track is buffered, conditionally clear/notify,
2383 * otherwise clear the track if that option is selected */
2384 if (tracks[cur_idx].event_sent)
2386 if (last_idx >= 0)
2388 /* If there is an unbuffer callback, call it, otherwise,
2389 * just clear the track */
2390 if (track_unbuffer_callback)
2391 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2393 close_track_handles(&tracks[last_idx]);
2394 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2396 last_idx = cur_idx;
2398 else if (clear_unbuffered)
2400 close_track_handles(&tracks[cur_idx]);
2401 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2405 /* We clear the previous instance of a buffered track throughout
2406 * the above loop to facilitate 'last' detection. Clear/notify
2407 * the last track here */
2408 if (last_idx >= 0)
2410 if (track_unbuffer_callback)
2411 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2412 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2416 static void audio_release_tracks(void)
2418 int cur_idx = track_ridx;
2420 logf("releasing all tracks");
2422 while (1)
2424 close_track_handles(&tracks[cur_idx]);
2426 cur_idx++;
2427 cur_idx &= MAX_TRACK_MASK;
2429 if (cur_idx == track_widx)
2430 break;
2434 /* FIXME: This code should be made more generic and move to metadata.c */
2435 static void audio_strip_tags(void)
2437 #if 0
2438 int i;
2439 static const unsigned char tag[] = "TAG";
2440 static const unsigned char apetag[] = "APETAGEX";
2441 size_t tag_idx;
2442 size_t cur_idx;
2443 size_t len, version;
2445 tag_idx = RINGBUF_SUB(buf_widx, 128);
2447 if (bufused() > 128 && tag_idx > buf_ridx)
2449 cur_idx = tag_idx;
2450 for(i = 0;i < 3;i++)
2452 if(filebuf[cur_idx] != tag[i])
2453 goto strip_ape_tag;
2455 cur_idx = RINGBUF_ADD(cur_idx, 1);
2458 /* Skip id3v1 tag */
2459 logf("Skipping ID3v1 tag");
2460 buf_widx = tag_idx;
2461 tracks[track_widx].available -= 128;
2462 tracks[track_widx].filesize -= 128;
2465 strip_ape_tag:
2466 /* Check for APE tag (look for the APE tag footer) */
2467 tag_idx = RINGBUF_SUB(buf_widx, 32);
2469 if (bufused() > 32 && tag_idx > buf_ridx)
2471 cur_idx = tag_idx;
2472 for(i = 0;i < 8;i++)
2474 if(filebuf[cur_idx] != apetag[i])
2475 return;
2477 cur_idx = RINGBUF_ADD(cur_idx, 1);
2480 /* Read the version and length from the footer */
2481 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2482 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2483 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2484 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2485 if (version == 2000)
2486 len += 32; /* APEv2 has a 32 byte header */
2488 /* Skip APE tag */
2489 if (bufused() > len)
2491 logf("Skipping APE tag (%ldB)", len);
2492 buf_widx = RINGBUF_SUB(buf_widx, len);
2493 tracks[track_widx].available -= len;
2494 tracks[track_widx].filesize -= len;
2497 #endif
2500 #if 0
2501 /* Returns true if a whole file is read, false otherwise */
2502 static bool audio_read_file(size_t minimum)
2504 bool ret_val = false;
2506 /* If we're called and no file is open, this is an error */
2507 if (current_fd < 0)
2509 logf("Bad fd in arf");
2510 /* Give some hope of miraculous recovery by forcing a track reload */
2511 tracks[track_widx].filesize = 0;
2512 /* Stop this buffering run */
2513 return ret_val;
2516 trigger_cpu_boost();
2517 while (tracks[track_widx].filerem > 0)
2519 size_t copy_n;
2520 int overlap;
2521 int rc;
2523 /* copy_n is the largest chunk that is safe to read */
2524 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2526 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2527 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2528 break;
2530 /* rc is the actual amount read */
2531 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2533 if (rc < 0)
2535 logf("File ended %ldB early", tracks[track_widx].filerem);
2536 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2537 tracks[track_widx].filerem = 0;
2538 break;
2541 /* How much of the playing track did we overwrite */
2542 if (buf_widx == CUR_TI->buf_idx)
2544 /* Special handling; zero or full overlap? */
2545 if (track_widx == track_ridx && CUR_TI->available == 0)
2546 overlap = 0;
2547 else
2548 overlap = rc;
2550 else
2551 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2553 if ((unsigned)rc > tracks[track_widx].filerem)
2555 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2556 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2557 tracks[track_widx].filerem = rc;
2560 /* Advance buffer */
2561 buf_widx = RINGBUF_ADD(buf_widx, rc);
2562 tracks[track_widx].available += rc;
2563 tracks[track_widx].filerem -= rc;
2565 /* If we write into the playing track, adjust it's buffer info */
2566 if (overlap > 0)
2568 CUR_TI->buf_idx += overlap;
2569 CUR_TI->start_pos += overlap;
2572 /* For a rebuffer, fill at least this minimum */
2573 if (minimum > (unsigned)rc)
2574 minimum -= rc;
2575 /* Let the codec process up to the watermark */
2576 /* Break immediately if this is a quick buffer, or there is an event */
2577 else if (minimum || audio_yield_codecs())
2579 /* Exit quickly, but don't stop the overall buffering process */
2580 ret_val = true;
2581 break;
2585 if (tracks[track_widx].filerem == 0)
2587 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2588 close(current_fd);
2589 current_fd = -1;
2590 audio_strip_tags();
2592 track_widx++;
2593 track_widx &= MAX_TRACK_MASK;
2595 tracks[track_widx].filesize = 0;
2596 return true;
2598 else
2600 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2601 tracks[track_widx].filesize - tracks[track_widx].filerem);
2602 return ret_val;
2605 #endif
2607 static bool audio_loadcodec(bool start_play)
2609 size_t size = 0;
2610 int fd;
2611 int prev_track;
2612 char codec_path[MAX_PATH]; /* Full path to codec */
2614 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play ? "true" : "false");
2616 if (tracks[track_widx].id3_hid <= 0) {
2617 DEBUGF("track ID3 info not ready\n");
2618 return false;
2621 const char * codec_fn =
2622 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2623 if (codec_fn == NULL)
2624 return false;
2626 tracks[track_widx].codec_hid = 0;
2628 if (start_play)
2630 /* Load the codec directly from disk and save some memory. */
2631 track_ridx = track_widx;
2632 ci.filesize = CUR_TI->filesize;
2633 ci.id3 = &curtrack_id3;
2634 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2635 ci.curpos = 0;
2636 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2637 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2638 return true;
2640 else
2642 /* If we already have another track than this one buffered */
2643 if (track_widx != track_ridx)
2645 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2647 /* If the previous codec is the same as this one, there is no need
2648 * to put another copy of it on the file buffer */
2649 if (get_codec_base_type(
2650 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2651 get_codec_base_type(
2652 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2653 && audio_codec_loaded)
2655 logf("Reusing prev. codec");
2656 return true;
2661 codec_get_full_path(codec_path, codec_fn);
2663 fd = open(codec_path, O_RDONLY);
2664 if (fd < 0)
2666 logf("Codec doesn't exist!");
2667 return false;
2670 tracks[track_widx].codecsize = filesize(fd);
2672 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2673 if (tracks[track_widx].codec_hid < 0)
2675 logf("Not enough space");
2676 close(fd);
2677 return false;
2680 close(fd);
2681 logf("Done: %ldB", (long)size);
2683 return true;
2686 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2687 static void audio_set_elapsed(struct mp3entry* id3)
2689 unsigned long offset = id3->offset > id3->first_frame_offset ?
2690 id3->offset - id3->first_frame_offset : 0;
2692 if ( id3->vbr ) {
2693 if ( id3->has_toc ) {
2694 /* calculate elapsed time using TOC */
2695 int i;
2696 unsigned int remainder, plen, relpos, nextpos;
2698 /* find wich percent we're at */
2699 for (i=0; i<100; i++ )
2700 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2701 break;
2703 i--;
2704 if (i < 0)
2705 i = 0;
2707 relpos = id3->toc[i];
2709 if (i < 99)
2710 nextpos = id3->toc[i+1];
2711 else
2712 nextpos = 256;
2714 remainder = offset - (relpos * (id3->filesize / 256));
2716 /* set time for this percent (divide before multiply to prevent
2717 overflow on long files. loss of precision is negligible on
2718 short files) */
2719 id3->elapsed = i * (id3->length / 100);
2721 /* calculate remainder time */
2722 plen = (nextpos - relpos) * (id3->filesize / 256);
2723 id3->elapsed += (((remainder * 100) / plen) *
2724 (id3->length / 10000));
2726 else {
2727 /* no TOC exists. set a rough estimate using average bitrate */
2728 int tpk = id3->length /
2729 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2730 1024);
2731 id3->elapsed = offset / 1024 * tpk;
2734 else
2736 /* constant bitrate, use exact calculation */
2737 if (id3->bitrate != 0)
2738 id3->elapsed = offset / (id3->bitrate / 8);
2742 /* Load one track by making the appropriate bufopen calls. Return true if
2743 everything required was loaded correctly, false if not. */
2744 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2746 (void)rebuffer;
2747 char *trackname;
2748 char msgbuf[80];
2749 int fd;
2750 struct mp3entry id3;
2752 /* Stop buffer filling if there is no free track entries.
2753 Don't fill up the last track entry (we wan't to store next track
2754 metadata there). */
2755 if (!audio_have_free_tracks())
2757 logf("No free tracks");
2758 return false;
2761 last_peek_offset++;
2762 peek_again:
2763 logf("Buffering track:%d/%d", track_widx, track_ridx);
2764 /* Get track name from current playlist read position. */
2765 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2767 /* Handle broken playlists. */
2768 fd = open(trackname, O_RDONLY);
2769 if (fd < 0)
2771 logf("Open failed");
2772 /* Skip invalid entry from playlist. */
2773 playlist_skip_entry(NULL, last_peek_offset);
2775 else
2776 break;
2779 if (!trackname)
2781 logf("End-of-playlist");
2782 playlist_end = true;
2783 return false;
2786 tracks[track_widx].filesize = filesize(fd);
2788 /* Get track metadata if we don't already have it. */
2789 if (tracks[track_widx].id3_hid <= 0)
2791 if (get_metadata(&id3, fd, trackname))
2793 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2794 TYPE_ID3);
2795 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2797 if (tracks[track_widx].id3_hid <= 0)
2799 DEBUGF("failed to allocate space for metadata\n");
2800 last_peek_offset--;
2801 return false;
2804 if (track_widx == track_ridx)
2805 copy_mp3entry(&curtrack_id3, &id3);
2806 else if (track_widx == (track_ridx + 1) & MAX_TRACK_MASK)
2807 copy_mp3entry(&nexttrack_id3, &id3);
2809 if (start_play)
2811 track_changed = true;
2812 playlist_update_resume_info(audio_current_track());
2815 else
2817 logf("mde:%s!",trackname);
2819 /* Skip invalid entry from playlist. */
2820 playlist_skip_entry(NULL, last_peek_offset);
2821 tracks[track_widx].taginfo_ready = false;
2822 goto peek_again;
2827 close(fd);
2829 /* Set default values */
2830 if (start_play)
2832 int last_codec = current_codec;
2834 set_current_codec(CODEC_IDX_AUDIO);
2835 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2836 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2837 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2838 dsp_configure(DSP_RESET, 0);
2839 set_current_codec(last_codec);
2841 track_changed = true;
2842 playlist_update_resume_info(audio_current_track());
2845 #if 0
2846 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2848 char cuepath[MAX_PATH];
2850 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2852 if (look_for_cuesheet_file(trackname, cuepath) &&
2853 parse_cuesheet(cuepath, cue))
2855 strcpy((cue)->audio_filename, trackname);
2856 if (start_play)
2857 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2860 #endif
2862 /* Load the codec. */
2863 if (!audio_loadcodec(start_play))
2865 #if 0
2866 /* Set filesize to zero to indicate no file was loaded. */
2867 /* tracks[track_widx].filesize = 0;
2868 tracks[track_widx].filerem = 0;
2869 close(current_fd);
2870 current_fd = -1; */
2872 if (tracks[track_widx].codecsize)
2874 /* No space for codec on buffer, not an error */
2875 tracks[track_widx].codecsize = 0;
2876 return false;
2879 /* This is an error condition, either no codec was found, or reading
2880 * the codec file failed part way through, either way, skip the track */
2881 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2882 /* We should not use gui_syncplash from audio thread! */
2883 gui_syncsplash(HZ*2, msgbuf);
2884 /* Skip invalid entry from playlist. */
2885 playlist_skip_entry(NULL, last_peek_offset);
2886 tracks[track_widx].taginfo_ready = false;
2887 goto peek_again;
2888 #endif
2889 return false;
2892 struct mp3entry *track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2894 /* tracks[track_widx].start_pos = 0; */
2895 set_filebuf_watermark(buffer_margin);
2896 track_id3->elapsed = 0;
2899 if (offset > 0)
2901 switch (id3.codectype) {
2902 case AFMT_MPA_L1:
2903 case AFMT_MPA_L2:
2904 case AFMT_MPA_L3:
2905 track_id3->offset = offset;
2906 audio_set_elapsed(&id3);
2907 ci.curpos = offset;
2908 break;
2910 case AFMT_WAVPACK:
2911 track_id3->offset = offset;
2912 track_id3->elapsed = id3.length / 2;
2913 ci.curpos = offset;
2914 break;
2916 case AFMT_OGG_VORBIS:
2917 case AFMT_SPEEX:
2918 case AFMT_FLAC:
2919 case AFMT_PCM_WAV:
2920 case AFMT_A52:
2921 case AFMT_AAC:
2922 case AFMT_MPC:
2923 case AFMT_APE:
2924 track_id3->offset = offset;
2925 break;
2929 logf("alt:%s", trackname);
2930 /* tracks[track_widx].buf_idx = buf_widx; */
2932 //return audio_read_file(rebuffer);
2934 tracks[track_widx].audio_hid = bufopen(trackname, offset, TYPE_AUDIO);
2936 if (tracks[track_widx].audio_hid <= 0)
2937 return false;
2939 if (start_play)
2941 LOGFQUEUE("audio >| buffering Q_BUFFER_HANDLE");
2942 queue_send(&buffering_queue, Q_BUFFER_HANDLE, tracks[track_widx].audio_hid);
2944 else
2946 LOGFQUEUE("audio > buffering Q_BUFFER_HANDLE");
2947 queue_post(&buffering_queue, Q_BUFFER_HANDLE, tracks[track_widx].audio_hid);
2950 track_widx++;
2951 track_widx &= MAX_TRACK_MASK;
2953 return true;
2956 static bool audio_read_next_metadata(void)
2958 int fd;
2959 char *trackname;
2960 int next_idx;
2961 int status;
2963 next_idx = track_widx;
2964 if (tracks[next_idx].id3_hid > 0)
2966 next_idx++;
2967 next_idx &= MAX_TRACK_MASK;
2969 if (tracks[next_idx].id3_hid > 0)
2970 return true;
2973 trackname = playlist_peek(last_peek_offset + 1);
2974 if (!trackname)
2975 return false;
2977 fd = open(trackname, O_RDONLY);
2978 if (fd < 0)
2979 return false;
2981 struct mp3entry id3;
2983 status = get_metadata(&id3, fd, trackname);
2984 /* Preload the glyphs in the tags */
2985 if (status)
2987 tracks[next_idx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
2989 if (tracks[next_idx].id3_hid > 0)
2991 tracks[next_idx].taginfo_ready = true;
2992 if (id3.title)
2993 lcd_getstringsize(id3.title, NULL, NULL);
2994 if (id3.artist)
2995 lcd_getstringsize(id3.artist, NULL, NULL);
2996 if (id3.album)
2997 lcd_getstringsize(id3.album, NULL, NULL);
2999 else
3000 status = false;
3002 close(fd);
3004 return status;
3007 /* Send callback events to notify about new tracks. */
3008 static void audio_generate_postbuffer_events(void)
3010 int cur_idx;
3011 int last_idx = -1;
3013 logf("Postbuffer:%d/%d",track_ridx,track_widx);
3015 if (audio_have_tracks())
3017 cur_idx = track_ridx;
3019 while (1) {
3020 if (!tracks[cur_idx].event_sent)
3022 if (last_idx >= 0 && !tracks[last_idx].event_sent)
3024 /* Mark the event 'sent' even if we don't really send one */
3025 tracks[last_idx].event_sent = true;
3026 if (track_buffer_callback)
3027 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
3029 last_idx = cur_idx;
3031 if (cur_idx == track_widx)
3032 break;
3033 cur_idx++;
3034 cur_idx &= MAX_TRACK_MASK;
3037 if (last_idx >= 0 && !tracks[last_idx].event_sent)
3039 tracks[last_idx].event_sent = true;
3040 if (track_buffer_callback)
3041 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
3046 static bool audio_initialize_buffer_fill(bool clear_tracks)
3048 /* Don't initialize if we're already initialized */
3049 if (filling)
3050 return true;
3052 logf("Starting buffer fill");
3054 /* Set the filling flag true before calling audio_clear_tracks as that
3055 * function can yield and we start looping. */
3056 filling = true;
3058 if (clear_tracks)
3059 audio_clear_track_entries(false);
3061 /* Save the current resume position once. */
3062 playlist_update_resume_info(audio_current_track());
3064 return true;
3067 static void audio_fill_file_buffer(
3068 bool start_play, bool rebuffer, size_t offset)
3070 bool had_next_track = audio_next_track() != NULL;
3071 bool continue_buffering;
3073 /* Must reset the buffer before use if trashed or voice only - voice
3074 file size shouldn't have changed so we can go straight from
3075 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
3076 if (buffer_state != BUFFER_STATE_INITIALIZED)
3077 audio_reset_buffer();
3079 if (!audio_initialize_buffer_fill(!start_play))
3080 return ;
3082 continue_buffering = audio_load_track(offset, start_play, rebuffer);
3084 if (!had_next_track && audio_next_track())
3085 track_changed = true;
3087 /* If we're done buffering */
3088 if (!continue_buffering)
3090 //audio_read_next_metadata();
3092 audio_generate_postbuffer_events();
3093 filling = false;
3095 #ifndef SIMULATOR
3096 ata_sleep();
3097 #endif
3101 static void audio_rebuffer(void)
3103 logf("Forcing rebuffer");
3105 #if 0
3106 /* Stop in progress fill, and clear open file descriptor */
3107 if (current_fd >= 0)
3109 close(current_fd);
3110 current_fd = -1;
3112 filling = false;
3114 /* Reset buffer and track pointers */
3115 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3116 track_widx = track_ridx;
3117 audio_clear_track_entries(true);
3118 CUR_TI->available = 0;
3120 /* Fill the buffer */
3121 last_peek_offset = -1;
3122 CUR_TI->filesize = 0;
3123 CUR_TI->start_pos = 0;
3124 ci.curpos = 0;
3126 if (!CUR_TI->taginfo_ready)
3127 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3129 audio_fill_file_buffer(false, true, 0);
3130 #endif
3133 static int audio_check_new_track(void)
3135 DEBUGF("audio_check_new_track\n");
3137 int track_count = audio_track_count();
3138 int old_track_ridx = track_ridx;
3139 int next_idx;
3140 bool forward;
3142 if (dir_skip)
3144 dir_skip = false;
3145 if (playlist_next_dir(ci.new_track))
3147 ci.new_track = 0;
3148 CUR_TI->taginfo_ready = false;
3149 audio_rebuffer();
3150 goto skip_done;
3152 else
3154 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3155 return Q_CODEC_REQUEST_FAILED;
3159 if (new_playlist)
3160 ci.new_track = 0;
3162 /* If the playlist isn't that big */
3163 if (!playlist_check(ci.new_track))
3165 if (ci.new_track >= 0)
3167 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3168 return Q_CODEC_REQUEST_FAILED;
3170 /* Find the beginning backward if the user over-skips it */
3171 while (!playlist_check(++ci.new_track))
3172 if (ci.new_track >= 0)
3174 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3175 return Q_CODEC_REQUEST_FAILED;
3178 /* Update the playlist */
3179 last_peek_offset -= ci.new_track;
3181 if (playlist_next(ci.new_track) < 0)
3183 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3184 return Q_CODEC_REQUEST_FAILED;
3187 if (new_playlist)
3189 ci.new_track = 1;
3190 new_playlist = false;
3193 /* Save the old track */
3194 /* prev_ti = CUR_TI; */
3196 int i, idx;
3197 for (i = 0; i < ci.new_track; i++)
3199 idx = (track_ridx + i) & MAX_TRACK_MASK;
3200 close_track_handles(&tracks[idx]);
3203 /* Move to the new track */
3204 track_ridx += ci.new_track;
3205 track_ridx &= MAX_TRACK_MASK;
3207 if (CUR_TI->id3_hid > 0)
3208 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
3210 next_idx = track_ridx + 1;
3211 next_idx &= MAX_TRACK_MASK;
3213 if (tracks[next_idx].id3_hid > 0)
3214 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
3216 if (automatic_skip)
3217 playlist_end = false;
3219 track_changed = !automatic_skip;
3221 /* If it is not safe to even skip this many track entries */
3222 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3224 ci.new_track = 0;
3225 CUR_TI->taginfo_ready = false;
3226 audio_rebuffer();
3227 goto skip_done;
3230 forward = ci.new_track > 0;
3231 ci.new_track = 0;
3233 /* If the target track is clearly not in memory */
3234 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3236 audio_rebuffer();
3237 goto skip_done;
3240 /* The track may be in memory, see if it really is */
3241 if (forward)
3243 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3244 audio_rebuffer();
3246 else
3248 int cur_idx = track_ridx;
3249 bool taginfo_ready = true;
3250 bool wrap = track_ridx > old_track_ridx;
3252 while (1)
3254 cur_idx++;
3255 cur_idx &= MAX_TRACK_MASK;
3256 if (!(wrap || cur_idx < old_track_ridx))
3257 break;
3259 /* If we hit a track in between without valid tag info, bail */
3260 if (!tracks[cur_idx].taginfo_ready)
3262 taginfo_ready = false;
3263 break;
3266 tracks[cur_idx].available = tracks[cur_idx].filesize;
3267 if (tracks[cur_idx].codecsize)
3268 tracks[cur_idx].has_codec = true;*/
3270 if (taginfo_ready)
3272 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3273 audio_rebuffer();
3275 else
3277 CUR_TI->taginfo_ready = false;
3278 audio_rebuffer();
3282 skip_done:
3283 audio_update_trackinfo();
3284 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3285 return Q_CODEC_REQUEST_COMPLETE;
3288 static int audio_rebuffer_and_seek(size_t newpos)
3290 #if 0
3291 size_t real_preseek;
3292 int fd;
3293 char *trackname;
3295 /* (Re-)open current track's file handle. */
3296 trackname = playlist_peek(0);
3297 fd = open(trackname, O_RDONLY);
3298 if (fd < 0)
3300 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3301 return Q_CODEC_REQUEST_FAILED;
3304 if (current_fd >= 0)
3305 close(current_fd);
3306 current_fd = fd;
3308 playlist_end = false;
3310 ci.curpos = newpos;
3312 /* Clear codec buffer. */
3313 track_widx = track_ridx;
3314 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3316 last_peek_offset = 0;
3317 filling = false;
3318 audio_initialize_buffer_fill(true);
3320 /* This may have been tweaked by the id3v1 code */
3321 CUR_TI->filesize=filesize(fd);
3322 if (newpos > conf_preseek)
3324 CUR_TI->start_pos = newpos - conf_preseek;
3325 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3326 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3327 real_preseek = conf_preseek;
3329 else
3331 CUR_TI->start_pos = 0;
3332 CUR_TI->filerem = CUR_TI->filesize;
3333 real_preseek = newpos;
3336 CUR_TI->available = 0;
3338 audio_read_file(real_preseek);
3340 /* Account for the data we just read that is 'behind' us now */
3341 CUR_TI->available -= real_preseek;
3343 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3345 #endif
3346 (void)newpos;
3347 DEBUGF("/!\\ not implemented /!\\");
3348 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3349 return Q_CODEC_REQUEST_COMPLETE;
3352 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3353 bool last_track))
3355 track_buffer_callback = handler;
3358 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3359 bool last_track))
3361 track_unbuffer_callback = handler;
3364 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3366 track_changed_callback = handler;
3369 unsigned long audio_prev_elapsed(void)
3371 return prev_track_elapsed;
3374 static void audio_stop_codec_flush(void)
3376 ci.stop_codec = true;
3377 pcmbuf_pause(true);
3379 while (audio_codec_loaded)
3380 yield();
3382 /* If the audio codec is not loaded any more, and the audio is still
3383 * playing, it is now and _only_ now safe to call this function from the
3384 * audio thread */
3385 if (pcm_is_playing())
3386 pcmbuf_play_stop();
3387 pcmbuf_pause(paused);
3390 static void audio_stop_playback(void)
3392 /* If we were playing, save resume information */
3393 if (playing)
3395 struct mp3entry *id3 = NULL;
3397 if (!playlist_end || !ci.stop_codec)
3399 /* Set this early, the outside code yields and may allow the codec
3400 to try to wait for a reply on a buffer wait */
3401 ci.stop_codec = true;
3402 id3 = audio_current_track();
3405 /* Save the current playing spot, or NULL if the playlist has ended */
3406 playlist_update_resume_info(id3);
3408 prev_track_elapsed = curtrack_id3.elapsed;
3410 /* Increment index so runtime info is saved in audio_clear_track_entries().
3411 * Done here, as audio_stop_playback() may be called more than once.
3412 * Don't update runtime unless playback is stopped because of end of playlist.
3413 * Updating runtime when manually stopping a tracks, can destroy autoscores
3414 * and playcounts.
3416 if (playlist_end)
3418 track_ridx++;
3419 track_ridx &= MAX_TRACK_MASK;
3423 filling = false;
3424 paused = false;
3425 audio_stop_codec_flush();
3426 playing = false;
3428 /* Mark all entries null. */
3429 audio_clear_track_entries(false);
3431 /* Close all tracks */
3432 audio_release_tracks();
3435 static void audio_play_start(size_t offset)
3437 #if INPUT_SRC_CAPS != 0
3438 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3439 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3440 #endif
3442 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3443 paused = false;
3444 audio_stop_codec_flush();
3446 track_changed = true;
3447 playlist_end = false;
3449 playing = true;
3451 ci.new_track = 0;
3452 ci.seek_time = 0;
3453 wps_offset = 0;
3455 sound_set_volume(global_settings.volume);
3456 track_widx = track_ridx = 0;
3458 /* Mark all entries null. */
3459 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3461 last_peek_offset = -1;
3463 /* Officially playing */
3464 queue_reply(&audio_queue, 1);
3466 audio_fill_file_buffer(true, false, offset);
3468 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3469 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3473 /* Invalidates all but currently playing track. */
3474 static void audio_invalidate_tracks(void)
3476 #if 0
3477 if (audio_have_tracks())
3479 last_peek_offset = 0;
3480 playlist_end = false;
3481 track_widx = track_ridx;
3483 /* Mark all other entries null (also buffered wrong metadata). */
3484 audio_clear_track_entries(true);
3486 /* If the current track is fully buffered, advance the write pointer */
3487 if (tracks[track_widx].filerem == 0)
3488 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3490 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3492 audio_read_next_metadata();
3494 #endif
3497 static void audio_new_playlist(void)
3499 /* Prepare to start a new fill from the beginning of the playlist */
3500 last_peek_offset = -1;
3501 if (audio_have_tracks())
3503 if (paused)
3504 skipped_during_pause = true;
3505 playlist_end = false;
3506 track_widx = track_ridx;
3507 audio_clear_track_entries(true);
3509 track_widx++;
3510 track_widx &= MAX_TRACK_MASK;
3512 /* Mark the current track as invalid to prevent skipping back to it */
3513 CUR_TI->taginfo_ready = false;
3516 /* Signal the codec to initiate a track change forward */
3517 new_playlist = true;
3518 ci.new_track = 1;
3520 /* Officially playing */
3521 queue_reply(&audio_queue, 1);
3523 audio_fill_file_buffer(false, true, 0);
3526 static void audio_initiate_track_change(long direction)
3528 playlist_end = false;
3529 ci.new_track += direction;
3530 wps_offset -= direction;
3531 if (paused)
3532 skipped_during_pause = true;
3535 static void audio_initiate_dir_change(long direction)
3537 playlist_end = false;
3538 dir_skip = true;
3539 ci.new_track = direction;
3540 if (paused)
3541 skipped_during_pause = true;
3545 * Layout audio buffer as follows - iram buffer depends on target:
3546 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3548 static void audio_reset_buffer(void)
3550 /* see audio_get_recording_buffer if this is modified */
3551 logf("audio_reset_buffer");
3553 /* If the setup of anything allocated before the file buffer is
3554 changed, do check the adjustments after the buffer_alloc call
3555 as it will likely be affected and need sliding over */
3557 /* Initially set up file buffer as all space available */
3558 malloc_buf = audiobuf + talk_get_bufsize();
3559 /* Align the malloc buf to line size. Especially important to cf
3560 targets that do line reads/writes. */
3561 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3562 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3563 filebuflen = audiobufend - filebuf;
3565 /* Allow for codec swap space at end of audio buffer */
3566 if (talk_voice_required())
3568 /* Layout of swap buffer:
3569 * #ifdef IRAM_STEAL (dedicated iram_buf):
3570 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3571 * #else:
3572 * audiobuf...|dram_buf|iram_buf|audiobufend
3574 #ifdef PLAYBACK_VOICE
3575 /* Check for an absolutely nasty situation which should never,
3576 ever happen - frankly should just panic */
3577 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3579 logf("buffer reset with voice swapped");
3581 /* line align length which line aligns the calculations below since
3582 all sizes are also at least line aligned - needed for memswap128 */
3583 filebuflen &= ~15;
3584 #ifdef IRAM_STEAL
3585 filebuflen -= CODEC_SIZE;
3586 #else
3587 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3588 #endif
3589 /* Allocate buffers for swapping voice <=> audio */
3590 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3591 and out of the way of buffer usage or else a call to audio_get_buffer
3592 and subsequent buffer use might trash the swap space. A plugin
3593 initializing IRAM after getting the full buffer would present similar
3594 problem. Options include: failing the request if the other buffer
3595 has been obtained already or never allowing use of the voice IRAM
3596 buffer within the audio buffer. Using buffer_alloc basically
3597 implements the second in a more convenient way. */
3598 dram_buf = filebuf + filebuflen;
3600 #ifdef IRAM_STEAL
3601 /* Allocate voice IRAM swap buffer once */
3602 if (iram_buf == NULL)
3604 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3605 /* buffer_alloc moves audiobuf; this is safe because only the end
3606 * has been touched so far in this function and the address of
3607 * filebuf + filebuflen is not changed */
3608 malloc_buf += CODEC_IRAM_SIZE;
3609 filebuf += CODEC_IRAM_SIZE;
3610 filebuflen -= CODEC_IRAM_SIZE;
3612 #else
3613 /* Allocate iram_buf after dram_buf */
3614 iram_buf = dram_buf + CODEC_SIZE;
3615 #endif /* IRAM_STEAL */
3616 #endif /* PLAYBACK_VOICE */
3618 else
3620 #ifdef PLAYBACK_VOICE
3621 /* No swap buffers needed */
3622 iram_buf = NULL;
3623 dram_buf = NULL;
3624 #endif
3627 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3628 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3630 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3631 will already be line aligned */
3632 filebuflen &= ~3;
3634 /* Set the high watermark as 75% full...or 25% empty :) */
3635 #if MEM > 8
3636 high_watermark = 3*filebuflen / 4;
3637 #endif
3639 /* Clear any references to the file buffer */
3640 buffer_state = BUFFER_STATE_INITIALIZED;
3642 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3643 /* Make sure everything adds up - yes, some info is a bit redundant but
3644 aids viewing and the sumation of certain variables should add up to
3645 the location of others. */
3647 size_t pcmbufsize;
3648 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3649 logf("mabuf: %08X", (unsigned)malloc_buf);
3650 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3651 logf("fbuf: %08X", (unsigned)filebuf);
3652 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3653 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3654 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3655 logf("pcmb: %08X", (unsigned)pcmbuf);
3656 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3657 if (dram_buf)
3659 logf("dramb: %08X", (unsigned)dram_buf);
3660 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3662 if (iram_buf)
3664 logf("iramb: %08X", (unsigned)iram_buf);
3665 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3668 #endif
3671 #if MEM > 8
3672 /* we dont want this rebuffering on targets with little ram
3673 because the disk may never spin down */
3674 static bool ata_fillbuffer_callback(void)
3676 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3677 return true;
3679 #endif
3681 static void audio_thread(void)
3683 struct queue_event ev;
3685 pcm_postinit();
3687 #ifdef PLAYBACK_VOICE
3688 /* Unlock semaphore that init stage locks before creating this thread */
3689 semaphore_release(&sem_codecthread);
3691 /* Buffers must be set up by now - should panic - really */
3692 if (buffer_state != BUFFER_STATE_INITIALIZED)
3694 logf("audio_thread start: no buffer");
3697 /* Have to wait for voice to load up or else the codec swap will be
3698 invalid when an audio codec is loaded */
3699 wait_for_voice_swap_in();
3700 #endif
3702 while (1)
3704 if (filling)
3706 queue_wait_w_tmo(&audio_queue, &ev, 0);
3707 if (ev.id == SYS_TIMEOUT)
3708 ev.id = Q_AUDIO_FILL_BUFFER;
3710 else
3712 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3713 #if MEM > 8
3714 if (playing && (ev.id == SYS_TIMEOUT) &&
3715 (bufused() < high_watermark))
3716 register_ata_idle_func(ata_fillbuffer_callback);
3717 #endif
3720 switch (ev.id) {
3721 #if MEM > 8
3722 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3723 /* only fill if the disk is still spining */
3724 #ifndef SIMULATOR
3725 if (!ata_disk_is_active())
3726 break;
3727 #endif
3728 #endif /* MEM > 8 */
3729 /* else fall through to Q_AUDIO_FILL_BUFFER */
3730 case Q_AUDIO_FILL_BUFFER:
3731 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3732 if (!filling)
3733 if (!playing || playlist_end || ci.stop_codec)
3734 break;
3735 audio_fill_file_buffer(false, false, 0);
3736 break;
3738 case Q_AUDIO_PLAY:
3739 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3740 if (playing && ev.data <= 0)
3741 audio_new_playlist();
3742 else
3744 audio_stop_playback();
3745 audio_play_start((size_t)ev.data);
3747 break;
3749 case Q_AUDIO_STOP:
3750 LOGFQUEUE("audio < Q_AUDIO_STOP");
3751 if (playing)
3752 audio_stop_playback();
3753 if (ev.data != 0)
3754 queue_clear(&audio_queue);
3755 break;
3757 case Q_AUDIO_PAUSE:
3758 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3759 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3760 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3761 skipped_during_pause = false;
3762 if (!playing)
3763 break;
3764 pcmbuf_pause((bool)ev.data);
3765 paused = (bool)ev.data;
3766 break;
3768 case Q_AUDIO_SKIP:
3769 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3770 audio_initiate_track_change((long)ev.data);
3771 break;
3773 case Q_AUDIO_PRE_FF_REWIND:
3774 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3775 if (!playing)
3776 break;
3777 pcmbuf_pause(true);
3778 break;
3780 case Q_AUDIO_FF_REWIND:
3781 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3782 if (!playing)
3783 break;
3784 ci.seek_time = (long)ev.data+1;
3785 break;
3787 case Q_AUDIO_REBUFFER_SEEK:
3788 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3789 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3790 break;
3792 case Q_AUDIO_CHECK_NEW_TRACK:
3793 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3794 queue_reply(&audio_queue, audio_check_new_track());
3795 break;
3797 case Q_AUDIO_DIR_SKIP:
3798 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3799 playlist_end = false;
3800 audio_initiate_dir_change(ev.data);
3801 break;
3803 case Q_AUDIO_FLUSH:
3804 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3805 audio_invalidate_tracks();
3806 break;
3808 case Q_AUDIO_TRACK_CHANGED:
3809 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3810 if (track_changed_callback)
3811 track_changed_callback(&curtrack_id3);
3812 track_changed = true;
3813 playlist_update_resume_info(audio_current_track());
3814 break;
3816 #ifndef SIMULATOR
3817 case SYS_USB_CONNECTED:
3818 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3819 if (playing)
3820 audio_stop_playback();
3821 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3822 usb_wait_for_disconnect(&audio_queue);
3823 break;
3824 #endif
3826 case SYS_TIMEOUT:
3827 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3828 break;
3830 default:
3831 //LOGFQUEUE("audio < default");
3832 break;
3833 } /* end switch */
3834 } /* end while */
3837 #ifdef ROCKBOX_HAS_LOGF
3838 static void audio_test_track_changed_event(struct mp3entry *id3)
3840 (void)id3;
3842 logf("tce:%s", id3->path);
3844 #endif
3846 /* Initialize the audio system - called from init() in main.c.
3847 * Last function because of all the references to internal symbols
3849 void audio_init(void)
3851 #ifdef PLAYBACK_VOICE
3852 static bool voicetagtrue = true;
3853 static struct mp3entry id3_voice;
3854 struct thread_entry *voice_thread_p = NULL;
3855 #endif
3856 struct thread_entry *audio_thread_p;
3858 /* Can never do this twice */
3859 if (audio_is_initialized)
3861 logf("audio: already initialized");
3862 return;
3865 logf("audio: initializing");
3867 /* Initialize queues before giving control elsewhere in case it likes
3868 to send messages. Thread creation will be delayed however so nothing
3869 starts running until ready if something yields such as talk_init. */
3870 #ifdef PLAYBACK_VOICE
3871 /* Take ownership of lock to prevent playback of anything before audio
3872 hardware is initialized - audio thread unlocks it after final init
3873 stage */
3874 semaphore_init(&sem_codecthread, 1, 0);
3875 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3876 #endif
3877 queue_init(&audio_queue, true);
3878 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3879 queue_init(&codec_queue, true);
3880 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3882 pcm_init();
3884 #ifdef ROCKBOX_HAS_LOGF
3885 audio_set_track_changed_event(audio_test_track_changed_event);
3886 #endif
3888 /* Initialize codec api. */
3889 ci.read_filebuf = codec_filebuf_callback;
3890 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3891 ci.get_codec_memory = codec_get_memory_callback;
3892 ci.request_buffer = codec_request_buffer_callback;
3893 ci.advance_buffer = codec_advance_buffer_callback;
3894 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3895 ci.request_next_track = codec_request_next_track_callback;
3896 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3897 ci.seek_buffer = codec_seek_buffer_callback;
3898 ci.seek_complete = codec_seek_complete_callback;
3899 ci.set_elapsed = codec_set_elapsed_callback;
3900 ci.set_offset = codec_set_offset_callback;
3901 ci.configure = codec_configure_callback;
3902 ci.discard_codec = codec_discard_codec_callback;
3904 /* Initialize voice codec api. */
3905 #ifdef PLAYBACK_VOICE
3906 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3907 memset(&id3_voice, 0, sizeof(id3_voice));
3908 ci_voice.read_filebuf = voice_filebuf_callback;
3909 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3910 ci_voice.get_codec_memory = voice_get_memory_callback;
3911 ci_voice.request_buffer = voice_request_buffer_callback;
3912 ci_voice.advance_buffer = voice_advance_buffer_callback;
3913 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3914 ci_voice.request_next_track = voice_request_next_track_callback;
3915 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3916 ci_voice.seek_buffer = voice_seek_buffer_callback;
3917 ci_voice.seek_complete = voice_do_nothing;
3918 ci_voice.set_elapsed = voice_set_elapsed_callback;
3919 ci_voice.set_offset = voice_set_offset_callback;
3920 ci_voice.configure = voice_configure_callback;
3921 ci_voice.discard_codec = voice_do_nothing;
3922 ci_voice.taginfo_ready = &voicetagtrue;
3923 ci_voice.id3 = &id3_voice;
3924 id3_voice.frequency = 11200;
3925 id3_voice.length = 1000000L;
3926 #endif
3928 /* initialize the buffer */
3929 filebuf = audiobuf;
3931 /* audio_reset_buffer must to know the size of voice buffer so init
3932 talk first */
3933 talk_init();
3935 codec_thread_p = create_thread(
3936 codec_thread, codec_stack, sizeof(codec_stack),
3937 CREATE_THREAD_FROZEN,
3938 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3939 IF_COP(, CPU));
3941 audio_thread_p = create_thread(audio_thread, audio_stack,
3942 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3943 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3944 IF_COP(, CPU));
3946 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
3947 sizeof(buffering_stack), CREATE_THREAD_FROZEN,
3948 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3949 IF_COP(, CPU, true));
3951 #ifdef PLAYBACK_VOICE
3952 /* TODO: Change this around when various speech codecs can be used */
3953 if (talk_voice_required())
3955 logf("Starting voice codec");
3956 queue_init(&voice_queue, true);
3957 voice_thread_p = create_thread(voice_thread, voice_stack,
3958 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3959 voice_thread_name
3960 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3962 #endif
3964 /* Set crossfade setting for next buffer init which should be about... */
3965 pcmbuf_crossfade_enable(global_settings.crossfade);
3967 /* ...now! Set up the buffers */
3968 audio_reset_buffer();
3970 buffering_init(filebuf, filebuflen);
3972 /* Probably safe to say */
3973 audio_is_initialized = true;
3975 sound_settings_apply();
3976 #ifdef HAVE_WM8758
3977 eq_hw_enable(global_settings.eq_hw_enabled);
3978 #endif
3979 #ifndef HAVE_FLASH_STORAGE
3980 audio_set_buffer_margin(global_settings.buffer_margin);
3981 #endif
3983 /* it's safe to let the threads run now */
3984 thread_thaw(codec_thread_p);
3985 #ifdef PLAYBACK_VOICE
3986 if (voice_thread_p)
3987 thread_thaw(voice_thread_p);
3988 #endif
3989 thread_thaw(audio_thread_p);
3990 thread_thaw(buffering_thread_p);
3991 } /* audio_init */