Make the audio thread wait with a timeout even when filling
[Rockbox.git] / apps / playback.c
blobb8ce456ee6dd180e54f2cdd591cda79430748d9f
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
34 #include "system.h"
35 #include "thread.h"
36 #include "file.h"
37 #include "panic.h"
38 #include "memory.h"
39 #include "lcd.h"
40 #include "font.h"
41 #include "button.h"
42 #include "kernel.h"
43 #include "tree.h"
44 #include "debug.h"
45 #include "sprintf.h"
46 #include "settings.h"
47 #include "codecs.h"
48 #include "audio.h"
49 #include "buffering.h"
50 #include "mp3_playback.h"
51 #include "usb.h"
52 #include "status.h"
53 #include "ata.h"
54 #include "screens.h"
55 #include "playlist.h"
56 #include "playback.h"
57 #include "pcmbuf.h"
58 #include "buffer.h"
59 #include "dsp.h"
60 #include "abrepeat.h"
61 #include "cuesheet.h"
62 #ifdef HAVE_TAGCACHE
63 #include "tagcache.h"
64 #endif
65 #ifdef HAVE_LCD_BITMAP
66 #include "icons.h"
67 #include "peakmeter.h"
68 #include "action.h"
69 #endif
70 #include "lang.h"
71 #include "bookmark.h"
72 #include "misc.h"
73 #include "sound.h"
74 #include "metadata.h"
75 #include "splash.h"
76 #include "talk.h"
77 #include "ata_idle_notify.h"
79 #ifdef HAVE_RECORDING
80 #include "recording.h"
81 #include "talk.h"
82 #endif
84 #ifdef HAVE_WM8758
85 #include "menus/eq_menu.h"
86 #endif
88 #define PLAYBACK_VOICE
91 /* Define LOGF_ENABLE to enable logf output in this file */
92 /*#define LOGF_ENABLE*/
93 #include "logf.h"
95 /* macros to enable logf for queues
96 logging on SYS_TIMEOUT can be disabled */
97 #ifdef SIMULATOR
98 /* Define this for logf output of all queuing except SYS_TIMEOUT */
99 #define PLAYBACK_LOGQUEUES
100 /* Define this to logf SYS_TIMEOUT messages */
101 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
102 #endif
104 #ifdef PLAYBACK_LOGQUEUES
105 #define LOGFQUEUE logf
106 #else
107 #define LOGFQUEUE(...)
108 #endif
110 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
111 #define LOGFQUEUE_SYS_TIMEOUT logf
112 #else
113 #define LOGFQUEUE_SYS_TIMEOUT(...)
114 #endif
117 /* Define one constant that includes recording related functionality */
118 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
119 #define AUDIO_HAVE_RECORDING
120 #endif
122 enum {
123 Q_AUDIO_PLAY = 1,
124 Q_AUDIO_STOP,
125 Q_AUDIO_PAUSE,
126 Q_AUDIO_SKIP,
127 Q_AUDIO_PRE_FF_REWIND,
128 Q_AUDIO_FF_REWIND,
129 /* Q_AUDIO_REBUFFER_SEEK, */
130 Q_AUDIO_CHECK_NEW_TRACK,
131 Q_AUDIO_FLUSH,
132 Q_AUDIO_TRACK_CHANGED,
133 Q_AUDIO_DIR_SKIP,
134 Q_AUDIO_POSTINIT,
135 Q_AUDIO_FILL_BUFFER,
136 #if MEM > 8
137 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
138 #endif
139 Q_CODEC_REQUEST_COMPLETE,
140 Q_CODEC_REQUEST_FAILED,
142 Q_VOICE_PLAY,
143 Q_VOICE_STOP,
145 Q_CODEC_LOAD,
146 Q_CODEC_LOAD_DISK,
148 #ifdef AUDIO_HAVE_RECORDING
149 Q_ENCODER_LOAD_DISK,
150 Q_ENCODER_RECORD,
151 #endif
154 /* As defined in plugins/lib/xxx2wav.h */
155 #if MEM > 1
156 #define MALLOC_BUFSIZE (512*1024)
157 #define GUARD_BUFSIZE (32*1024)
158 #else
159 #define MALLOC_BUFSIZE (100*1024)
160 #define GUARD_BUFSIZE (8*1024)
161 #endif
163 /* As defined in plugin.lds */
164 #if defined(CPU_PP)
165 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
166 #define CODEC_IRAM_SIZE ((size_t)0xc000)
167 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
168 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
169 #define CODEC_IRAM_SIZE ((size_t)0x10000)
170 #else
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #endif
175 #ifndef IBSS_ATTR_VOICE_STACK
176 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
177 #endif
179 bool audio_is_initialized = false;
181 /* Variables are commented with the threads that use them: *
182 * A=audio, C=codec, V=voice. A suffix of - indicates that *
183 * the variable is read but not updated on that thread. */
184 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
186 /* Main state control */
187 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
188 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
189 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
190 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
192 /* Ring buffer where compressed audio and codecs are loaded */
193 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
194 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
195 /* FIXME: make filebuflen static */
196 size_t filebuflen = 0; /* Size of buffer (A/C-) */
197 /* FIXME: make buf_ridx (C/A-) */
199 /* Possible arrangements of the buffer */
200 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
201 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
202 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
203 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
205 static struct mp3entry curtrack_id3;
206 static struct mp3entry nexttrack_id3;
208 /* Track info structure about songs in the file buffer (A/C-) */
209 struct track_info {
210 int audio_hid; /* The ID for the track's buffer handle */
211 int id3_hid; /* The ID for the track's metadata handle */
212 int codec_hid; /* The ID for the track's codec handle */
214 size_t codecsize; /* Codec length in bytes */
215 size_t filesize; /* File total length */
217 bool taginfo_ready; /* Is metadata read */
219 bool event_sent; /* Was this track's buffered event sent */
222 static struct track_info tracks[MAX_TRACK];
223 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
224 static int track_widx = 0; /* Track being buffered (A) */
226 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
228 /* Set by the audio thread when the current track information has updated
229 * and the WPS may need to update its cached information */
230 static bool track_changed = false;
232 /* Information used only for filling the buffer */
233 /* Playlist steps from playing track to next track to be buffered (A) */
234 static int last_peek_offset = 0;
236 /* Scrobbler support */
237 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
239 /* Track change controls */
240 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
241 static bool playlist_end = false; /* Has the current playlist ended? (A) */
242 static bool dir_skip = false; /* Is a directory skip pending? (A) */
243 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
244 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
245 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
247 /* Callbacks which applications or plugins may set */
248 /* When the playing track has changed from the user's perspective */
249 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
250 /* When a track has been buffered */
251 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
252 /* When a track's buffer has been overwritten or cleared */
253 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
255 /* Configuration */
256 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
257 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
258 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
259 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
260 #if MEM > 8
261 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
262 #endif
264 /* Multiple threads */
265 static void set_current_codec(int codec_idx);
266 /* Set the watermark to trigger buffer fill (A/C) FIXME */
267 static void set_filebuf_watermark(int seconds);
269 /* Audio thread */
270 static struct event_queue audio_queue NOCACHEBSS_ATTR;
271 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
272 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
273 static const char audio_thread_name[] = "audio";
275 static void audio_thread(void);
276 static void audio_initiate_track_change(long direction);
277 static bool audio_have_tracks(void);
278 static void audio_reset_buffer(void);
280 /* Codec thread */
281 extern struct codec_api ci;
282 static struct event_queue codec_queue NOCACHEBSS_ATTR;
283 static struct queue_sender_list codec_queue_sender_list;
284 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
285 IBSS_ATTR;
286 static const char codec_thread_name[] = "codec";
287 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
289 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
291 /* Voice thread */
292 #ifdef PLAYBACK_VOICE
294 extern struct codec_api ci_voice;
296 static struct thread_entry *voice_thread_p = NULL;
297 static struct event_queue voice_queue NOCACHEBSS_ATTR;
298 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
299 IBSS_ATTR_VOICE_STACK;
300 static const char voice_thread_name[] = "voice codec";
302 /* Voice codec swapping control */
303 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
305 #ifdef SIMULATOR
306 /* IRAM codec swap buffer for sim*/
307 static unsigned char sim_iram[CODEC_IRAM_SIZE];
308 #undef CODEC_IRAM_ORIGIN
309 #define CODEC_IRAM_ORIGIN sim_iram
310 #endif
312 /* iram_buf and dram_buf are either both NULL or both non-NULL */
313 /* Pointer to IRAM buffer for codec swapping */
314 static unsigned char *iram_buf = NULL;
315 /* Pointer to DRAM buffer for codec swapping */
316 static unsigned char *dram_buf = NULL;
317 /* Parity of swap_codec calls - needed because one codec swapping itself in
318 automatically swaps in the other and the swap when unlocking should not
319 happen if the parity is even.
321 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
322 /* Locking to control which codec (normal/voice) is running */
323 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
324 static struct event event_codecthread NOCACHEBSS_ATTR;
326 /* Voice state */
327 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
328 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
329 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
330 static unsigned char *voicebuf = NULL;
331 static size_t voice_remaining = 0;
333 #ifdef IRAM_STEAL
334 /* Voice IRAM has been stolen for other use */
335 static bool voice_iram_stolen = false;
336 #endif
338 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
340 struct voice_info {
341 void (*callback)(unsigned char **start, size_t* size);
342 size_t size;
343 unsigned char *buf;
345 static void voice_thread(void);
346 static void voice_stop(void);
348 #endif /* PLAYBACK_VOICE */
351 /* --- Helper functions --- */
353 struct mp3entry *bufgetid3(int handle_id)
355 if (handle_id < 0)
356 return NULL;
358 struct mp3entry *id3;
359 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
361 if (ret < 0 || ret != sizeof(struct mp3entry))
362 return NULL;
364 return id3;
367 void *bufgetcodec(struct track_info *track)
369 void *ptr;
370 ssize_t ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
372 if (ret == -2) {
373 request_buffer_handle(CUR_TI->audio_hid);
376 while (ret == -2) {
377 sleep(1);
378 ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
381 if (ret < 0)
382 return NULL;
383 else
384 return ptr;
387 void clear_track_info(struct track_info *track)
389 if (!track)
390 return;
392 if (track->codec_hid > 0) {
393 bufclose(track->codec_hid);
396 if (track->id3_hid > 0) {
397 bufclose(track->id3_hid);
400 if (track->audio_hid > 0) {
401 bufclose(track->audio_hid);
404 memset(track, 0, sizeof(struct track_info));
407 /* --- External interfaces --- */
409 void mp3_play_data(const unsigned char* start, int size,
410 void (*get_more)(unsigned char** start, size_t* size))
412 #ifdef PLAYBACK_VOICE
413 static struct voice_info voice_clip;
414 voice_clip.callback = get_more;
415 voice_clip.buf = (unsigned char*)start;
416 voice_clip.size = size;
417 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
418 queue_post(&voice_queue, Q_VOICE_STOP, 0);
419 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
420 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
421 voice_thread_start = true;
422 trigger_cpu_boost();
423 #else
424 (void) start;
425 (void) size;
426 (void) get_more;
427 #endif
430 void mp3_play_stop(void)
432 #ifdef PLAYBACK_VOICE
433 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
434 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
435 queue_post(&voice_queue, Q_VOICE_STOP, 1);
436 #endif
439 void mp3_play_pause(bool play)
441 /* a dummy */
442 (void)play;
445 bool mp3_is_playing(void)
447 #ifdef PLAYBACK_VOICE
448 return voice_is_playing;
449 #else
450 return false;
451 #endif
454 /* If voice could be swapped out - wait for it to return
455 * Used by buffer claming functions.
457 static void wait_for_voice_swap_in(void)
459 #ifdef PLAYBACK_VOICE
460 if (NULL == iram_buf)
461 return;
463 event_wait(&event_codecthread, STATE_NONSIGNALED);
464 #endif /* PLAYBACK_VOICE */
467 /* This sends a stop message and the audio thread will dump all it's
468 subsequenct messages */
469 static void audio_hard_stop(void)
471 /* Stop playback */
472 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
473 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
476 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
478 unsigned char *buf, *end;
480 if (audio_is_initialized)
482 audio_hard_stop();
483 wait_for_voice_swap_in();
484 #ifdef PLAYBACK_VOICE
485 voice_stop();
486 #endif
488 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
490 if (buffer_size == NULL)
492 /* Special case for talk_init to use since it already knows it's
493 trashed */
494 buffer_state = BUFFER_STATE_TRASHED;
495 return NULL;
498 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
499 || !talk_voice_required())
501 logf("get buffer: talk, audio");
502 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
503 the talk buffer is not needed because voice isn't being used, or
504 could be BUFFER_STATE_TRASHED already. If state is
505 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
506 without the caller knowing what's going on. Changing certain settings
507 may move it to a worse condition but the memory in use by something
508 else will remain undisturbed.
510 if (buffer_state != BUFFER_STATE_TRASHED)
512 talk_buffer_steal();
513 buffer_state = BUFFER_STATE_TRASHED;
516 buf = audiobuf;
517 end = audiobufend;
519 else
521 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
522 still BUFFER_STATE_INITIALIZED */
523 /* Skip talk buffer and move pcm buffer to end to maximize available
524 contiguous memory - no audio running means voice will not need the
525 swap space */
526 logf("get buffer: audio");
527 buf = audiobuf + talk_get_bufsize();
528 end = audiobufend - pcmbuf_init(audiobufend);
529 buffer_state = BUFFER_STATE_VOICED_ONLY;
532 *buffer_size = end - buf;
534 return buf;
537 #ifdef IRAM_STEAL
538 void audio_iram_steal(void)
540 /* We need to stop audio playback in order to use codec IRAM */
541 audio_hard_stop();
543 #ifdef PLAYBACK_VOICE
544 if (NULL != iram_buf)
546 /* Can't already be stolen */
547 if (voice_iram_stolen)
548 return;
550 /* Must wait for voice to be current again if it is swapped which
551 would cause the caller's buffer to get clobbered when voice locks
552 and runs - we'll wait for it to lock and yield again then make sure
553 the ride has come to a complete stop */
554 wait_for_voice_swap_in();
555 voice_stop();
557 /* Save voice IRAM but just memcpy - safe to do here since voice
558 is current and no audio codec is loaded */
559 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
560 voice_iram_stolen = true;
562 else
564 /* Nothing much to do if no voice */
565 voice_iram_stolen = false;
567 #endif
569 #endif /* IRAM_STEAL */
571 #ifdef HAVE_RECORDING
572 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
574 /* Don't allow overwrite of voice swap area or we'll trash the
575 swapped-out voice codec but can use whole thing if none */
576 unsigned char *end;
578 /* Stop audio and voice. Wait for voice to swap in and be clear
579 of pending events to ensure trouble-free operation of encoders */
580 audio_hard_stop();
581 wait_for_voice_swap_in();
582 #ifdef PLAYBACK_VOICE
583 voice_stop();
584 #endif
585 talk_buffer_steal();
587 #ifdef PLAYBACK_VOICE
588 /* If no dram_buf, swap space not used and recording gets more
589 memory. Codec swap areas will remain unaffected by the next init
590 since they're allocated at the end of the buffer and their sizes
591 don't change between calls */
592 end = dram_buf;
593 if (NULL == end)
594 #endif /* PLAYBACK_VOICE */
595 end = audiobufend;
597 buffer_state = BUFFER_STATE_TRASHED;
599 *buffer_size = end - audiobuf;
601 return (unsigned char *)audiobuf;
604 bool audio_load_encoder(int afmt)
606 #ifndef SIMULATOR
607 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
608 if (!enc_fn)
609 return false;
611 audio_remove_encoder();
612 ci.enc_codec_loaded = 0; /* clear any previous error condition */
614 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
615 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
617 while (ci.enc_codec_loaded == 0)
618 yield();
620 logf("codec loaded: %d", ci.enc_codec_loaded);
622 return ci.enc_codec_loaded > 0;
623 #else
624 (void)afmt;
625 return true;
626 #endif
627 } /* audio_load_encoder */
629 void audio_remove_encoder(void)
631 #ifndef SIMULATOR
632 /* force encoder codec unload (if currently loaded) */
633 if (ci.enc_codec_loaded <= 0)
634 return;
636 ci.stop_encoder = true;
637 while (ci.enc_codec_loaded > 0)
638 yield();
639 #endif
640 } /* audio_remove_encoder */
642 #endif /* HAVE_RECORDING */
644 struct mp3entry* audio_current_track(void)
646 const char *filename;
647 const char *p;
648 static struct mp3entry temp_id3;
649 int cur_idx;
650 int offset = ci.new_track + wps_offset;
652 cur_idx = track_ridx + offset;
653 cur_idx &= MAX_TRACK_MASK;
655 if (cur_idx == track_ridx && *curtrack_id3.path)
656 return &curtrack_id3;
657 else if (tracks[cur_idx].id3_hid > 0)
658 return bufgetid3(tracks[cur_idx].id3_hid);
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 static void codec_advance_buffer_counters(size_t amount)
1508 bufadvance(CUR_TI->audio_hid, amount);
1509 ci.curpos += amount;
1511 /* Start buffer filling as necessary. */
1512 if (!pcmbuf_is_lowdata() && !buffering)
1514 if (useful_data(CUR_TI->audio_hid) < conf_watermark &&
1515 playing && !playlist_end)
1517 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1518 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1523 /* copy up-to size bytes into ptr and return the actual size copied */
1524 static size_t codec_filebuf_callback(void *ptr, size_t size)
1526 ssize_t copy_n;
1528 if (ci.stop_codec || !playing)
1529 return 0;
1531 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1533 /* Nothing requested OR nothing left */
1534 if (copy_n == 0)
1535 return 0;
1538 if (copy_n == -2)
1540 request_buffer_handle(CUR_TI->audio_hid);
1543 /* Let the disk buffer catch fill until enough data is available */
1544 while (copy_n == -2)
1546 sleep(1);
1548 if (ci.stop_codec || ci.new_track)
1549 return 0;
1551 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1554 /* Update read and other position pointers */
1555 codec_advance_buffer_counters(copy_n);
1557 /* Return the actual amount of data copied to the buffer */
1558 return copy_n;
1559 } /* codec_filebuf_callback */
1561 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1563 size_t copy_n = reqsize;
1564 ssize_t ret;
1565 void *ptr;
1567 if (!playing)
1569 *realsize = 0;
1570 return NULL;
1573 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1574 if (ret >= 0)
1575 copy_n = MIN((size_t)ret, reqsize);
1577 if (copy_n == 0)
1579 *realsize = 0;
1580 return NULL;
1583 if (ret == -2)
1585 request_buffer_handle(CUR_TI->audio_hid);
1588 /* Let the disk buffer catch fill until enough data is available */
1589 while (ret == -2)
1591 sleep(1);
1593 if (ci.stop_codec || ci.new_track)
1595 *realsize = 0;
1596 return NULL;
1598 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1600 copy_n = MIN((size_t)ret, reqsize);
1602 *realsize = copy_n;
1604 return ptr;
1605 } /* codec_request_buffer_callback */
1607 static int get_codec_base_type(int type)
1609 switch (type) {
1610 case AFMT_MPA_L1:
1611 case AFMT_MPA_L2:
1612 case AFMT_MPA_L3:
1613 return AFMT_MPA_L3;
1616 return type;
1619 static void codec_advance_buffer_callback(size_t amount)
1621 codec_advance_buffer_counters(amount);
1622 codec_set_offset_callback(ci.curpos);
1625 static void codec_advance_buffer_loc_callback(void *ptr)
1627 size_t amount = get_offset(CUR_TI->audio_hid, ptr);
1629 codec_advance_buffer_callback(amount);
1632 /* Copied from mpeg.c. Should be moved somewhere else. */
1633 static int codec_get_file_pos(void)
1635 int pos = -1;
1636 struct mp3entry *id3 = audio_current_track();
1638 if (id3->vbr)
1640 if (id3->has_toc)
1642 /* Use the TOC to find the new position */
1643 unsigned int percent, remainder;
1644 int curtoc, nexttoc, plen;
1646 percent = (id3->elapsed*100)/id3->length;
1647 if (percent > 99)
1648 percent = 99;
1650 curtoc = id3->toc[percent];
1652 if (percent < 99)
1653 nexttoc = id3->toc[percent+1];
1654 else
1655 nexttoc = 256;
1657 pos = (id3->filesize/256)*curtoc;
1659 /* Use the remainder to get a more accurate position */
1660 remainder = (id3->elapsed*100)%id3->length;
1661 remainder = (remainder*100)/id3->length;
1662 plen = (nexttoc - curtoc)*(id3->filesize/256);
1663 pos += (plen/100)*remainder;
1665 else
1667 /* No TOC exists, estimate the new position */
1668 pos = (id3->filesize / (id3->length / 1000)) *
1669 (id3->elapsed / 1000);
1672 else if (id3->bitrate)
1673 pos = id3->elapsed * (id3->bitrate / 8);
1674 else
1675 return -1;
1677 pos += id3->first_frame_offset;
1679 /* Don't seek right to the end of the file so that we can
1680 transition properly to the next song */
1681 if (pos >= (int)(id3->filesize - id3->id3v1len))
1682 pos = id3->filesize - id3->id3v1len - 1;
1684 return pos;
1687 static off_t codec_mp3_get_filepos_callback(int newtime)
1689 off_t newpos;
1691 curtrack_id3.elapsed = newtime;
1692 newpos = codec_get_file_pos();
1694 return newpos;
1697 static void codec_seek_complete_callback(void)
1699 logf("seek_complete");
1700 if (pcm_is_paused())
1702 /* If this is not a seamless seek, clear the buffer */
1703 pcmbuf_play_stop();
1704 dsp_configure(DSP_FLUSH, 0);
1706 /* If playback was not 'deliberately' paused, unpause now */
1707 if (!paused)
1708 pcmbuf_pause(false);
1710 ci.seek_time = 0;
1713 static bool codec_seek_buffer_callback(size_t newpos)
1715 logf("codec_seek_buffer_callback");
1717 int ret = bufseek(CUR_TI->audio_hid, newpos);
1718 if (ret == 0) {
1719 ci.curpos = newpos;
1720 return true;
1722 else {
1723 return false;
1727 static void codec_configure_callback(int setting, intptr_t value)
1729 switch (setting) {
1730 case CODEC_SET_FILEBUF_WATERMARK:
1731 conf_watermark = value;
1732 set_filebuf_watermark(buffer_margin);
1733 break;
1735 case CODEC_SET_FILEBUF_CHUNKSIZE:
1736 conf_filechunk = value;
1737 break;
1739 case CODEC_SET_FILEBUF_PRESEEK:
1740 conf_preseek = value;
1741 break;
1743 default:
1744 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1748 static void codec_track_changed(void)
1750 automatic_skip = false;
1751 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1752 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1755 static void codec_pcmbuf_track_changed_callback(void)
1757 pcmbuf_set_position_callback(NULL);
1758 codec_track_changed();
1761 static void codec_discard_codec_callback(void)
1763 if (CUR_TI->codec_hid > 0)
1765 bufclose(CUR_TI->codec_hid);
1766 CUR_TI->codec_hid = 0;
1767 CUR_TI->codecsize = 0;
1771 static inline void codec_gapless_track_change(void) {
1772 /* callback keeps the progress bar moving while the pcmbuf empties */
1773 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1774 /* set the pcmbuf callback for when the track really changes */
1775 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1778 static inline void codec_crossfade_track_change(void) {
1779 /* Initiate automatic crossfade mode */
1780 pcmbuf_crossfade_init(false);
1781 /* Notify the wps that the track change starts now */
1782 codec_track_changed();
1785 static void codec_track_skip_done(bool was_manual)
1787 int crossfade_mode = global_settings.crossfade;
1789 /* Manual track change (always crossfade or flush audio). */
1790 if (was_manual)
1792 pcmbuf_crossfade_init(true);
1793 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1794 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1796 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1797 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1798 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1800 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1802 if (global_settings.playlist_shuffle)
1803 /* shuffle mode is on, so crossfade: */
1804 codec_crossfade_track_change();
1805 else
1806 /* shuffle mode is off, so do a gapless track change */
1807 codec_gapless_track_change();
1809 else
1810 /* normal crossfade: */
1811 codec_crossfade_track_change();
1813 else
1814 /* normal gapless playback. */
1815 codec_gapless_track_change();
1818 static bool codec_load_next_track(void)
1820 intptr_t result = Q_CODEC_REQUEST_FAILED;
1822 prev_track_elapsed = curtrack_id3.elapsed;
1824 if (ci.seek_time)
1825 codec_seek_complete_callback();
1827 #ifdef AB_REPEAT_ENABLE
1828 ab_end_of_track_report();
1829 #endif
1831 logf("Request new track");
1833 if (ci.new_track == 0)
1835 ci.new_track++;
1836 automatic_skip = true;
1839 if (!ci.stop_codec)
1841 trigger_cpu_boost();
1842 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1843 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1846 switch (result)
1848 case Q_CODEC_REQUEST_COMPLETE:
1849 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1850 codec_track_skip_done(!automatic_skip);
1851 return true;
1853 case Q_CODEC_REQUEST_FAILED:
1854 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1855 ci.new_track = 0;
1856 ci.stop_codec = true;
1857 return false;
1859 default:
1860 LOGFQUEUE("codec |< default");
1861 ci.stop_codec = true;
1862 return false;
1866 static bool codec_request_next_track_callback(void)
1868 int prev_codectype;
1870 if (ci.stop_codec || !playing)
1871 return false;
1873 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1875 if (!codec_load_next_track())
1876 return false;
1878 /* Seek to the beginning of the new track because if the struct mp3entry was
1879 buffered, "elapsed" might not be zero (if the track has been played
1880 already but not unbuffered) */
1881 codec_seek_buffer_callback(0);
1883 /* Check if the next codec is the same file. */
1884 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1886 logf("New track loaded");
1887 codec_discard_codec_callback();
1888 return true;
1890 else
1892 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1893 return false;
1897 static void codec_thread(void)
1899 struct queue_event ev;
1900 int status;
1901 size_t wrap;
1903 while (1) {
1904 status = 0;
1905 queue_wait(&codec_queue, &ev);
1907 switch (ev.id) {
1908 case Q_CODEC_LOAD_DISK:
1909 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1910 queue_reply(&codec_queue, 1);
1911 audio_codec_loaded = true;
1912 #ifdef PLAYBACK_VOICE
1913 /* Don't sent messages to voice codec if it's already swapped
1914 out or it will never get this */
1915 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1917 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1918 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1920 semaphore_wait(&sem_codecthread);
1921 event_set_state(&event_codecthread, true);
1922 #endif
1923 set_current_codec(CODEC_IDX_AUDIO);
1924 ci.stop_codec = false;
1925 status = codec_load_file((const char *)ev.data, &ci);
1926 DEBUGF("codec_load = %d\n", status);
1927 #ifdef PLAYBACK_VOICE
1928 semaphore_release(&sem_codecthread);
1929 #endif
1930 break;
1932 case Q_CODEC_LOAD:
1933 LOGFQUEUE("codec < Q_CODEC_LOAD");
1934 if (CUR_TI->codec_hid <= 0) {
1935 logf("Codec slot is empty!");
1936 /* Wait for the pcm buffer to go empty */
1937 while (pcm_is_playing())
1938 yield();
1939 /* This must be set to prevent an infinite loop */
1940 ci.stop_codec = true;
1941 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1942 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1943 break;
1946 audio_codec_loaded = true;
1947 #ifdef PLAYBACK_VOICE
1948 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1950 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1951 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1953 semaphore_wait(&sem_codecthread);
1954 event_set_state(&event_codecthread, true);
1955 #endif
1956 set_current_codec(CODEC_IDX_AUDIO);
1957 ci.stop_codec = false;
1958 wrap = (size_t)&filebuf[filebuflen] - (size_t)bufgetcodec(CUR_TI);
1959 status = codec_load_ram(bufgetcodec(CUR_TI), CUR_TI->codecsize,
1960 &filebuf[0], wrap, &ci);
1961 #ifdef PLAYBACK_VOICE
1962 semaphore_release(&sem_codecthread);
1963 #endif
1964 break;
1966 #ifdef AUDIO_HAVE_RECORDING
1967 case Q_ENCODER_LOAD_DISK:
1968 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1969 audio_codec_loaded = false; /* Not audio codec! */
1970 #ifdef PLAYBACK_VOICE
1971 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1973 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1974 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
1976 semaphore_wait(&sem_codecthread);
1977 event_set_state(&event_codecthread, true);
1978 #endif
1979 logf("loading encoder");
1980 set_current_codec(CODEC_IDX_AUDIO);
1981 ci.stop_encoder = false;
1982 status = codec_load_file((const char *)ev.data, &ci);
1983 #ifdef PLAYBACK_VOICE
1984 semaphore_release(&sem_codecthread);
1985 #endif
1986 logf("encoder stopped");
1987 break;
1988 #endif /* AUDIO_HAVE_RECORDING */
1990 #ifndef SIMULATOR
1991 case SYS_USB_CONNECTED:
1992 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1993 queue_clear(&codec_queue);
1994 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1995 usb_wait_for_disconnect(&codec_queue);
1996 break;
1997 #endif
1999 default:
2000 LOGFQUEUE("codec < default");
2003 if (audio_codec_loaded)
2005 if (ci.stop_codec)
2007 status = CODEC_OK;
2008 if (!playing)
2009 pcmbuf_play_stop();
2012 audio_codec_loaded = false;
2015 switch (ev.id) {
2016 case Q_CODEC_LOAD_DISK:
2017 case Q_CODEC_LOAD:
2018 LOGFQUEUE("codec < Q_CODEC_LOAD");
2019 if (playing)
2021 if (ci.new_track || status != CODEC_OK)
2023 if (!ci.new_track)
2025 logf("Codec failure");
2026 gui_syncsplash(HZ*2, "Codec failure");
2029 if (!codec_load_next_track())
2031 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2032 /* End of playlist */
2033 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2034 break;
2037 else
2039 logf("Codec finished");
2040 if (ci.stop_codec)
2042 /* Wait for the audio to stop playing before
2043 * triggering the WPS exit */
2044 while(pcm_is_playing())
2046 curtrack_id3.elapsed =
2047 curtrack_id3.length - pcmbuf_get_latency();
2048 sleep(1);
2050 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2051 /* End of playlist */
2052 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2053 break;
2057 if (CUR_TI->codec_hid > 0)
2059 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2060 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2062 else
2064 const char *codec_fn =
2065 get_codec_filename(curtrack_id3.codectype);
2066 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2067 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2068 (intptr_t)codec_fn);
2071 break;
2073 #ifdef AUDIO_HAVE_RECORDING
2074 case Q_ENCODER_LOAD_DISK:
2075 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2077 if (status == CODEC_OK)
2078 break;
2080 logf("Encoder failure");
2081 gui_syncsplash(HZ*2, "Encoder failure");
2083 if (ci.enc_codec_loaded < 0)
2084 break;
2086 logf("Encoder failed to load");
2087 ci.enc_codec_loaded = -1;
2088 break;
2089 #endif /* AUDIO_HAVE_RECORDING */
2091 default:
2092 LOGFQUEUE("codec < default");
2094 } /* end switch */
2099 /* --- Audio thread --- */
2101 static bool audio_have_tracks(void)
2103 return track_ridx != track_widx || CUR_TI->filesize;
2106 static bool audio_have_free_tracks(void)
2108 if (track_widx < track_ridx)
2109 return track_widx + 1 < track_ridx;
2110 else if (track_ridx == 0)
2111 return track_widx < MAX_TRACK - 1;
2113 return true;
2116 int audio_track_count(void)
2118 if (audio_have_tracks())
2120 int relative_track_widx = track_widx;
2122 if (track_ridx > track_widx)
2123 relative_track_widx += MAX_TRACK;
2125 return relative_track_widx - track_ridx + 1;
2128 return 0;
2131 long audio_filebufused(void)
2133 return (long) bufused();
2136 static void audio_update_trackinfo(void)
2138 if (CUR_TI->id3_hid > 0)
2139 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
2141 CUR_TI->taginfo_ready = (CUR_TI->id3_hid > 0);
2143 int next_idx = track_ridx + 1;
2144 next_idx &= MAX_TRACK_MASK;
2146 if (tracks[next_idx].id3_hid > 0)
2147 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
2149 tracks[next_idx].taginfo_ready = (tracks[next_idx].id3_hid > 0);
2151 ci.filesize = CUR_TI->filesize;
2152 curtrack_id3.elapsed = 0;
2153 curtrack_id3.offset = 0;
2154 ci.id3 = &curtrack_id3;
2155 ci.curpos = 0;
2156 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2159 static void audio_clear_track_entries(bool clear_unbuffered)
2161 int cur_idx = track_widx;
2162 int last_idx = -1;
2164 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2166 /* Loop over all tracks from write-to-read */
2167 while (1)
2169 cur_idx++;
2170 cur_idx &= MAX_TRACK_MASK;
2172 if (cur_idx == track_ridx)
2173 break;
2175 /* If the track is buffered, conditionally clear/notify,
2176 * otherwise clear the track if that option is selected */
2177 if (tracks[cur_idx].event_sent)
2179 if (last_idx >= 0)
2181 /* If there is an unbuffer callback, call it, otherwise,
2182 * just clear the track */
2183 if (track_unbuffer_callback && tracks[last_idx].id3_hid > 0)
2184 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2186 clear_track_info(&tracks[last_idx]);
2188 last_idx = cur_idx;
2190 else if (clear_unbuffered)
2191 clear_track_info(&tracks[cur_idx]);
2194 /* We clear the previous instance of a buffered track throughout
2195 * the above loop to facilitate 'last' detection. Clear/notify
2196 * the last track here */
2197 if (last_idx >= 0)
2199 if (track_unbuffer_callback && tracks[last_idx].id3_hid > 0)
2200 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2201 clear_track_info(&tracks[last_idx]);
2205 static void audio_release_tracks(void)
2207 int i, cur_idx;
2209 logf("releasing all tracks");
2211 for(i = 0; i < MAX_TRACKS; i++)
2213 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
2214 clear_track_info(&tracks[cur_idx]);
2218 #if 0
2219 /* FIXME: This code should be made more generic and move to metadata.c */
2220 static void audio_strip_tags(void)
2222 int i;
2223 static const unsigned char tag[] = "TAG";
2224 static const unsigned char apetag[] = "APETAGEX";
2225 size_t tag_idx;
2226 size_t cur_idx;
2227 size_t len, version;
2229 tag_idx = RINGBUF_SUB(buf_widx, 128);
2231 if (bufused() > 128 && tag_idx > buf_ridx)
2233 cur_idx = tag_idx;
2234 for(i = 0;i < 3;i++)
2236 if(filebuf[cur_idx] != tag[i])
2237 goto strip_ape_tag;
2239 cur_idx = RINGBUF_ADD(cur_idx, 1);
2242 /* Skip id3v1 tag */
2243 logf("Skipping ID3v1 tag");
2244 buf_widx = tag_idx;
2245 tracks[track_widx].available -= 128;
2246 tracks[track_widx].filesize -= 128;
2249 strip_ape_tag:
2250 /* Check for APE tag (look for the APE tag footer) */
2251 tag_idx = RINGBUF_SUB(buf_widx, 32);
2253 if (bufused() > 32 && tag_idx > buf_ridx)
2255 cur_idx = tag_idx;
2256 for(i = 0;i < 8;i++)
2258 if(filebuf[cur_idx] != apetag[i])
2259 return;
2261 cur_idx = RINGBUF_ADD(cur_idx, 1);
2264 /* Read the version and length from the footer */
2265 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2266 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2267 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2268 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2269 if (version == 2000)
2270 len += 32; /* APEv2 has a 32 byte header */
2272 /* Skip APE tag */
2273 if (bufused() > len)
2275 logf("Skipping APE tag (%ldB)", len);
2276 buf_widx = RINGBUF_SUB(buf_widx, len);
2277 tracks[track_widx].available -= len;
2278 tracks[track_widx].filesize -= len;
2282 #endif
2284 static bool audio_loadcodec(bool start_play)
2286 int fd;
2287 int prev_track;
2288 char codec_path[MAX_PATH]; /* Full path to codec */
2290 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play ? "true" : "false");
2292 if (tracks[track_widx].id3_hid <= 0) {
2293 DEBUGF("track ID3 info not ready\n");
2294 return false;
2297 const char * codec_fn =
2298 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2299 if (codec_fn == NULL)
2300 return false;
2302 tracks[track_widx].codec_hid = 0;
2304 if (start_play)
2306 /* Load the codec directly from disk and save some memory. */
2307 track_ridx = track_widx;
2308 ci.filesize = CUR_TI->filesize;
2309 ci.id3 = &curtrack_id3;
2310 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2311 ci.curpos = 0;
2312 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2313 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2314 return true;
2316 else
2318 /* If we already have another track than this one buffered */
2319 if (track_widx != track_ridx)
2321 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2323 /* If the previous codec is the same as this one, there is no need
2324 * to put another copy of it on the file buffer */
2325 if (get_codec_base_type(
2326 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2327 get_codec_base_type(
2328 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2329 && audio_codec_loaded)
2331 logf("Reusing prev. codec");
2332 return true;
2337 codec_get_full_path(codec_path, codec_fn);
2339 fd = open(codec_path, O_RDONLY);
2340 if (fd < 0)
2342 logf("Codec doesn't exist!");
2343 return false;
2346 tracks[track_widx].codecsize = filesize(fd);
2348 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2349 if (tracks[track_widx].codec_hid < 0)
2351 logf("Not enough space");
2352 close(fd);
2353 return false;
2356 close(fd);
2357 logf("Loaded codec");
2359 return true;
2362 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2363 static void audio_set_elapsed(struct mp3entry* id3)
2365 unsigned long offset = id3->offset > id3->first_frame_offset ?
2366 id3->offset - id3->first_frame_offset : 0;
2368 if ( id3->vbr ) {
2369 if ( id3->has_toc ) {
2370 /* calculate elapsed time using TOC */
2371 int i;
2372 unsigned int remainder, plen, relpos, nextpos;
2374 /* find wich percent we're at */
2375 for (i=0; i<100; i++ )
2376 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2377 break;
2379 i--;
2380 if (i < 0)
2381 i = 0;
2383 relpos = id3->toc[i];
2385 if (i < 99)
2386 nextpos = id3->toc[i+1];
2387 else
2388 nextpos = 256;
2390 remainder = offset - (relpos * (id3->filesize / 256));
2392 /* set time for this percent (divide before multiply to prevent
2393 overflow on long files. loss of precision is negligible on
2394 short files) */
2395 id3->elapsed = i * (id3->length / 100);
2397 /* calculate remainder time */
2398 plen = (nextpos - relpos) * (id3->filesize / 256);
2399 id3->elapsed += (((remainder * 100) / plen) *
2400 (id3->length / 10000));
2402 else {
2403 /* no TOC exists. set a rough estimate using average bitrate */
2404 int tpk = id3->length /
2405 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2406 1024);
2407 id3->elapsed = offset / 1024 * tpk;
2410 else
2412 /* constant bitrate, use exact calculation */
2413 if (id3->bitrate != 0)
2414 id3->elapsed = offset / (id3->bitrate / 8);
2418 /* Load one track by making the appropriate bufopen calls. Return true if
2419 everything required was loaded correctly, false if not. */
2420 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2422 (void)rebuffer;
2423 char *trackname;
2424 char msgbuf[80];
2425 int fd = -1;
2426 int file_offset = 0;
2427 struct mp3entry id3;
2429 /* Stop buffer filling if there is no free track entries.
2430 Don't fill up the last track entry (we wan't to store next track
2431 metadata there). */
2432 if (!audio_have_free_tracks())
2434 logf("No free tracks");
2435 return false;
2438 last_peek_offset++;
2439 peek_again:
2440 logf("Buffering track:%d/%d", track_widx, track_ridx);
2441 /* Get track name from current playlist read position. */
2442 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2444 /* Handle broken playlists. */
2445 fd = open(trackname, O_RDONLY);
2446 if (fd < 0)
2448 logf("Open failed");
2449 /* Skip invalid entry from playlist. */
2450 playlist_skip_entry(NULL, last_peek_offset);
2452 else
2453 break;
2456 if (!trackname)
2458 logf("End-of-playlist");
2459 playlist_end = true;
2460 return false;
2463 tracks[track_widx].filesize = filesize(fd);
2465 /* Set default values */
2466 if (start_play)
2468 int last_codec = current_codec;
2470 set_current_codec(CODEC_IDX_AUDIO);
2471 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2472 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2473 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2474 dsp_configure(DSP_RESET, 0);
2475 set_current_codec(last_codec);
2477 track_changed = true;
2478 playlist_update_resume_info(audio_current_track());
2481 /* Get track metadata if we don't already have it. */
2482 if (tracks[track_widx].id3_hid <= 0)
2484 if (get_metadata(&id3, fd, trackname))
2486 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2487 TYPE_ID3);
2488 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2490 if (tracks[track_widx].id3_hid <= 0)
2492 DEBUGF("failed to allocate space for metadata\n");
2493 last_peek_offset--;
2494 close(fd);
2495 return false;
2498 if (track_widx == track_ridx)
2499 copy_mp3entry(&curtrack_id3, &id3);
2500 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2501 copy_mp3entry(&nexttrack_id3, &id3);
2503 if (start_play)
2505 track_changed = true;
2506 playlist_update_resume_info(audio_current_track());
2509 else
2511 logf("mde:%s!",trackname);
2513 /* Skip invalid entry from playlist. */
2514 playlist_skip_entry(NULL, last_peek_offset);
2515 tracks[track_widx].taginfo_ready = false;
2516 goto peek_again;
2521 close(fd);
2523 #if 0
2524 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2526 char cuepath[MAX_PATH];
2528 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2530 if (look_for_cuesheet_file(trackname, cuepath) &&
2531 parse_cuesheet(cuepath, cue))
2533 strcpy((cue)->audio_filename, trackname);
2534 if (start_play)
2535 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2538 #endif
2540 /* Load the codec. */
2541 if (!audio_loadcodec(start_play))
2543 if (tracks[track_widx].codecsize)
2545 /* No space for codec on buffer, not an error */
2546 tracks[track_widx].codecsize = 0;
2547 return false;
2550 /* This is an error condition, either no codec was found, or reading
2551 * the codec file failed part way through, either way, skip the track */
2552 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2553 /* We should not use gui_syncplash from audio thread! */
2554 gui_syncsplash(HZ*2, msgbuf);
2555 /* Skip invalid entry from playlist. */
2556 playlist_skip_entry(NULL, last_peek_offset);
2557 tracks[track_widx].taginfo_ready = false;
2558 goto peek_again;
2561 struct mp3entry *track_id3;
2563 if (track_widx == track_ridx)
2564 track_id3 = &curtrack_id3;
2565 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2566 track_id3 = &nexttrack_id3;
2567 else
2568 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2570 set_filebuf_watermark(buffer_margin);
2571 track_id3->elapsed = 0;
2573 if (offset > 0)
2575 switch (track_id3->codectype) {
2576 case AFMT_MPA_L1:
2577 case AFMT_MPA_L2:
2578 case AFMT_MPA_L3:
2579 file_offset = offset;
2580 track_id3->offset = offset;
2581 audio_set_elapsed(track_id3);
2582 ci.curpos = offset;
2583 break;
2585 case AFMT_WAVPACK:
2586 file_offset = offset;
2587 track_id3->offset = offset;
2588 track_id3->elapsed = track_id3->length / 2;
2589 ci.curpos = offset;
2590 break;
2592 case AFMT_OGG_VORBIS:
2593 case AFMT_SPEEX:
2594 case AFMT_FLAC:
2595 case AFMT_PCM_WAV:
2596 case AFMT_A52:
2597 case AFMT_AAC:
2598 case AFMT_MPC:
2599 case AFMT_APE:
2600 track_id3->offset = offset;
2601 break;
2605 logf("alt:%s", trackname);
2607 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, TYPE_AUDIO);
2609 if (tracks[track_widx].audio_hid <= 0)
2610 return false;
2612 if (start_play)
2614 request_buffer_handle(tracks[track_widx].audio_hid);
2617 track_widx++;
2618 track_widx &= MAX_TRACK_MASK;
2620 return true;
2623 /* Send callback events to notify about new tracks. */
2624 static void audio_generate_postbuffer_events(void)
2626 int cur_idx;
2627 int last_idx = -1;
2629 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2631 if (audio_have_tracks())
2633 cur_idx = track_ridx;
2635 while (1) {
2636 if (!tracks[cur_idx].event_sent)
2638 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2640 /* Mark the event 'sent' even if we don't really send one */
2641 tracks[last_idx].event_sent = true;
2642 if (track_buffer_callback && tracks[last_idx].id3_hid > 0)
2643 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2645 last_idx = cur_idx;
2647 if (cur_idx == track_widx)
2648 break;
2649 cur_idx++;
2650 cur_idx &= MAX_TRACK_MASK;
2653 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2655 tracks[last_idx].event_sent = true;
2656 if (track_buffer_callback && tracks[last_idx].id3_hid > 0)
2657 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2662 static bool audio_initialize_buffer_fill(bool clear_tracks)
2664 /* Don't initialize if we're already initialized */
2665 if (filling)
2666 return true;
2668 logf("Starting buffer fill");
2670 /* Set the filling flag true before calling audio_clear_tracks as that
2671 * function can yield and we start looping. */
2672 filling = true;
2674 if (clear_tracks)
2675 audio_clear_track_entries(false);
2677 /* Save the current resume position once. */
2678 playlist_update_resume_info(audio_current_track());
2680 return true;
2683 static void audio_fill_file_buffer(
2684 bool start_play, bool rebuffer, size_t offset)
2686 bool had_next_track = audio_next_track() != NULL;
2687 bool continue_buffering;
2689 /* Must reset the buffer before use if trashed or voice only - voice
2690 file size shouldn't have changed so we can go straight from
2691 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2692 if (buffer_state != BUFFER_STATE_INITIALIZED)
2693 audio_reset_buffer();
2695 if (!audio_initialize_buffer_fill(!start_play))
2696 return ;
2698 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2700 if (!had_next_track && audio_next_track())
2701 track_changed = true;
2703 /* If we're done buffering */
2704 if (!continue_buffering)
2706 //audio_read_next_metadata();
2708 audio_generate_postbuffer_events();
2709 filling = false;
2713 static void audio_rebuffer(void)
2715 logf("Forcing rebuffer");
2717 clear_track_info(CUR_TI);
2719 /* Reset track pointers */
2720 track_widx = track_ridx;
2721 audio_clear_track_entries(true);
2723 /* Just to make sure none were forgotten */
2724 audio_release_tracks();
2726 /* Fill the buffer */
2727 last_peek_offset = -1;
2728 ci.curpos = 0;
2730 if (!CUR_TI->taginfo_ready)
2731 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2733 audio_fill_file_buffer(false, true, 0);
2736 static int audio_check_new_track(void)
2738 DEBUGF("audio_check_new_track\n");
2740 int track_count = audio_track_count();
2741 int old_track_ridx = track_ridx;
2742 bool forward;
2744 if (dir_skip)
2746 dir_skip = false;
2747 if (playlist_next_dir(ci.new_track))
2749 ci.new_track = 0;
2750 audio_rebuffer();
2751 goto skip_done;
2753 else
2755 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2756 return Q_CODEC_REQUEST_FAILED;
2760 if (new_playlist)
2761 ci.new_track = 0;
2763 /* If the playlist isn't that big */
2764 if (!playlist_check(ci.new_track))
2766 if (ci.new_track >= 0)
2768 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2769 return Q_CODEC_REQUEST_FAILED;
2771 /* Find the beginning backward if the user over-skips it */
2772 while (!playlist_check(++ci.new_track))
2773 if (ci.new_track >= 0)
2775 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2776 return Q_CODEC_REQUEST_FAILED;
2779 /* Update the playlist */
2780 last_peek_offset -= ci.new_track;
2782 if (playlist_next(ci.new_track) < 0)
2784 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2785 return Q_CODEC_REQUEST_FAILED;
2788 if (new_playlist)
2790 ci.new_track = 1;
2791 new_playlist = false;
2794 /* Save the old track */
2795 /* prev_ti = CUR_TI; */
2797 #if 0
2798 int i, idx;
2799 for (i = 0; i < ci.new_track; i++)
2801 idx = (track_ridx + i) & MAX_TRACK_MASK;
2802 clear_track_info(&tracks[idx]);
2804 #endif
2806 /* Move to the new track */
2807 track_ridx += ci.new_track;
2808 track_ridx &= MAX_TRACK_MASK;
2810 if (automatic_skip)
2811 playlist_end = false;
2813 track_changed = !automatic_skip;
2815 /* If it is not safe to even skip this many track entries */
2816 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
2818 ci.new_track = 0;
2819 audio_rebuffer();
2820 goto skip_done;
2823 forward = ci.new_track > 0;
2824 ci.new_track = 0;
2826 /* If the target track is clearly not in memory */
2827 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
2829 audio_rebuffer();
2830 goto skip_done;
2833 /* The track may be in memory, see if it really is */
2834 if (!forward)
2836 int cur_idx = track_ridx;
2837 bool taginfo_ready = true;
2838 bool wrap = track_ridx > old_track_ridx;
2840 while (1)
2842 cur_idx++;
2843 cur_idx &= MAX_TRACK_MASK;
2844 if (!(wrap || cur_idx < old_track_ridx))
2845 break;
2847 /* If we hit a track in between without valid tag info, bail */
2848 if (!tracks[cur_idx].taginfo_ready)
2850 taginfo_ready = false;
2851 break;
2854 if (!taginfo_ready)
2856 audio_rebuffer();
2860 skip_done:
2861 audio_update_trackinfo();
2862 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
2863 return Q_CODEC_REQUEST_COMPLETE;
2866 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
2867 bool last_track))
2869 track_buffer_callback = handler;
2872 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
2873 bool last_track))
2875 track_unbuffer_callback = handler;
2878 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
2880 track_changed_callback = handler;
2883 unsigned long audio_prev_elapsed(void)
2885 return prev_track_elapsed;
2888 static void audio_stop_codec_flush(void)
2890 ci.stop_codec = true;
2891 pcmbuf_pause(true);
2893 while (audio_codec_loaded)
2894 yield();
2896 /* If the audio codec is not loaded any more, and the audio is still
2897 * playing, it is now and _only_ now safe to call this function from the
2898 * audio thread */
2899 if (pcm_is_playing())
2900 pcmbuf_play_stop();
2901 pcmbuf_pause(paused);
2904 static void audio_stop_playback(void)
2906 /* If we were playing, save resume information */
2907 if (playing)
2909 struct mp3entry *id3 = NULL;
2911 if (!playlist_end || !ci.stop_codec)
2913 /* Set this early, the outside code yields and may allow the codec
2914 to try to wait for a reply on a buffer wait */
2915 ci.stop_codec = true;
2916 id3 = audio_current_track();
2919 /* Save the current playing spot, or NULL if the playlist has ended */
2920 playlist_update_resume_info(id3);
2922 prev_track_elapsed = curtrack_id3.elapsed;
2924 /* Increment index so runtime info is saved in audio_clear_track_entries().
2925 * Done here, as audio_stop_playback() may be called more than once.
2926 * Don't update runtime unless playback is stopped because of end of playlist.
2927 * Updating runtime when manually stopping a tracks, can destroy autoscores
2928 * and playcounts.
2930 if (playlist_end)
2932 track_ridx++;
2933 track_ridx &= MAX_TRACK_MASK;
2937 filling = false;
2938 paused = false;
2939 audio_stop_codec_flush();
2940 playing = false;
2942 /* Close all tracks */
2943 audio_release_tracks();
2945 /* Mark all entries null. */
2946 audio_clear_track_entries(false);
2948 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2949 memset(&nexttrack_id3, 0, sizeof(struct mp3entry));
2952 static void audio_play_start(size_t offset)
2954 #if INPUT_SRC_CAPS != 0
2955 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2956 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2957 #endif
2959 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2960 paused = false;
2961 audio_stop_codec_flush();
2963 track_changed = true;
2964 playlist_end = false;
2966 playing = true;
2968 ci.new_track = 0;
2969 ci.seek_time = 0;
2970 wps_offset = 0;
2972 sound_set_volume(global_settings.volume);
2973 track_widx = track_ridx = 0;
2975 /* Mark all entries null. */
2976 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
2978 last_peek_offset = -1;
2980 /* Officially playing */
2981 queue_reply(&audio_queue, 1);
2983 audio_fill_file_buffer(true, false, offset);
2985 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
2986 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
2990 /* Invalidates all but currently playing track. */
2991 static void audio_invalidate_tracks(void)
2993 if (audio_have_tracks())
2995 last_peek_offset = 0;
2996 playlist_end = false;
2997 track_widx = track_ridx;
2999 /* Mark all other entries null (also buffered wrong metadata). */
3000 audio_clear_track_entries(true);
3002 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3004 audio_fill_file_buffer(false, true, 0);
3008 static void audio_new_playlist(void)
3010 /* Prepare to start a new fill from the beginning of the playlist */
3011 last_peek_offset = -1;
3012 if (audio_have_tracks())
3014 if (paused)
3015 skipped_during_pause = true;
3016 playlist_end = false;
3017 track_widx = track_ridx;
3018 audio_clear_track_entries(true);
3020 track_widx++;
3021 track_widx &= MAX_TRACK_MASK;
3023 /* Mark the current track as invalid to prevent skipping back to it */
3024 CUR_TI->taginfo_ready = false;
3027 /* Signal the codec to initiate a track change forward */
3028 new_playlist = true;
3029 ci.new_track = 1;
3031 /* Officially playing */
3032 queue_reply(&audio_queue, 1);
3034 audio_fill_file_buffer(false, true, 0);
3037 static void audio_initiate_track_change(long direction)
3039 playlist_end = false;
3040 ci.new_track += direction;
3041 wps_offset -= direction;
3042 if (paused)
3043 skipped_during_pause = true;
3046 static void audio_initiate_dir_change(long direction)
3048 playlist_end = false;
3049 dir_skip = true;
3050 ci.new_track = direction;
3051 if (paused)
3052 skipped_during_pause = true;
3056 * Layout audio buffer as follows - iram buffer depends on target:
3057 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3059 static void audio_reset_buffer(void)
3061 /* see audio_get_recording_buffer if this is modified */
3062 logf("audio_reset_buffer");
3064 /* If the setup of anything allocated before the file buffer is
3065 changed, do check the adjustments after the buffer_alloc call
3066 as it will likely be affected and need sliding over */
3068 /* Initially set up file buffer as all space available */
3069 malloc_buf = audiobuf + talk_get_bufsize();
3070 /* Align the malloc buf to line size. Especially important to cf
3071 targets that do line reads/writes. */
3072 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3073 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3074 filebuflen = audiobufend - filebuf;
3076 /* Allow for codec swap space at end of audio buffer */
3077 if (talk_voice_required())
3079 /* Layout of swap buffer:
3080 * #ifdef IRAM_STEAL (dedicated iram_buf):
3081 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3082 * #else:
3083 * audiobuf...|dram_buf|iram_buf|audiobufend
3085 #ifdef PLAYBACK_VOICE
3086 /* Check for an absolutely nasty situation which should never,
3087 ever happen - frankly should just panic */
3088 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3090 logf("buffer reset with voice swapped");
3092 /* line align length which line aligns the calculations below since
3093 all sizes are also at least line aligned - needed for memswap128 */
3094 filebuflen &= ~15;
3095 #ifdef IRAM_STEAL
3096 filebuflen -= CODEC_SIZE;
3097 #else
3098 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3099 #endif
3100 /* Allocate buffers for swapping voice <=> audio */
3101 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3102 and out of the way of buffer usage or else a call to audio_get_buffer
3103 and subsequent buffer use might trash the swap space. A plugin
3104 initializing IRAM after getting the full buffer would present similar
3105 problem. Options include: failing the request if the other buffer
3106 has been obtained already or never allowing use of the voice IRAM
3107 buffer within the audio buffer. Using buffer_alloc basically
3108 implements the second in a more convenient way. */
3109 dram_buf = filebuf + filebuflen;
3111 #ifdef IRAM_STEAL
3112 /* Allocate voice IRAM swap buffer once */
3113 if (iram_buf == NULL)
3115 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3116 /* buffer_alloc moves audiobuf; this is safe because only the end
3117 * has been touched so far in this function and the address of
3118 * filebuf + filebuflen is not changed */
3119 malloc_buf += CODEC_IRAM_SIZE;
3120 filebuf += CODEC_IRAM_SIZE;
3121 filebuflen -= CODEC_IRAM_SIZE;
3123 #else
3124 /* Allocate iram_buf after dram_buf */
3125 iram_buf = dram_buf + CODEC_SIZE;
3126 #endif /* IRAM_STEAL */
3127 #endif /* PLAYBACK_VOICE */
3129 else
3131 #ifdef PLAYBACK_VOICE
3132 /* No swap buffers needed */
3133 iram_buf = NULL;
3134 dram_buf = NULL;
3135 #endif
3138 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3139 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3141 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3142 will already be line aligned */
3143 filebuflen &= ~3;
3145 /* Set the high watermark as 75% full...or 25% empty :) */
3146 #if MEM > 8
3147 high_watermark = 3*filebuflen / 4;
3148 #endif
3150 /* Clear any references to the file buffer */
3151 buffer_state = BUFFER_STATE_INITIALIZED;
3153 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3154 /* Make sure everything adds up - yes, some info is a bit redundant but
3155 aids viewing and the sumation of certain variables should add up to
3156 the location of others. */
3158 size_t pcmbufsize;
3159 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3160 logf("mabuf: %08X", (unsigned)malloc_buf);
3161 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3162 logf("fbuf: %08X", (unsigned)filebuf);
3163 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3164 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3165 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3166 logf("pcmb: %08X", (unsigned)pcmbuf);
3167 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3168 if (dram_buf)
3170 logf("dramb: %08X", (unsigned)dram_buf);
3171 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3173 if (iram_buf)
3175 logf("iramb: %08X", (unsigned)iram_buf);
3176 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3179 #endif
3182 #if MEM > 8
3183 /* we dont want this rebuffering on targets with little ram
3184 because the disk may never spin down */
3185 static bool ata_fillbuffer_callback(void)
3187 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3188 return true;
3190 #endif
3192 static void audio_thread(void)
3194 struct queue_event ev;
3196 pcm_postinit();
3198 #ifdef PLAYBACK_VOICE
3199 /* Unlock semaphore that init stage locks before creating this thread */
3200 semaphore_release(&sem_codecthread);
3202 /* Buffers must be set up by now - should panic - really */
3203 if (buffer_state != BUFFER_STATE_INITIALIZED)
3205 logf("audio_thread start: no buffer");
3208 /* Have to wait for voice to load up or else the codec swap will be
3209 invalid when an audio codec is loaded */
3210 wait_for_voice_swap_in();
3211 #endif
3213 while (1)
3215 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3217 if (filling)
3219 if (ev.id == SYS_TIMEOUT)
3220 ev.id = Q_AUDIO_FILL_BUFFER;
3222 else
3224 #if MEM > 8
3225 if (playing && (ev.id == SYS_TIMEOUT) && !buffering &&
3226 (bufused() < high_watermark) && (audio_have_free_tracks()))
3227 register_ata_idle_func(ata_fillbuffer_callback);
3228 #endif
3231 switch (ev.id) {
3232 #if MEM > 8
3233 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3234 /* only fill if the disk is still spining */
3235 #ifndef SIMULATOR
3236 if (!ata_disk_is_active())
3237 break;
3238 #endif
3239 #endif /* MEM > 8 */
3240 /* else fall through to Q_AUDIO_FILL_BUFFER */
3241 case Q_AUDIO_FILL_BUFFER:
3242 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3243 if (!filling)
3244 if (!playing || playlist_end || ci.stop_codec)
3245 break;
3246 audio_fill_file_buffer(false, false, 0);
3247 break;
3249 case Q_AUDIO_PLAY:
3250 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3251 if (playing && ev.data <= 0)
3252 audio_new_playlist();
3253 else
3255 audio_stop_playback();
3256 audio_play_start((size_t)ev.data);
3258 break;
3260 case Q_AUDIO_STOP:
3261 LOGFQUEUE("audio < Q_AUDIO_STOP");
3262 if (playing)
3263 audio_stop_playback();
3264 if (ev.data != 0)
3265 queue_clear(&audio_queue);
3266 break;
3268 case Q_AUDIO_PAUSE:
3269 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3270 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3271 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3272 skipped_during_pause = false;
3273 if (!playing)
3274 break;
3275 pcmbuf_pause((bool)ev.data);
3276 paused = (bool)ev.data;
3277 break;
3279 case Q_AUDIO_SKIP:
3280 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3281 audio_initiate_track_change((long)ev.data);
3282 break;
3284 case Q_AUDIO_PRE_FF_REWIND:
3285 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3286 if (!playing)
3287 break;
3288 pcmbuf_pause(true);
3289 break;
3291 case Q_AUDIO_FF_REWIND:
3292 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3293 if (!playing)
3294 break;
3295 ci.seek_time = (long)ev.data+1;
3296 break;
3298 case Q_AUDIO_CHECK_NEW_TRACK:
3299 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3300 queue_reply(&audio_queue, audio_check_new_track());
3301 break;
3303 case Q_AUDIO_DIR_SKIP:
3304 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3305 playlist_end = false;
3306 audio_initiate_dir_change(ev.data);
3307 break;
3309 case Q_AUDIO_FLUSH:
3310 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3311 audio_invalidate_tracks();
3312 break;
3314 case Q_AUDIO_TRACK_CHANGED:
3315 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3316 if (track_changed_callback)
3317 track_changed_callback(&curtrack_id3);
3318 track_changed = true;
3319 playlist_update_resume_info(audio_current_track());
3320 break;
3322 #ifndef SIMULATOR
3323 case SYS_USB_CONNECTED:
3324 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3325 if (playing)
3326 audio_stop_playback();
3327 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3328 usb_wait_for_disconnect(&audio_queue);
3329 break;
3330 #endif
3332 case SYS_TIMEOUT:
3333 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3334 break;
3336 default:
3337 //LOGFQUEUE("audio < default");
3338 break;
3339 } /* end switch */
3340 } /* end while */
3343 #ifdef ROCKBOX_HAS_LOGF
3344 static void audio_test_track_changed_event(struct mp3entry *id3)
3346 (void)id3;
3348 logf("tce:%s", id3->path);
3350 #endif
3352 /* Initialize the audio system - called from init() in main.c.
3353 * Last function because of all the references to internal symbols
3355 void audio_init(void)
3357 #ifdef PLAYBACK_VOICE
3358 static bool voicetagtrue = true;
3359 static struct mp3entry id3_voice;
3360 struct thread_entry *voice_thread_p = NULL;
3361 #endif
3362 struct thread_entry *audio_thread_p;
3364 /* Can never do this twice */
3365 if (audio_is_initialized)
3367 logf("audio: already initialized");
3368 return;
3371 logf("audio: initializing");
3373 /* Initialize queues before giving control elsewhere in case it likes
3374 to send messages. Thread creation will be delayed however so nothing
3375 starts running until ready if something yields such as talk_init. */
3376 #ifdef PLAYBACK_VOICE
3377 /* Take ownership of lock to prevent playback of anything before audio
3378 hardware is initialized - audio thread unlocks it after final init
3379 stage */
3380 semaphore_init(&sem_codecthread, 1, 0);
3381 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3382 #endif
3383 queue_init(&audio_queue, true);
3384 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3385 queue_init(&codec_queue, true);
3386 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3388 pcm_init();
3390 #ifdef ROCKBOX_HAS_LOGF
3391 audio_set_track_changed_event(audio_test_track_changed_event);
3392 #endif
3394 /* Initialize codec api. */
3395 ci.read_filebuf = codec_filebuf_callback;
3396 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3397 ci.get_codec_memory = codec_get_memory_callback;
3398 ci.request_buffer = codec_request_buffer_callback;
3399 ci.advance_buffer = codec_advance_buffer_callback;
3400 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3401 ci.request_next_track = codec_request_next_track_callback;
3402 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3403 ci.seek_buffer = codec_seek_buffer_callback;
3404 ci.seek_complete = codec_seek_complete_callback;
3405 ci.set_elapsed = codec_set_elapsed_callback;
3406 ci.set_offset = codec_set_offset_callback;
3407 ci.configure = codec_configure_callback;
3408 ci.discard_codec = codec_discard_codec_callback;
3410 /* Initialize voice codec api. */
3411 #ifdef PLAYBACK_VOICE
3412 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3413 memset(&id3_voice, 0, sizeof(id3_voice));
3414 ci_voice.read_filebuf = voice_filebuf_callback;
3415 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3416 ci_voice.get_codec_memory = voice_get_memory_callback;
3417 ci_voice.request_buffer = voice_request_buffer_callback;
3418 ci_voice.advance_buffer = voice_advance_buffer_callback;
3419 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3420 ci_voice.request_next_track = voice_request_next_track_callback;
3421 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3422 ci_voice.seek_buffer = voice_seek_buffer_callback;
3423 ci_voice.seek_complete = voice_do_nothing;
3424 ci_voice.set_elapsed = voice_set_elapsed_callback;
3425 ci_voice.set_offset = voice_set_offset_callback;
3426 ci_voice.configure = voice_configure_callback;
3427 ci_voice.discard_codec = voice_do_nothing;
3428 ci_voice.taginfo_ready = &voicetagtrue;
3429 ci_voice.id3 = &id3_voice;
3430 id3_voice.frequency = 11200;
3431 id3_voice.length = 1000000L;
3432 #endif
3434 /* initialize the buffer */
3435 filebuf = audiobuf;
3437 /* audio_reset_buffer must to know the size of voice buffer so init
3438 talk first */
3439 talk_init();
3441 codec_thread_p = create_thread(
3442 codec_thread, codec_stack, sizeof(codec_stack),
3443 CREATE_THREAD_FROZEN,
3444 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3445 IF_COP(, CPU));
3447 audio_thread_p = create_thread(audio_thread, audio_stack,
3448 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3449 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3450 IF_COP(, CPU));
3452 #ifdef PLAYBACK_VOICE
3453 /* TODO: Change this around when various speech codecs can be used */
3454 if (talk_voice_required())
3456 logf("Starting voice codec");
3457 queue_init(&voice_queue, true);
3458 voice_thread_p = create_thread(voice_thread, voice_stack,
3459 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3460 voice_thread_name
3461 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3463 #endif
3465 /* Set crossfade setting for next buffer init which should be about... */
3466 pcmbuf_crossfade_enable(global_settings.crossfade);
3468 /* ...now! Set up the buffers */
3469 audio_reset_buffer();
3471 buffering_init(filebuf, filebuflen);
3473 /* Probably safe to say */
3474 audio_is_initialized = true;
3476 sound_settings_apply();
3477 #ifdef HAVE_WM8758
3478 eq_hw_enable(global_settings.eq_hw_enabled);
3479 #endif
3480 #ifndef HAVE_FLASH_STORAGE
3481 audio_set_buffer_margin(global_settings.buffer_margin);
3482 #endif
3484 /* it's safe to let the threads run now */
3485 thread_thaw(codec_thread_p);
3486 #ifdef PLAYBACK_VOICE
3487 if (voice_thread_p)
3488 thread_thaw(voice_thread_p);
3489 #endif
3490 thread_thaw(audio_thread_p);
3491 } /* audio_init */