Fix the error and warning in buffering.c
[Rockbox.git] / apps / playback.c
blobd256f2eed938ef5f7e2a9d68378f0ce319ffc86f
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 /* default point to start buffer refill */
92 #define AUDIO_DEFAULT_WATERMARK (1024*512)
93 /* amount of data to read in one read() call */
94 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
95 /* point at which the file buffer will fight for CPU time */
96 #define AUDIO_FILEBUF_CRITICAL (1024*128)
97 /* amount of guess-space to allow for codecs that must hunt and peck
98 * for their correct seeek target, 32k seems a good size */
99 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
101 /* Define LOGF_ENABLE to enable logf output in this file */
102 /*#define LOGF_ENABLE*/
103 #include "logf.h"
105 /* macros to enable logf for queues
106 logging on SYS_TIMEOUT can be disabled */
107 #ifdef SIMULATOR
108 /* Define this for logf output of all queuing except SYS_TIMEOUT */
109 #define PLAYBACK_LOGQUEUES
110 /* Define this to logf SYS_TIMEOUT messages */
111 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
112 #endif
114 #ifdef PLAYBACK_LOGQUEUES
115 #define LOGFQUEUE logf
116 #else
117 #define LOGFQUEUE(...)
118 #endif
120 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
121 #define LOGFQUEUE_SYS_TIMEOUT logf
122 #else
123 #define LOGFQUEUE_SYS_TIMEOUT(...)
124 #endif
127 /* Define one constant that includes recording related functionality */
128 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
129 #define AUDIO_HAVE_RECORDING
130 #endif
132 enum {
133 Q_AUDIO_PLAY = 1,
134 Q_AUDIO_STOP,
135 Q_AUDIO_PAUSE,
136 Q_AUDIO_SKIP,
137 Q_AUDIO_PRE_FF_REWIND,
138 Q_AUDIO_FF_REWIND,
139 Q_AUDIO_REBUFFER_SEEK,
140 Q_AUDIO_CHECK_NEW_TRACK,
141 Q_AUDIO_FLUSH,
142 Q_AUDIO_TRACK_CHANGED,
143 Q_AUDIO_DIR_SKIP,
144 Q_AUDIO_POSTINIT,
145 Q_AUDIO_FILL_BUFFER,
146 #if MEM > 8
147 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA,
148 #endif
149 Q_CODEC_REQUEST_COMPLETE,
150 Q_CODEC_REQUEST_FAILED,
152 Q_VOICE_PLAY,
153 Q_VOICE_STOP,
155 Q_CODEC_LOAD,
156 Q_CODEC_LOAD_DISK,
158 #ifdef AUDIO_HAVE_RECORDING
159 Q_ENCODER_LOAD_DISK,
160 Q_ENCODER_RECORD,
161 #endif
164 /* As defined in plugins/lib/xxx2wav.h */
165 #if MEM > 1
166 #define MALLOC_BUFSIZE (512*1024)
167 #define GUARD_BUFSIZE (32*1024)
168 #else
169 #define MALLOC_BUFSIZE (100*1024)
170 #define GUARD_BUFSIZE (8*1024)
171 #endif
173 /* As defined in plugin.lds */
174 #if defined(CPU_PP)
175 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
176 #define CODEC_IRAM_SIZE ((size_t)0xc000)
177 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
178 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
179 #define CODEC_IRAM_SIZE ((size_t)0x10000)
180 #else
181 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
182 #define CODEC_IRAM_SIZE ((size_t)0xc000)
183 #endif
185 #ifndef IBSS_ATTR_VOICE_STACK
186 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
187 #endif
189 bool audio_is_initialized = false;
191 /* Variables are commented with the threads that use them: *
192 * A=audio, C=codec, V=voice. A suffix of - indicates that *
193 * the variable is read but not updated on that thread. */
194 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
196 /* Main state control */
197 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
198 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
199 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
200 static volatile bool filling IDATA_ATTR = false; /* Is file buffer refilling? (A/C-) */
202 /* Ring buffer where compressed audio and codecs are loaded */
203 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
204 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
205 /* FIXME: make filebuflen static */
206 size_t filebuflen = 0; /* Size of buffer (A/C-) */
207 /* FIXME: make buf_ridx (C/A-) */
209 /* Possible arrangements of the buffer */
210 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
211 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
212 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
213 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
215 struct mp3entry curtrack_id3;
216 struct mp3entry nexttrack_id3;
218 /* Track info structure about songs in the file buffer (A/C-) */
219 struct track_info {
220 int audio_hid; /* The ID for the track's buffer handle */
221 int id3_hid; /* The ID for the track's metadata handle */
222 int codec_hid; /* The ID for the track's codec handle */
224 size_t codecsize; /* Codec length in bytes */
225 size_t filesize; /* File total length */
227 bool taginfo_ready; /* Is metadata read */
229 bool event_sent; /* Was this track's buffered event sent */
232 static struct track_info tracks[MAX_TRACK];
233 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
234 static int track_widx = 0; /* Track being buffered (A) */
236 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
237 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
239 /* Set by the audio thread when the current track information has updated
240 * and the WPS may need to update its cached information */
241 static bool track_changed = false;
243 /* Information used only for filling the buffer */
244 /* Playlist steps from playing track to next track to be buffered (A) */
245 static int last_peek_offset = 0;
247 /* Scrobbler support */
248 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
250 /* Track change controls */
251 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
252 static bool playlist_end = false; /* Has the current playlist ended? (A) */
253 static bool dir_skip = false; /* Is a directory skip pending? (A) */
254 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
255 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
256 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
258 /* Callbacks which applications or plugins may set */
259 /* When the playing track has changed from the user's perspective */
260 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
261 /* When a track has been buffered */
262 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
263 /* When a track's buffer has been overwritten or cleared */
264 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
266 /* Configuration */
267 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
268 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
269 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
270 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
271 #if MEM > 8
272 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
273 #endif
275 /* Multiple threads */
276 static void set_current_codec(int codec_idx);
277 /* Set the watermark to trigger buffer fill (A/C) FIXME */
278 static void set_filebuf_watermark(int seconds);
280 /* Audio thread */
281 static struct event_queue audio_queue NOCACHEBSS_ATTR;
282 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
283 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
284 static const char audio_thread_name[] = "audio";
286 static void audio_thread(void);
287 static void audio_initiate_track_change(long direction);
288 static bool audio_have_tracks(void);
289 static void audio_reset_buffer(void);
291 /* Codec thread */
292 extern struct codec_api ci;
293 static struct event_queue codec_queue NOCACHEBSS_ATTR;
294 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
295 IBSS_ATTR;
296 static const char codec_thread_name[] = "codec";
297 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
299 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
301 /* Buffering thread */
302 void buffering_thread(void);
303 static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
304 static const char buffering_thread_name[] = "buffering";
305 struct thread_entry *buffering_thread_p;
307 /* Voice thread */
308 #ifdef PLAYBACK_VOICE
310 extern struct codec_api ci_voice;
312 static struct thread_entry *voice_thread_p = NULL;
313 static struct event_queue voice_queue NOCACHEBSS_ATTR;
314 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
315 IBSS_ATTR_VOICE_STACK;
316 static const char voice_thread_name[] = "voice codec";
318 /* Voice codec swapping control */
319 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
321 #ifdef SIMULATOR
322 /* IRAM codec swap buffer for sim*/
323 static unsigned char sim_iram[CODEC_IRAM_SIZE];
324 #undef CODEC_IRAM_ORIGIN
325 #define CODEC_IRAM_ORIGIN sim_iram
326 #endif
328 /* iram_buf and dram_buf are either both NULL or both non-NULL */
329 /* Pointer to IRAM buffer for codec swapping */
330 static unsigned char *iram_buf = NULL;
331 /* Pointer to DRAM buffer for codec swapping */
332 static unsigned char *dram_buf = NULL;
333 /* Parity of swap_codec calls - needed because one codec swapping itself in
334 automatically swaps in the other and the swap when unlocking should not
335 happen if the parity is even.
337 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
338 /* Locking to control which codec (normal/voice) is running */
339 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
340 static struct event event_codecthread NOCACHEBSS_ATTR;
342 /* Voice state */
343 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
344 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
345 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
346 static unsigned char *voicebuf = NULL;
347 static size_t voice_remaining = 0;
349 #ifdef IRAM_STEAL
350 /* Voice IRAM has been stolen for other use */
351 static bool voice_iram_stolen = false;
352 #endif
354 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
356 struct voice_info {
357 void (*callback)(unsigned char **start, size_t* size);
358 size_t size;
359 unsigned char *buf;
361 static void voice_thread(void);
362 static void voice_stop(void);
364 #endif /* PLAYBACK_VOICE */
367 /* --- Helper functions --- */
369 struct mp3entry *bufgetid3(int handle_id)
371 struct mp3entry *id3;
372 ssize_t ret = bufgetdata(handle_id, 0, (unsigned char **)&id3);
374 if (ret < 0 || ret != sizeof(struct mp3entry))
375 return NULL;
377 return id3;
380 /* --- External interfaces --- */
382 void mp3_play_data(const unsigned char* start, int size,
383 void (*get_more)(unsigned char** start, size_t* size))
385 #ifdef PLAYBACK_VOICE
386 static struct voice_info voice_clip;
387 voice_clip.callback = get_more;
388 voice_clip.buf = (unsigned char*)start;
389 voice_clip.size = size;
390 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
391 queue_post(&voice_queue, Q_VOICE_STOP, 0);
392 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
393 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
394 voice_thread_start = true;
395 trigger_cpu_boost();
396 #else
397 (void) start;
398 (void) size;
399 (void) get_more;
400 #endif
403 void mp3_play_stop(void)
405 #ifdef PLAYBACK_VOICE
406 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
407 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
408 queue_post(&voice_queue, Q_VOICE_STOP, 1);
409 #endif
412 void mp3_play_pause(bool play)
414 /* a dummy */
415 (void)play;
418 bool mp3_is_playing(void)
420 #ifdef PLAYBACK_VOICE
421 return voice_is_playing;
422 #else
423 return false;
424 #endif
427 /* If voice could be swapped out - wait for it to return
428 * Used by buffer claming functions.
430 static void wait_for_voice_swap_in(void)
432 #ifdef PLAYBACK_VOICE
433 if (NULL == iram_buf)
434 return;
436 event_wait(&event_codecthread, STATE_NONSIGNALED);
437 #endif /* PLAYBACK_VOICE */
440 /* This sends a stop message and the audio thread will dump all it's
441 subsequenct messages */
442 static void audio_hard_stop(void)
444 /* Stop playback */
445 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
446 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
449 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
451 unsigned char *buf, *end;
453 if (audio_is_initialized)
455 audio_hard_stop();
456 wait_for_voice_swap_in();
457 #ifdef PLAYBACK_VOICE
458 voice_stop();
459 #endif
461 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
463 if (buffer_size == NULL)
465 /* Special case for talk_init to use since it already knows it's
466 trashed */
467 buffer_state = BUFFER_STATE_TRASHED;
468 return NULL;
471 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
472 || !talk_voice_required())
474 logf("get buffer: talk, audio");
475 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
476 the talk buffer is not needed because voice isn't being used, or
477 could be BUFFER_STATE_TRASHED already. If state is
478 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
479 without the caller knowing what's going on. Changing certain settings
480 may move it to a worse condition but the memory in use by something
481 else will remain undisturbed.
483 if (buffer_state != BUFFER_STATE_TRASHED)
485 talk_buffer_steal();
486 buffer_state = BUFFER_STATE_TRASHED;
489 buf = audiobuf;
490 end = audiobufend;
492 else
494 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
495 still BUFFER_STATE_INITIALIZED */
496 /* Skip talk buffer and move pcm buffer to end to maximize available
497 contiguous memory - no audio running means voice will not need the
498 swap space */
499 logf("get buffer: audio");
500 buf = audiobuf + talk_get_bufsize();
501 end = audiobufend - pcmbuf_init(audiobufend);
502 buffer_state = BUFFER_STATE_VOICED_ONLY;
505 *buffer_size = end - buf;
507 return buf;
510 #ifdef IRAM_STEAL
511 void audio_iram_steal(void)
513 /* We need to stop audio playback in order to use codec IRAM */
514 audio_hard_stop();
516 #ifdef PLAYBACK_VOICE
517 if (NULL != iram_buf)
519 /* Can't already be stolen */
520 if (voice_iram_stolen)
521 return;
523 /* Must wait for voice to be current again if it is swapped which
524 would cause the caller's buffer to get clobbered when voice locks
525 and runs - we'll wait for it to lock and yield again then make sure
526 the ride has come to a complete stop */
527 wait_for_voice_swap_in();
528 voice_stop();
530 /* Save voice IRAM but just memcpy - safe to do here since voice
531 is current and no audio codec is loaded */
532 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
533 voice_iram_stolen = true;
535 else
537 /* Nothing much to do if no voice */
538 voice_iram_stolen = false;
540 #endif
542 #endif /* IRAM_STEAL */
544 #ifdef HAVE_RECORDING
545 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
547 /* Don't allow overwrite of voice swap area or we'll trash the
548 swapped-out voice codec but can use whole thing if none */
549 unsigned char *end;
551 /* Stop audio and voice. Wait for voice to swap in and be clear
552 of pending events to ensure trouble-free operation of encoders */
553 audio_hard_stop();
554 wait_for_voice_swap_in();
555 #ifdef PLAYBACK_VOICE
556 voice_stop();
557 #endif
558 talk_buffer_steal();
560 #ifdef PLAYBACK_VOICE
561 /* If no dram_buf, swap space not used and recording gets more
562 memory. Codec swap areas will remain unaffected by the next init
563 since they're allocated at the end of the buffer and their sizes
564 don't change between calls */
565 end = dram_buf;
566 if (NULL == end)
567 #endif /* PLAYBACK_VOICE */
568 end = audiobufend;
570 buffer_state = BUFFER_STATE_TRASHED;
572 *buffer_size = end - audiobuf;
574 return (unsigned char *)audiobuf;
577 bool audio_load_encoder(int afmt)
579 #ifndef SIMULATOR
580 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
581 if (!enc_fn)
582 return false;
584 audio_remove_encoder();
585 ci.enc_codec_loaded = 0; /* clear any previous error condition */
587 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
588 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
590 while (ci.enc_codec_loaded == 0)
591 yield();
593 logf("codec loaded: %d", ci.enc_codec_loaded);
595 return ci.enc_codec_loaded > 0;
596 #else
597 (void)afmt;
598 return true;
599 #endif
600 } /* audio_load_encoder */
602 void audio_remove_encoder(void)
604 #ifndef SIMULATOR
605 /* force encoder codec unload (if currently loaded) */
606 if (ci.enc_codec_loaded <= 0)
607 return;
609 ci.stop_encoder = true;
610 while (ci.enc_codec_loaded > 0)
611 yield();
612 #endif
613 } /* audio_remove_encoder */
615 #endif /* HAVE_RECORDING */
617 struct mp3entry* audio_current_track(void)
619 const char *filename;
620 const char *p;
621 static struct mp3entry temp_id3;
622 int cur_idx;
623 int offset = ci.new_track + wps_offset;
625 cur_idx = track_ridx + offset;
626 cur_idx &= MAX_TRACK_MASK;
628 if (tracks[cur_idx].id3_hid > 0)
629 return bufgetid3(tracks[cur_idx].id3_hid);
631 memset(&temp_id3, 0, sizeof(struct mp3entry));
633 filename = playlist_peek(0);
634 if (!filename)
635 filename = "No file!";
637 #ifdef HAVE_TC_RAMCACHE
638 if (tagcache_fill_tags(&temp_id3, filename))
639 return &temp_id3;
640 #endif
642 p = strrchr(filename, '/');
643 if (!p)
644 p = filename;
645 else
646 p++;
648 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
649 temp_id3.title = &temp_id3.path[0];
651 return &temp_id3;
654 struct mp3entry* audio_next_track(void)
656 int next_idx = track_ridx;
658 if (!audio_have_tracks())
659 return NULL;
661 next_idx++;
662 next_idx &= MAX_TRACK_MASK;
664 if (tracks[next_idx].id3_hid <= 0)
665 return NULL;
667 return bufgetid3(tracks[next_idx].id3_hid);
670 bool audio_has_changed_track(void)
672 if (track_changed)
674 track_changed = false;
675 return true;
678 return false;
681 void audio_play(long offset)
683 logf("audio_play");
685 #ifdef PLAYBACK_VOICE
686 /* Truncate any existing voice output so we don't have spelling
687 * etc. over the first part of the played track */
688 talk_force_shutup();
689 #endif
691 /* Start playback */
692 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
693 /* Don't return until playback has actually started */
694 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
697 void audio_stop(void)
699 /* Stop playback */
700 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
701 /* Don't return until playback has actually stopped */
702 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
705 void audio_pause(void)
707 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
708 /* Don't return until playback has actually paused */
709 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
712 void audio_resume(void)
714 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
715 /* Don't return until playback has actually resumed */
716 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
719 void audio_next(void)
721 if (playlist_check(ci.new_track + wps_offset + 1))
723 if (global_settings.beep)
724 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
726 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
727 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
728 /* Update wps while our message travels inside deep playback queues. */
729 wps_offset++;
730 track_changed = true;
732 else
734 /* No more tracks. */
735 if (global_settings.beep)
736 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
740 void audio_prev(void)
742 if (playlist_check(ci.new_track + wps_offset - 1))
744 if (global_settings.beep)
745 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
747 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
748 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
749 /* Update wps while our message travels inside deep playback queues. */
750 wps_offset--;
751 track_changed = true;
753 else
755 /* No more tracks. */
756 if (global_settings.beep)
757 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
761 void audio_next_dir(void)
763 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
764 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
767 void audio_prev_dir(void)
769 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
770 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
773 void audio_pre_ff_rewind(void)
775 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
776 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
779 void audio_ff_rewind(long newpos)
781 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
782 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
785 void audio_flush_and_reload_tracks(void)
787 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
788 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
791 void audio_error_clear(void)
793 #ifdef AUDIO_HAVE_RECORDING
794 pcm_rec_error_clear();
795 #endif
798 int audio_status(void)
800 int ret = 0;
802 if (playing)
803 ret |= AUDIO_STATUS_PLAY;
805 if (paused)
806 ret |= AUDIO_STATUS_PAUSE;
808 #ifdef HAVE_RECORDING
809 /* Do this here for constitency with mpeg.c version */
810 ret |= pcm_rec_status();
811 #endif
813 return ret;
816 int audio_get_file_pos(void)
818 return 0;
821 #ifndef HAVE_FLASH_STORAGE
822 void audio_set_buffer_margin(int setting)
824 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
825 buffer_margin = lookup[setting];
826 logf("buffer margin: %ld", buffer_margin);
827 set_filebuf_watermark(buffer_margin);
829 #endif
831 /* Take nescessary steps to enable or disable the crossfade setting */
832 void audio_set_crossfade(int enable)
834 size_t offset;
835 bool was_playing;
836 size_t size;
838 /* Tell it the next setting to use */
839 pcmbuf_crossfade_enable(enable);
841 /* Return if size hasn't changed or this is too early to determine
842 which in the second case there's no way we could be playing
843 anything at all */
844 if (pcmbuf_is_same_size())
846 /* This function is a copout and just syncs some variables -
847 to be removed at a later date */
848 pcmbuf_crossfade_enable_finished();
849 return;
852 offset = 0;
853 was_playing = playing;
855 /* Playback has to be stopped before changing the buffer size */
856 if (was_playing)
858 /* Store the track resume position */
859 offset = curtrack_id3.offset;
860 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
863 /* Blast it - audio buffer will have to be setup again next time
864 something plays */
865 audio_get_buffer(true, &size);
867 /* Restart playback if audio was running previously */
868 if (was_playing)
869 audio_play(offset);
872 /* --- Routines called from multiple threads --- */
873 static void set_current_codec(int codec_idx)
875 current_codec = codec_idx;
876 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
879 #ifdef PLAYBACK_VOICE
880 static void swap_codec(void)
882 int my_codec;
884 /* Swap nothing if no swap buffers exist */
885 if (dram_buf == NULL)
887 logf("swap: no swap buffers");
888 return;
891 my_codec = current_codec;
893 logf("swapping out codec: %d", my_codec);
895 /* Invert this when a codec thread enters and leaves */
896 swap_codec_parity = !swap_codec_parity;
898 /* If this is true, an odd number of calls has occurred and there's
899 no codec thread waiting to swap us out when it locks and runs. This
900 occurs when playback is stopped or when just starting playback and
901 the audio thread is loading a codec; parities should always be even
902 on entry when a thread calls this during playback */
903 if (swap_codec_parity)
905 /* Save our current IRAM and DRAM */
906 #ifdef IRAM_STEAL
907 if (voice_iram_stolen)
909 logf("swap: iram restore");
910 voice_iram_stolen = false;
911 /* Don't swap trashed data into buffer as the voice IRAM will
912 already be swapped out - should _always_ be the case if
913 voice_iram_stolen is true since the voice has been swapped
914 in beforehand */
915 if (my_codec == CODEC_IDX_VOICE)
917 logf("voice iram already swapped");
918 goto skip_iram_swap;
921 #endif
923 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
925 #ifdef IRAM_STEAL
926 skip_iram_swap:
927 #endif
929 memswap128(dram_buf, codecbuf, CODEC_SIZE);
930 /* No cache invalidation needed; it will be done in codec_load_ram
931 or we won't be here otherwise */
934 /* Release my semaphore */
935 semaphore_release(&sem_codecthread);
936 logf("unlocked: %d", my_codec);
938 /* Wait for other codec */
939 event_wait(&event_codecthread,
940 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
942 /* Wait for other codec to unlock */
943 logf("waiting for lock: %d", my_codec);
944 semaphore_wait(&sem_codecthread);
946 /* Take control */
947 set_current_codec(my_codec);
948 event_set_state(&event_codecthread,
949 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
951 /* Reload our IRAM and DRAM */
952 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
953 memswap128(dram_buf, codecbuf, CODEC_SIZE);
954 invalidate_icache();
956 /* Flip parity again */
957 swap_codec_parity = !swap_codec_parity;
959 logf("resuming codec: %d", my_codec);
962 /* This function is meant to be used by the buffer stealing functions to
963 ensure the codec is no longer active and so voice will be swapped-in
964 before it is called */
965 static void voice_stop(void)
967 /* Must have a voice codec loaded or we'll hang forever here */
968 if (!voice_codec_loaded)
969 return;
971 talk_force_shutup();
973 /* Loop until voice empties it's queue, stops and picks up on the new
974 track; the voice thread must be stopped and waiting for messages
975 outside the codec */
976 while (voice_is_playing || !queue_empty(&voice_queue) ||
977 ci_voice.new_track)
978 yield();
980 if (!playing)
981 pcmbuf_play_stop();
982 } /* voice_stop */
984 /* Is voice still speaking */
985 /* Unfortunately only reliable when music is not also playing. */
986 static bool is_voice_speaking(void)
988 return is_voice_queued()
989 || voice_is_playing
990 || (!playing && pcm_is_playing());
993 #endif /* PLAYBACK_VOICE */
995 /* Wait for voice to finish speaking. */
996 /* Also only reliable when music is not also playing. */
997 void voice_wait(void)
999 #ifdef PLAYBACK_VOICE
1000 while (is_voice_speaking())
1001 sleep(HZ/10);
1002 #endif
1005 static void set_filebuf_watermark(int seconds)
1007 size_t bytes;
1009 if (!filebuf)
1010 return; /* Audio buffers not yet set up */
1012 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), conf_watermark);
1013 bytes = MIN(bytes, filebuflen / 2);
1014 conf_watermark = bytes;
1017 const char * get_codec_filename(int cod_spec)
1019 const char *fname;
1021 #ifdef HAVE_RECORDING
1022 /* Can choose decoder or encoder if one available */
1023 int type = cod_spec & CODEC_TYPE_MASK;
1024 int afmt = cod_spec & CODEC_AFMT_MASK;
1026 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1027 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1029 fname = (type == CODEC_TYPE_ENCODER) ?
1030 audio_formats[afmt].codec_enc_root_fn :
1031 audio_formats[afmt].codec_root_fn;
1033 logf("%s: %d - %s",
1034 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1035 afmt, fname ? fname : "<unknown>");
1036 #else /* !HAVE_RECORDING */
1037 /* Always decoder */
1038 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1039 cod_spec = AFMT_UNKNOWN;
1040 fname = audio_formats[cod_spec].codec_root_fn;
1041 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1042 #endif /* HAVE_RECORDING */
1044 return fname;
1045 } /* get_codec_filename */
1048 /* --- Voice thread --- */
1050 #ifdef PLAYBACK_VOICE
1052 static bool voice_pcmbuf_insert_callback(
1053 const void *ch1, const void *ch2, int count)
1055 const char *src[2] = { ch1, ch2 };
1057 while (count > 0)
1059 int out_count = dsp_output_count(count);
1060 int inp_count;
1061 char *dest;
1063 while ((dest = pcmbuf_request_voice_buffer(
1064 &out_count, playing)) == NULL)
1066 if (playing && audio_codec_loaded)
1067 swap_codec();
1068 else
1069 yield();
1072 /* Get the real input_size for output_size bytes, guarding
1073 * against resampling buffer overflows. */
1074 inp_count = dsp_input_count(out_count);
1076 if (inp_count <= 0)
1077 return true;
1079 /* Input size has grown, no error, just don't write more than length */
1080 if (inp_count > count)
1081 inp_count = count;
1083 out_count = dsp_process(dest, src, inp_count);
1085 if (out_count <= 0)
1086 return true;
1088 if (playing)
1090 pcmbuf_mix_voice(out_count);
1091 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1092 audio_codec_loaded)
1093 swap_codec();
1095 else
1096 pcmbuf_write_complete(out_count);
1098 count -= inp_count;
1101 return true;
1102 } /* voice_pcmbuf_insert_callback */
1104 static void* voice_get_memory_callback(size_t *size)
1106 /* Voice should have no use for this. If it did, we'd have to
1107 swap the malloc buffer as well. */
1108 *size = 0;
1109 return NULL;
1112 static void voice_set_elapsed_callback(unsigned int value)
1114 (void)value;
1117 static void voice_set_offset_callback(size_t value)
1119 (void)value;
1122 static void voice_configure_callback(int setting, intptr_t value)
1124 if (!dsp_configure(setting, value))
1126 logf("Illegal key:%d", setting);
1130 static size_t voice_filebuf_callback(void *ptr, size_t size)
1132 (void)ptr;
1133 (void)size;
1135 return 0;
1138 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1139 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1141 if (aborting && !playing)
1143 /* Aborting: Slight hack - flush PCM buffer if
1144 only being used for voice */
1145 pcmbuf_play_stop();
1148 if (voice_is_playing)
1150 /* Clear the current buffer */
1151 voice_is_playing = false;
1152 voice_getmore = NULL;
1153 voice_remaining = 0;
1154 voicebuf = NULL;
1156 /* Cancel any automatic boost if no more clips requested. */
1157 if (!playing || !voice_thread_start)
1158 sleep(0);
1160 /* Force the codec to think it's changing tracks */
1161 ci_voice.new_track = 1;
1163 *realsize = 0;
1164 return true; /* Yes, change tracks */
1167 return false;
1170 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1172 struct queue_event ev;
1174 if (ci_voice.new_track)
1176 *realsize = 0;
1177 return NULL;
1180 while (1)
1182 if (voice_is_playing || playing)
1184 queue_wait_w_tmo(&voice_queue, &ev, 0);
1185 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1186 ev.id = Q_AUDIO_PLAY;
1188 else
1190 queue_wait(&voice_queue, &ev);
1193 switch (ev.id) {
1194 case Q_AUDIO_PLAY:
1195 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1196 if (playing)
1198 if (audio_codec_loaded)
1199 swap_codec();
1200 yield();
1202 break;
1204 #ifdef AUDIO_HAVE_RECORDING
1205 case Q_ENCODER_RECORD:
1206 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1207 swap_codec();
1208 break;
1209 #endif
1211 case Q_VOICE_STOP:
1212 LOGFQUEUE("voice < Q_VOICE_STOP");
1213 if (voice_on_voice_stop(ev.data, realsize))
1214 return NULL;
1215 break;
1217 case SYS_USB_CONNECTED:
1219 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1220 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1221 /* Voice is obviously current so let us swap ourselves away if
1222 playing so audio may stop itself - audio_codec_loaded can
1223 only be true in this case if we're here even if the codec
1224 is only about to load */
1225 if (audio_codec_loaded)
1226 swap_codec();
1227 /* Playback should be finished by now - ack and wait */
1228 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1229 usb_wait_for_disconnect(&voice_queue);
1230 if (change_tracks)
1231 return NULL;
1232 break;
1235 case Q_VOICE_PLAY:
1236 LOGFQUEUE("voice < Q_VOICE_PLAY");
1237 if (!voice_is_playing)
1239 /* Set up new voice data */
1240 struct voice_info *voice_data;
1241 #ifdef IRAM_STEAL
1242 if (voice_iram_stolen)
1244 /* Voice is the first to run again and is currently
1245 loaded */
1246 logf("voice: iram restore");
1247 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1248 voice_iram_stolen = false;
1250 #endif
1251 /* Must reset the buffer before any playback begins if
1252 needed */
1253 if (buffer_state == BUFFER_STATE_TRASHED)
1254 audio_reset_buffer();
1256 voice_is_playing = true;
1257 trigger_cpu_boost();
1258 voice_data = (struct voice_info *)ev.data;
1259 voice_remaining = voice_data->size;
1260 voicebuf = voice_data->buf;
1261 voice_getmore = voice_data->callback;
1263 goto voice_play_clip; /* To exit both switch and while */
1265 case SYS_TIMEOUT:
1266 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1267 goto voice_play_clip;
1269 default:
1270 LOGFQUEUE("voice < default");
1274 voice_play_clip:
1276 if (voice_remaining == 0 || voicebuf == NULL)
1278 if (voice_getmore)
1279 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1281 /* If this clip is done */
1282 if (voice_remaining == 0)
1284 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1285 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1286 /* Force pcm playback. */
1287 if (!pcm_is_playing())
1288 pcmbuf_play_start();
1292 *realsize = MIN(voice_remaining, reqsize);
1294 if (*realsize == 0)
1295 return NULL;
1297 return voicebuf;
1298 } /* voice_request_buffer_callback */
1300 static void voice_advance_buffer_callback(size_t amount)
1302 amount = MIN(amount, voice_remaining);
1303 voicebuf += amount;
1304 voice_remaining -= amount;
1307 static void voice_advance_buffer_loc_callback(void *ptr)
1309 size_t amount = (size_t)ptr - (size_t)voicebuf;
1311 voice_advance_buffer_callback(amount);
1314 static off_t voice_mp3_get_filepos_callback(int newtime)
1316 (void)newtime;
1318 return 0;
1321 static void voice_do_nothing(void)
1323 return;
1326 static bool voice_seek_buffer_callback(size_t newpos)
1328 (void)newpos;
1330 return false;
1333 static bool voice_request_next_track_callback(void)
1335 ci_voice.new_track = 0;
1336 return true;
1339 static void voice_thread(void)
1341 logf("Loading voice codec");
1342 voice_codec_loaded = true;
1343 semaphore_wait(&sem_codecthread);
1344 event_set_state(&event_codecthread, false);
1345 set_current_codec(CODEC_IDX_VOICE);
1346 dsp_configure(DSP_RESET, 0);
1347 voice_remaining = 0;
1348 voice_getmore = NULL;
1350 /* FIXME: If we being starting the voice thread without reboot, the
1351 voice_queue could be full of old stuff and we must flush it. */
1352 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1354 logf("Voice codec finished");
1355 voice_codec_loaded = false;
1356 voice_thread_p = NULL;
1357 semaphore_release(&sem_codecthread);
1358 } /* voice_thread */
1360 #endif /* PLAYBACK_VOICE */
1362 /* --- Codec thread --- */
1363 static bool codec_pcmbuf_insert_callback(
1364 const void *ch1, const void *ch2, int count)
1366 const char *src[2] = { ch1, ch2 };
1368 while (count > 0)
1370 int out_count = dsp_output_count(count);
1371 int inp_count;
1372 char *dest;
1374 /* Prevent audio from a previous track from playing */
1375 if (ci.new_track || ci.stop_codec)
1376 return true;
1378 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1380 sleep(1);
1381 if (ci.seek_time || ci.new_track || ci.stop_codec)
1382 return true;
1385 /* Get the real input_size for output_size bytes, guarding
1386 * against resampling buffer overflows. */
1387 inp_count = dsp_input_count(out_count);
1389 if (inp_count <= 0)
1390 return true;
1392 /* Input size has grown, no error, just don't write more than length */
1393 if (inp_count > count)
1394 inp_count = count;
1396 out_count = dsp_process(dest, src, inp_count);
1398 if (out_count <= 0)
1399 return true;
1401 pcmbuf_write_complete(out_count);
1403 #ifdef PLAYBACK_VOICE
1404 if ((voice_is_playing || voice_thread_start)
1405 && pcm_is_playing() && voice_codec_loaded &&
1406 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1408 voice_thread_start = false;
1409 swap_codec();
1411 #endif
1413 count -= inp_count;
1416 return true;
1417 } /* codec_pcmbuf_insert_callback */
1419 static void* codec_get_memory_callback(size_t *size)
1421 *size = MALLOC_BUFSIZE;
1422 return malloc_buf;
1425 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1426 static void codec_pcmbuf_position_callback(size_t size)
1428 /* This is called from an ISR, so be quick */
1429 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1430 prev_ti->id3.elapsed;
1432 if (time >= prev_ti->id3.length)
1434 pcmbuf_set_position_callback(NULL);
1435 prev_ti->id3.elapsed = prev_ti->id3.length;
1437 else
1438 prev_ti->id3.elapsed = time;
1441 static void codec_set_elapsed_callback(unsigned int value)
1443 unsigned int latency;
1444 if (ci.seek_time)
1445 return;
1447 #ifdef AB_REPEAT_ENABLE
1448 ab_position_report(value);
1449 #endif
1451 latency = pcmbuf_get_latency();
1452 if (value < latency)
1453 curtrack_id3.elapsed = 0;
1454 else if (value - latency > curtrack_id3.elapsed ||
1455 value - latency < curtrack_id3.elapsed - 2)
1457 curtrack_id3.elapsed = value - latency;
1461 static void codec_set_offset_callback(size_t value)
1463 unsigned int latency;
1465 if (ci.seek_time)
1466 return;
1468 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1469 if (value < latency)
1470 curtrack_id3.offset = 0;
1471 else
1472 curtrack_id3.offset = value - latency;
1475 static void codec_advance_buffer_counters(size_t amount)
1477 bufadvance(CUR_TI->audio_hid, amount);
1479 /* Start buffer filling as necessary. */
1480 if (!pcmbuf_is_lowdata() && !filling)
1482 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1484 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1485 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1490 /* copy up-to size bytes into ptr and return the actual size copied */
1491 static size_t codec_filebuf_callback(void *ptr, size_t size)
1493 size_t copy_n;
1495 if (ci.stop_codec || !playing)
1496 return 0;
1498 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1500 /* Nothing requested OR nothing left */
1501 if (copy_n == 0)
1502 return 0;
1504 /* Let the disk buffer catch fill until enough data is available */
1505 while (copy_n == -2)
1507 if (!filling)
1509 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1510 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1513 sleep(1);
1514 if (ci.stop_codec || ci.new_track)
1515 return 0;
1518 /* Update read and other position pointers */
1519 codec_advance_buffer_counters(copy_n);
1521 /* Return the actual amount of data copied to the buffer */
1522 return copy_n;
1523 } /* codec_filebuf_callback */
1525 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1527 size_t short_n, copy_n, buf_rem;
1528 char *ret;
1530 if (!playing)
1532 *realsize = 0;
1533 return NULL;
1536 copy_n = bufgetdata(CUR_TI->audio_hid, reqsize, &ret);
1537 if (copy_n == 0)
1539 *realsize = 0;
1540 return NULL;
1543 while (copy_n == -2)
1545 if (!filling)
1547 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1548 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1551 sleep(1);
1552 if (ci.stop_codec || ci.new_track)
1554 *realsize = 0;
1555 return NULL;
1559 *realsize = copy_n;
1561 return ret;
1562 } /* codec_request_buffer_callback */
1564 static int get_codec_base_type(int type)
1566 switch (type) {
1567 case AFMT_MPA_L1:
1568 case AFMT_MPA_L2:
1569 case AFMT_MPA_L3:
1570 return AFMT_MPA_L3;
1573 return type;
1576 static void codec_advance_buffer_callback(size_t amount)
1578 if (amount > CUR_TI->available + CUR_TI->filerem)
1579 amount = CUR_TI->available + CUR_TI->filerem;
1581 while (amount > CUR_TI->available && filling)
1582 sleep(1);
1584 if (amount > CUR_TI->available)
1586 intptr_t result = Q_CODEC_REQUEST_FAILED;
1588 if (!ci.stop_codec)
1590 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1591 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1592 ci.curpos + amount);
1595 switch (result)
1597 case Q_CODEC_REQUEST_FAILED:
1598 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1599 ci.stop_codec = true;
1600 return;
1602 case Q_CODEC_REQUEST_COMPLETE:
1603 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1604 return;
1606 default:
1607 LOGFQUEUE("codec |< default");
1608 ci.stop_codec = true;
1609 return;
1613 codec_advance_buffer_counters(amount);
1615 codec_set_offset_callback(ci.curpos);
1618 static void codec_advance_buffer_loc_callback(void *ptr)
1620 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1622 codec_advance_buffer_callback(amount);
1625 /* Copied from mpeg.c. Should be moved somewhere else. */
1626 static int codec_get_file_pos(void)
1628 int pos = -1;
1629 struct mp3entry *id3 = audio_current_track();
1631 if (id3->vbr)
1633 if (id3->has_toc)
1635 /* Use the TOC to find the new position */
1636 unsigned int percent, remainder;
1637 int curtoc, nexttoc, plen;
1639 percent = (id3->elapsed*100)/id3->length;
1640 if (percent > 99)
1641 percent = 99;
1643 curtoc = id3->toc[percent];
1645 if (percent < 99)
1646 nexttoc = id3->toc[percent+1];
1647 else
1648 nexttoc = 256;
1650 pos = (id3->filesize/256)*curtoc;
1652 /* Use the remainder to get a more accurate position */
1653 remainder = (id3->elapsed*100)%id3->length;
1654 remainder = (remainder*100)/id3->length;
1655 plen = (nexttoc - curtoc)*(id3->filesize/256);
1656 pos += (plen/100)*remainder;
1658 else
1660 /* No TOC exists, estimate the new position */
1661 pos = (id3->filesize / (id3->length / 1000)) *
1662 (id3->elapsed / 1000);
1665 else if (id3->bitrate)
1666 pos = id3->elapsed * (id3->bitrate / 8);
1667 else
1668 return -1;
1670 pos += id3->first_frame_offset;
1672 /* Don't seek right to the end of the file so that we can
1673 transition properly to the next song */
1674 if (pos >= (int)(id3->filesize - id3->id3v1len))
1675 pos = id3->filesize - id3->id3v1len - 1;
1677 return pos;
1680 static off_t codec_mp3_get_filepos_callback(int newtime)
1682 off_t newpos;
1684 curtrack_id3.elapsed = newtime;
1685 newpos = codec_get_file_pos();
1687 return newpos;
1690 static void codec_seek_complete_callback(void)
1692 logf("seek_complete");
1693 if (pcm_is_paused())
1695 /* If this is not a seamless seek, clear the buffer */
1696 pcmbuf_play_stop();
1697 dsp_configure(DSP_FLUSH, 0);
1699 /* If playback was not 'deliberately' paused, unpause now */
1700 if (!paused)
1701 pcmbuf_pause(false);
1703 ci.seek_time = 0;
1706 static bool codec_seek_buffer_callback(size_t newpos)
1708 int difference;
1710 logf("codec_seek_buffer_callback");
1712 if (newpos >= CUR_TI->filesize)
1713 newpos = CUR_TI->filesize - 1;
1715 difference = newpos - ci.curpos;
1716 if (difference >= 0)
1718 /* Seeking forward */
1719 logf("seek: +%d", difference);
1720 codec_advance_buffer_callback(difference);
1721 return true;
1724 /* Seeking backward */
1725 difference = -difference;
1726 if (ci.curpos - difference < 0)
1727 difference = ci.curpos;
1729 /* We need to reload the song. */
1730 if (newpos < CUR_TI->start_pos)
1732 intptr_t result = Q_CODEC_REQUEST_FAILED;
1734 if (!ci.stop_codec)
1736 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1737 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1738 newpos);
1741 switch (result)
1743 case Q_CODEC_REQUEST_COMPLETE:
1744 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1745 return true;
1747 case Q_CODEC_REQUEST_FAILED:
1748 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1749 ci.stop_codec = true;
1750 return false;
1752 default:
1753 LOGFQUEUE("codec |< default");
1754 return false;
1758 /* Seeking inside buffer space. */
1759 logf("seek: -%d", difference);
1760 CUR_TI->available += difference;
1761 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1762 ci.curpos -= difference;
1764 return true;
1767 static void codec_configure_callback(int setting, intptr_t value)
1769 switch (setting) {
1770 case CODEC_SET_FILEBUF_WATERMARK:
1771 conf_watermark = value;
1772 set_filebuf_watermark(buffer_margin);
1773 break;
1775 case CODEC_SET_FILEBUF_CHUNKSIZE:
1776 conf_filechunk = value;
1777 break;
1779 case CODEC_SET_FILEBUF_PRESEEK:
1780 conf_preseek = value;
1781 break;
1783 default:
1784 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1788 static void codec_track_changed(void)
1790 automatic_skip = false;
1791 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1792 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1795 static void codec_pcmbuf_track_changed_callback(void)
1797 pcmbuf_set_position_callback(NULL);
1798 codec_track_changed();
1801 static void codec_discard_codec_callback(void)
1803 if (CUR_TI->has_codec)
1805 CUR_TI->has_codec = false;
1806 if (CUR_TI->codec_hid > 0)
1808 bufclose(CUR_TI->codec_hid);
1809 CUR_TI->codec_hid = 0;
1813 #if 0
1814 /* Check if a buffer desync has happened, log it and stop playback. */
1815 if (buf_ridx != CUR_TI->buf_idx)
1817 int offset = CUR_TI->buf_idx - buf_ridx;
1818 size_t new_used = FILEBUFUSED - offset;
1820 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1821 logf("Used off:%d",FILEBUFUSED - new_used);
1823 /* This is a fatal internal error and it's not safe to
1824 * continue playback. */
1825 ci.stop_codec = true;
1826 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1828 #endif
1831 static inline void codec_gapless_track_change(void) {
1832 /* callback keeps the progress bar moving while the pcmbuf empties */
1833 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1834 /* set the pcmbuf callback for when the track really changes */
1835 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1838 static inline void codec_crossfade_track_change(void) {
1839 /* Initiate automatic crossfade mode */
1840 pcmbuf_crossfade_init(false);
1841 /* Notify the wps that the track change starts now */
1842 codec_track_changed();
1845 static void codec_track_skip_done(bool was_manual)
1847 int crossfade_mode = global_settings.crossfade;
1849 /* Manual track change (always crossfade or flush audio). */
1850 if (was_manual)
1852 pcmbuf_crossfade_init(true);
1853 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1854 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1856 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1857 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1858 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1860 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1862 if (global_settings.playlist_shuffle)
1863 /* shuffle mode is on, so crossfade: */
1864 codec_crossfade_track_change();
1865 else
1866 /* shuffle mode is off, so do a gapless track change */
1867 codec_gapless_track_change();
1869 else
1870 /* normal crossfade: */
1871 codec_crossfade_track_change();
1873 else
1874 /* normal gapless playback. */
1875 codec_gapless_track_change();
1878 static bool codec_load_next_track(void)
1880 intptr_t result = Q_CODEC_REQUEST_FAILED;
1882 prev_track_elapsed = curtrack_id3.elapsed;
1884 if (ci.seek_time)
1885 codec_seek_complete_callback();
1887 #ifdef AB_REPEAT_ENABLE
1888 ab_end_of_track_report();
1889 #endif
1891 logf("Request new track");
1893 if (ci.new_track == 0)
1895 ci.new_track++;
1896 automatic_skip = true;
1899 if (!ci.stop_codec)
1901 trigger_cpu_boost();
1902 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1903 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1906 switch (result)
1908 case Q_CODEC_REQUEST_COMPLETE:
1909 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1910 codec_track_skip_done(!automatic_skip);
1911 return true;
1913 case Q_CODEC_REQUEST_FAILED:
1914 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1915 ci.new_track = 0;
1916 ci.stop_codec = true;
1917 return false;
1919 default:
1920 LOGFQUEUE("codec |< default");
1921 ci.stop_codec = true;
1922 return false;
1926 static bool codec_request_next_track_callback(void)
1928 int prev_codectype;
1930 if (ci.stop_codec || !playing)
1931 return false;
1933 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1935 if (!codec_load_next_track())
1936 return false;
1938 /* Check if the next codec is the same file. */
1939 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1941 logf("New track loaded");
1942 codec_discard_codec_callback();
1943 return true;
1945 else
1947 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1948 return false;
1952 static void codec_thread(void)
1954 struct queue_event ev;
1955 int status;
1956 size_t wrap;
1958 while (1) {
1959 status = 0;
1960 queue_wait(&codec_queue, &ev);
1962 switch (ev.id) {
1963 case Q_CODEC_LOAD_DISK:
1964 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1965 audio_codec_loaded = true;
1966 #ifdef PLAYBACK_VOICE
1967 /* Don't sent messages to voice codec if it's already swapped
1968 out or it will never get this */
1969 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1971 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1972 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1974 semaphore_wait(&sem_codecthread);
1975 event_set_state(&event_codecthread, true);
1976 #endif
1977 set_current_codec(CODEC_IDX_AUDIO);
1978 ci.stop_codec = false;
1979 status = codec_load_file((const char *)ev.data, &ci);
1980 #ifdef PLAYBACK_VOICE
1981 semaphore_release(&sem_codecthread);
1982 #endif
1983 break;
1985 case Q_CODEC_LOAD:
1986 LOGFQUEUE("codec < Q_CODEC_LOAD");
1987 if (!CUR_TI->has_codec) {
1988 logf("Codec slot is empty!");
1989 /* Wait for the pcm buffer to go empty */
1990 while (pcm_is_playing())
1991 yield();
1992 /* This must be set to prevent an infinite loop */
1993 ci.stop_codec = true;
1994 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1995 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1996 break;
1999 audio_codec_loaded = true;
2000 #ifdef PLAYBACK_VOICE
2001 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2003 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2004 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2006 semaphore_wait(&sem_codecthread);
2007 event_set_state(&event_codecthread, true);
2008 #endif
2009 set_current_codec(CODEC_IDX_AUDIO);
2010 ci.stop_codec = false;
2011 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
2012 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
2013 &filebuf[0], wrap, &ci);
2014 #ifdef PLAYBACK_VOICE
2015 semaphore_release(&sem_codecthread);
2016 #endif
2017 break;
2019 #ifdef AUDIO_HAVE_RECORDING
2020 case Q_ENCODER_LOAD_DISK:
2021 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2022 audio_codec_loaded = false; /* Not audio codec! */
2023 #ifdef PLAYBACK_VOICE
2024 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2026 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2027 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2029 semaphore_wait(&sem_codecthread);
2030 event_set_state(&event_codecthread, true);
2031 #endif
2032 logf("loading encoder");
2033 set_current_codec(CODEC_IDX_AUDIO);
2034 ci.stop_encoder = false;
2035 status = codec_load_file((const char *)ev.data, &ci);
2036 #ifdef PLAYBACK_VOICE
2037 semaphore_release(&sem_codecthread);
2038 #endif
2039 logf("encoder stopped");
2040 break;
2041 #endif /* AUDIO_HAVE_RECORDING */
2043 #ifndef SIMULATOR
2044 case SYS_USB_CONNECTED:
2045 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2046 queue_clear(&codec_queue);
2047 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2048 usb_wait_for_disconnect(&codec_queue);
2049 break;
2050 #endif
2052 default:
2053 LOGFQUEUE("codec < default");
2056 if (audio_codec_loaded)
2058 if (ci.stop_codec)
2060 status = CODEC_OK;
2061 if (!playing)
2062 pcmbuf_play_stop();
2065 audio_codec_loaded = false;
2068 switch (ev.id) {
2069 case Q_CODEC_LOAD_DISK:
2070 case Q_CODEC_LOAD:
2071 LOGFQUEUE("codec < Q_CODEC_LOAD");
2072 if (playing)
2074 if (ci.new_track || status != CODEC_OK)
2076 if (!ci.new_track)
2078 logf("Codec failure");
2079 gui_syncsplash(HZ*2, "Codec failure");
2082 if (!codec_load_next_track())
2084 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2085 /* End of playlist */
2086 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2087 break;
2090 else
2092 logf("Codec finished");
2093 if (ci.stop_codec)
2095 /* Wait for the audio to stop playing before
2096 * triggering the WPS exit */
2097 while(pcm_is_playing())
2099 curtrack_id3.elapsed =
2100 curtrack_id3.length - pcmbuf_get_latency();
2101 sleep(1);
2103 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2104 /* End of playlist */
2105 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2106 break;
2110 if (CUR_TI->has_codec)
2112 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2113 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2115 else
2117 const char *codec_fn =
2118 get_codec_filename(curtrack_id3.codectype);
2119 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2120 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2121 (intptr_t)codec_fn);
2124 break;
2126 #ifdef AUDIO_HAVE_RECORDING
2127 case Q_ENCODER_LOAD_DISK:
2128 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2130 if (status == CODEC_OK)
2131 break;
2133 logf("Encoder failure");
2134 gui_syncsplash(HZ*2, "Encoder failure");
2136 if (ci.enc_codec_loaded < 0)
2137 break;
2139 logf("Encoder failed to load");
2140 ci.enc_codec_loaded = -1;
2141 break;
2142 #endif /* AUDIO_HAVE_RECORDING */
2144 default:
2145 LOGFQUEUE("codec < default");
2147 } /* end switch */
2152 /* --- Audio thread --- */
2154 static bool audio_filebuf_is_lowdata(void)
2156 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
2159 static bool audio_have_tracks(void)
2161 return track_ridx != track_widx || CUR_TI->filesize;
2164 static bool audio_have_free_tracks(void)
2166 if (track_widx < track_ridx)
2167 return track_widx + 1 < track_ridx;
2168 else if (track_ridx == 0)
2169 return track_widx < MAX_TRACK - 1;
2171 return true;
2174 int audio_track_count(void)
2176 if (audio_have_tracks())
2178 int relative_track_widx = track_widx;
2180 if (track_ridx > track_widx)
2181 relative_track_widx += MAX_TRACK;
2183 return relative_track_widx - track_ridx + 1;
2186 return 0;
2189 long audio_filebufused(void)
2191 return (long) FILEBUFUSED;
2194 /* Count the data BETWEEN the selected tracks */
2195 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2197 size_t amount = 0;
2198 bool need_wrap = to_track < from_track;
2200 while (1)
2202 if (++from_track >= MAX_TRACK)
2204 from_track -= MAX_TRACK;
2205 need_wrap = false;
2208 if (from_track >= to_track && !need_wrap)
2209 break;
2211 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2213 return amount;
2216 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2218 size_t amount;
2220 /* Start with the remainder of the previously playing track */
2221 amount = tracks[old_track_ridx].filesize - ci.curpos;
2222 /* Then collect all data from tracks in between them */
2223 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2224 logf("bwf:%ldB", (long) amount);
2226 if (amount > FILEBUFUSED)
2227 return false;
2229 /* Wind the buffer to the beginning of the target track or its codec */
2230 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2232 return true;
2235 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2237 /* Available buffer data */
2238 size_t buf_back;
2239 /* Start with the previously playing track's data and our data */
2240 size_t amount;
2242 amount = ci.curpos;
2243 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2245 /* If we're not just resetting the current track */
2246 if (new_track_ridx != old_track_ridx)
2248 /* Need to wind to before the old track's codec and our filesize */
2249 amount += tracks[old_track_ridx].codecsize;
2250 amount += tracks[new_track_ridx].filesize;
2252 /* Rewind the old track to its beginning */
2253 tracks[old_track_ridx].available =
2254 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2257 /* If the codec was ever buffered */
2258 if (tracks[new_track_ridx].codecsize)
2260 /* Add the codec to the needed size */
2261 amount += tracks[new_track_ridx].codecsize;
2262 tracks[new_track_ridx].has_codec = true;
2265 /* Then collect all data from tracks between new and old */
2266 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2268 /* Do we have space to make this skip? */
2269 if (amount > buf_back)
2270 return false;
2272 logf("bwb:%ldB",amount);
2274 /* Rewind the buffer to the beginning of the target track or its codec */
2275 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2277 /* Reset to the beginning of the new track */
2278 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2280 return true;
2283 static void audio_update_trackinfo(void)
2285 ci.filesize = CUR_TI->filesize;
2286 curtrack_id3.elapsed = 0;
2287 curtrack_id3.offset = 0;
2288 ci.id3 = &curtrack_id3;
2289 ci.curpos = 0;
2290 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2293 /* Yield to codecs for as long as possible if they are in need of data
2294 * return true if the caller should break to let the audio thread process
2295 * new events */
2296 static bool audio_yield_codecs(void)
2298 yield();
2300 if (!queue_empty(&audio_queue))
2301 return true;
2303 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2304 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2306 if (filling)
2307 yield();
2308 else
2309 sleep(2);
2311 if (!queue_empty(&audio_queue))
2312 return true;
2315 return false;
2318 static void audio_clear_track_entries(bool clear_unbuffered)
2320 int cur_idx = track_widx;
2321 int last_idx = -1;
2323 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2325 /* Loop over all tracks from write-to-read */
2326 while (1)
2328 cur_idx++;
2329 cur_idx &= MAX_TRACK_MASK;
2331 if (cur_idx == track_ridx)
2332 break;
2334 /* If the track is buffered, conditionally clear/notify,
2335 * otherwise clear the track if that option is selected */
2336 if (tracks[cur_idx].event_sent)
2338 if (last_idx >= 0)
2340 /* If there is an unbuffer callback, call it, otherwise,
2341 * just clear the track */
2342 if (track_unbuffer_callback)
2343 track_unbuffer_callback(&tracks[last_idx].id3, false);
2345 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2347 last_idx = cur_idx;
2349 else if (clear_unbuffered)
2350 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2353 /* We clear the previous instance of a buffered track throughout
2354 * the above loop to facilitate 'last' detection. Clear/notify
2355 * the last track here */
2356 if (last_idx >= 0)
2358 if (track_unbuffer_callback)
2359 track_unbuffer_callback(&tracks[last_idx].id3, true);
2360 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2364 /* FIXME: This code should be made more generic and move to metadata.c */
2365 static void audio_strip_tags(void)
2367 int i;
2368 static const unsigned char tag[] = "TAG";
2369 static const unsigned char apetag[] = "APETAGEX";
2370 size_t tag_idx;
2371 size_t cur_idx;
2372 size_t len, version;
2374 tag_idx = RINGBUF_SUB(buf_widx, 128);
2376 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2378 cur_idx = tag_idx;
2379 for(i = 0;i < 3;i++)
2381 if(filebuf[cur_idx] != tag[i])
2382 goto strip_ape_tag;
2384 cur_idx = RINGBUF_ADD(cur_idx, 1);
2387 /* Skip id3v1 tag */
2388 logf("Skipping ID3v1 tag");
2389 buf_widx = tag_idx;
2390 tracks[track_widx].available -= 128;
2391 tracks[track_widx].filesize -= 128;
2394 strip_ape_tag:
2395 /* Check for APE tag (look for the APE tag footer) */
2396 tag_idx = RINGBUF_SUB(buf_widx, 32);
2398 if (FILEBUFUSED > 32 && tag_idx > buf_ridx)
2400 cur_idx = tag_idx;
2401 for(i = 0;i < 8;i++)
2403 if(filebuf[cur_idx] != apetag[i])
2404 return;
2406 cur_idx = RINGBUF_ADD(cur_idx, 1);
2409 /* Read the version and length from the footer */
2410 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2411 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2412 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2413 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2414 if (version == 2000)
2415 len += 32; /* APEv2 has a 32 byte header */
2417 /* Skip APE tag */
2418 if (FILEBUFUSED > len)
2420 logf("Skipping APE tag (%ldB)", len);
2421 buf_widx = RINGBUF_SUB(buf_widx, len);
2422 tracks[track_widx].available -= len;
2423 tracks[track_widx].filesize -= len;
2428 /* Returns true if a whole file is read, false otherwise */
2429 static bool audio_read_file(size_t minimum)
2431 bool ret_val = false;
2433 /* If we're called and no file is open, this is an error */
2434 if (current_fd < 0)
2436 logf("Bad fd in arf");
2437 /* Give some hope of miraculous recovery by forcing a track reload */
2438 tracks[track_widx].filesize = 0;
2439 /* Stop this buffering run */
2440 return ret_val;
2443 trigger_cpu_boost();
2444 while (tracks[track_widx].filerem > 0)
2446 size_t copy_n;
2447 int overlap;
2448 int rc;
2450 /* copy_n is the largest chunk that is safe to read */
2451 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2453 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2454 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2455 break;
2457 /* rc is the actual amount read */
2458 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2460 if (rc < 0)
2462 logf("File ended %ldB early", tracks[track_widx].filerem);
2463 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2464 tracks[track_widx].filerem = 0;
2465 break;
2468 /* How much of the playing track did we overwrite */
2469 if (buf_widx == CUR_TI->buf_idx)
2471 /* Special handling; zero or full overlap? */
2472 if (track_widx == track_ridx && CUR_TI->available == 0)
2473 overlap = 0;
2474 else
2475 overlap = rc;
2477 else
2478 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2480 if ((unsigned)rc > tracks[track_widx].filerem)
2482 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2483 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2484 tracks[track_widx].filerem = rc;
2487 /* Advance buffer */
2488 buf_widx = RINGBUF_ADD(buf_widx, rc);
2489 tracks[track_widx].available += rc;
2490 tracks[track_widx].filerem -= rc;
2492 /* If we write into the playing track, adjust it's buffer info */
2493 if (overlap > 0)
2495 CUR_TI->buf_idx += overlap;
2496 CUR_TI->start_pos += overlap;
2499 /* For a rebuffer, fill at least this minimum */
2500 if (minimum > (unsigned)rc)
2501 minimum -= rc;
2502 /* Let the codec process up to the watermark */
2503 /* Break immediately if this is a quick buffer, or there is an event */
2504 else if (minimum || audio_yield_codecs())
2506 /* Exit quickly, but don't stop the overall buffering process */
2507 ret_val = true;
2508 break;
2512 if (tracks[track_widx].filerem == 0)
2514 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2515 close(current_fd);
2516 current_fd = -1;
2517 audio_strip_tags();
2519 track_widx++;
2520 track_widx &= MAX_TRACK_MASK;
2522 tracks[track_widx].filesize = 0;
2523 return true;
2525 else
2527 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2528 tracks[track_widx].filesize - tracks[track_widx].filerem);
2529 return ret_val;
2533 static bool audio_loadcodec(bool start_play)
2535 size_t size = 0;
2536 int fd;
2537 int rc;
2538 size_t copy_n;
2539 int prev_track;
2540 char codec_path[MAX_PATH]; /* Full path to codec */
2542 const char * codec_fn =
2543 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid).codectype);
2544 if (codec_fn == NULL)
2545 return false;
2547 tracks[track_widx].codec_hid = 0;
2549 if (start_play)
2551 /* Load the codec directly from disk and save some memory. */
2552 track_ridx = track_widx;
2553 ci.filesize = CUR_TI->filesize;
2554 ci.id3 = &curtrack_id3;
2555 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2556 ci.curpos = 0;
2557 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2558 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2559 return true;
2561 else
2563 /* If we already have another track than this one buffered */
2564 if (track_widx != track_ridx)
2566 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2568 /* If the previous codec is the same as this one, there is no need
2569 * to put another copy of it on the file buffer */
2570 if (get_codec_base_type(
2571 bufgetid3(tracks[track_widx].id3_hid).codectype) ==
2572 get_codec_base_type(
2573 bufgetid3(tracks[prev_track].id3_hid).codectype)
2574 && audio_codec_loaded)
2576 logf("Reusing prev. codec");
2577 return true;
2582 codec_get_full_path(codec_path, codec_fn);
2584 fd = open(codec_path, O_RDONLY);
2585 if (fd < 0)
2587 logf("Codec doesn't exist!");
2588 return false;
2591 tracks[track_widx].codecsize = filesize(fd);
2593 tracks[track_widx].codec_hid = bufopen(codec_path, TYPE_CODEC);
2594 if (tracks[track_widx].codec_hid < 0)
2596 logf("Not enough space");
2597 close(fd);
2598 return false;
2601 tracks[track_widx].has_codec = true;
2603 close(fd);
2604 logf("Done: %ldB", size);
2606 return true;
2609 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2610 static void audio_set_elapsed(struct mp3entry* id3)
2612 unsigned long offset = id3->offset > id3->first_frame_offset ?
2613 id3->offset - id3->first_frame_offset : 0;
2615 if ( id3->vbr ) {
2616 if ( id3->has_toc ) {
2617 /* calculate elapsed time using TOC */
2618 int i;
2619 unsigned int remainder, plen, relpos, nextpos;
2621 /* find wich percent we're at */
2622 for (i=0; i<100; i++ )
2623 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2624 break;
2626 i--;
2627 if (i < 0)
2628 i = 0;
2630 relpos = id3->toc[i];
2632 if (i < 99)
2633 nextpos = id3->toc[i+1];
2634 else
2635 nextpos = 256;
2637 remainder = offset - (relpos * (id3->filesize / 256));
2639 /* set time for this percent (divide before multiply to prevent
2640 overflow on long files. loss of precision is negligible on
2641 short files) */
2642 id3->elapsed = i * (id3->length / 100);
2644 /* calculate remainder time */
2645 plen = (nextpos - relpos) * (id3->filesize / 256);
2646 id3->elapsed += (((remainder * 100) / plen) *
2647 (id3->length / 10000));
2649 else {
2650 /* no TOC exists. set a rough estimate using average bitrate */
2651 int tpk = id3->length /
2652 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2653 1024);
2654 id3->elapsed = offset / 1024 * tpk;
2657 else
2659 /* constant bitrate, use exact calculation */
2660 if (id3->bitrate != 0)
2661 id3->elapsed = offset / (id3->bitrate / 8);
2665 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2667 char *trackname;
2668 off_t size;
2669 char msgbuf[80];
2670 int fd;
2671 struct mp3entry id3;
2673 /* Stop buffer filling if there is no free track entries.
2674 Don't fill up the last track entry (we wan't to store next track
2675 metadata there). */
2676 if (!audio_have_free_tracks())
2678 logf("No free tracks");
2679 return false;
2682 last_peek_offset++;
2683 peek_again:
2684 logf("Buffering track:%d/%d", track_widx, track_ridx);
2685 /* Get track name from current playlist read position. */
2686 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2688 /* Handle broken playlists. */
2689 fd = open(trackname, O_RDONLY);
2690 if (fd < 0)
2692 logf("Open failed");
2693 /* Skip invalid entry from playlist. */
2694 playlist_skip_entry(NULL, last_peek_offset);
2696 else
2697 break;
2700 if (!trackname)
2702 logf("End-of-playlist");
2703 playlist_end = true;
2704 return false;
2707 /* Initialize track entry. */
2708 size = filesize(fd);
2709 tracks[track_widx].filesize = size;
2711 /* Set default values */
2712 if (start_play)
2714 int last_codec = current_codec;
2716 set_current_codec(CODEC_IDX_AUDIO);
2717 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2718 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2719 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2720 dsp_configure(DSP_RESET, 0);
2721 set_current_codec(last_codec);
2724 /* Get track metadata if we don't already have it. */
2725 if (!tracks[track_widx].taginfo_ready)
2727 if (get_metadata(&id3, fd, trackname))
2729 tracks[track_widx].taginfo_ready = true;
2730 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2731 TYPE_ID3);
2732 if (start_play)
2734 track_changed = true;
2735 playlist_update_resume_info(audio_current_track());
2738 else
2740 logf("mde:%s!",trackname);
2742 /* Skip invalid entry from playlist. */
2743 playlist_skip_entry(NULL, last_peek_offset);
2744 tracks[track_widx].taginfo_ready = false;
2745 goto peek_again;
2750 #if 0
2751 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2753 char cuepath[MAX_PATH];
2755 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2757 if (look_for_cuesheet_file(trackname, cuepath) &&
2758 parse_cuesheet(cuepath, cue))
2760 strcpy((cue)->audio_filename, trackname);
2761 if (start_play)
2762 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2765 #endif
2767 /* Load the codec. */
2768 if (!audio_loadcodec(start_play))
2770 /* Set filesize to zero to indicate no file was loaded. */
2771 tracks[track_widx].filesize = 0;
2772 tracks[track_widx].filerem = 0;
2773 close(current_fd);
2774 current_fd = -1;
2776 if (tracks[track_widx].codecsize)
2778 /* No space for codec on buffer, not an error */
2779 tracks[track_widx].codecsize = 0;
2780 return false;
2783 /* This is an error condition, either no codec was found, or reading
2784 * the codec file failed part way through, either way, skip the track */
2785 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2786 /* We should not use gui_syncplash from audio thread! */
2787 gui_syncsplash(HZ*2, msgbuf);
2788 /* Skip invalid entry from playlist. */
2789 playlist_skip_entry(NULL, last_peek_offset);
2790 tracks[track_widx].taginfo_ready = false;
2791 goto peek_again;
2794 tracks[track_widx].start_pos = 0;
2795 set_filebuf_watermark(buffer_margin);
2796 tracks[track_widx].id3.elapsed = 0;
2798 if (offset > 0)
2800 switch (tracks[track_widx].id3.codectype) {
2801 case AFMT_MPA_L1:
2802 case AFMT_MPA_L2:
2803 case AFMT_MPA_L3:
2804 lseek(current_fd, offset, SEEK_SET);
2805 tracks[track_widx].id3.offset = offset;
2806 audio_set_elapsed(&tracks[track_widx].id3);
2807 tracks[track_widx].filerem = size - offset;
2808 ci.curpos = offset;
2809 tracks[track_widx].start_pos = offset;
2810 break;
2812 case AFMT_WAVPACK:
2813 lseek(current_fd, offset, SEEK_SET);
2814 tracks[track_widx].id3.offset = offset;
2815 tracks[track_widx].id3.elapsed =
2816 tracks[track_widx].id3.length / 2;
2817 tracks[track_widx].filerem = size - offset;
2818 ci.curpos = offset;
2819 tracks[track_widx].start_pos = offset;
2820 break;
2822 case AFMT_OGG_VORBIS:
2823 case AFMT_SPEEX:
2824 case AFMT_FLAC:
2825 case AFMT_PCM_WAV:
2826 case AFMT_A52:
2827 case AFMT_AAC:
2828 case AFMT_MPC:
2829 case AFMT_APE:
2830 tracks[track_widx].id3.offset = offset;
2831 break;
2835 logf("alt:%s", trackname);
2836 tracks[track_widx].buf_idx = buf_widx;
2838 return audio_read_file(rebuffer);
2841 static bool audio_read_next_metadata(void)
2843 int fd;
2844 char *trackname;
2845 int next_idx;
2846 int status;
2848 next_idx = track_widx;
2849 if (tracks[next_idx].taginfo_ready)
2851 next_idx++;
2852 next_idx &= MAX_TRACK_MASK;
2854 if (tracks[next_idx].taginfo_ready)
2855 return true;
2858 trackname = playlist_peek(last_peek_offset + 1);
2859 if (!trackname)
2860 return false;
2862 fd = open(trackname, O_RDONLY);
2863 if (fd < 0)
2864 return false;
2866 status = get_metadata(&(tracks[next_idx].id3),fd,trackname);
2867 /* Preload the glyphs in the tags */
2868 if (status)
2870 tracks[next_idx].taginfo_ready = true;
2871 if (tracks[next_idx].id3.title)
2872 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2873 if (tracks[next_idx].id3.artist)
2874 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2875 if (tracks[next_idx].id3.album)
2876 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2878 close(fd);
2880 return status;
2883 /* Send callback events to notify about new tracks. */
2884 static void audio_generate_postbuffer_events(void)
2886 int cur_idx;
2887 int last_idx = -1;
2889 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2891 if (audio_have_tracks())
2893 cur_idx = track_ridx;
2895 while (1) {
2896 if (!tracks[cur_idx].event_sent)
2898 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2900 /* Mark the event 'sent' even if we don't really send one */
2901 tracks[last_idx].event_sent = true;
2902 if (track_buffer_callback)
2903 track_buffer_callback(&tracks[last_idx].id3, false);
2905 last_idx = cur_idx;
2907 if (cur_idx == track_widx)
2908 break;
2909 cur_idx++;
2910 cur_idx &= MAX_TRACK_MASK;
2913 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2915 tracks[last_idx].event_sent = true;
2916 if (track_buffer_callback)
2917 track_buffer_callback(&tracks[last_idx].id3, true);
2922 static bool audio_initialize_buffer_fill(bool clear_tracks)
2924 /* Don't initialize if we're already initialized */
2925 if (filling)
2926 return true;
2928 logf("Starting buffer fill");
2930 /* Set the filling flag true before calling audio_clear_tracks as that
2931 * function can yield and we start looping. */
2932 filling = true;
2934 if (clear_tracks)
2935 audio_clear_track_entries(false);
2937 /* Save the current resume position once. */
2938 playlist_update_resume_info(audio_current_track());
2940 return true;
2943 static void audio_fill_file_buffer(
2944 bool start_play, bool rebuffer, size_t offset)
2946 bool had_next_track = audio_next_track() != NULL;
2947 bool continue_buffering;
2949 /* Must reset the buffer before use if trashed or voice only - voice
2950 file size shouldn't have changed so we can go straight from
2951 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2952 if (buffer_state != BUFFER_STATE_INITIALIZED)
2953 audio_reset_buffer();
2955 if (!audio_initialize_buffer_fill(!start_play))
2956 return ;
2958 /* If we have a partially buffered track, continue loading,
2959 * otherwise load a new track */
2960 if (tracks[track_widx].filesize > 0)
2961 continue_buffering = audio_read_file(rebuffer);
2962 else
2963 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2965 if (!had_next_track && audio_next_track())
2966 track_changed = true;
2968 /* If we're done buffering */
2969 if (!continue_buffering)
2971 audio_read_next_metadata();
2973 audio_generate_postbuffer_events();
2974 filling = false;
2976 #ifndef SIMULATOR
2977 ata_sleep();
2978 #endif
2982 static void audio_rebuffer(void)
2984 logf("Forcing rebuffer");
2986 /* Stop in progress fill, and clear open file descriptor */
2987 if (current_fd >= 0)
2989 close(current_fd);
2990 current_fd = -1;
2992 filling = false;
2994 /* Reset buffer and track pointers */
2995 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
2996 track_widx = track_ridx;
2997 audio_clear_track_entries(true);
2998 CUR_TI->available = 0;
3000 /* Fill the buffer */
3001 last_peek_offset = -1;
3002 CUR_TI->filesize = 0;
3003 CUR_TI->start_pos = 0;
3004 ci.curpos = 0;
3006 if (!CUR_TI->taginfo_ready)
3007 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3009 audio_fill_file_buffer(false, true, 0);
3012 static int audio_check_new_track(void)
3014 int track_count = audio_track_count();
3015 int old_track_ridx = track_ridx;
3016 bool forward;
3018 if (dir_skip)
3020 dir_skip = false;
3021 if (playlist_next_dir(ci.new_track))
3023 ci.new_track = 0;
3024 CUR_TI->taginfo_ready = false;
3025 audio_rebuffer();
3026 goto skip_done;
3028 else
3030 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3031 return Q_CODEC_REQUEST_FAILED;
3035 if (new_playlist)
3036 ci.new_track = 0;
3038 /* If the playlist isn't that big */
3039 if (!playlist_check(ci.new_track))
3041 if (ci.new_track >= 0)
3043 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3044 return Q_CODEC_REQUEST_FAILED;
3046 /* Find the beginning backward if the user over-skips it */
3047 while (!playlist_check(++ci.new_track))
3048 if (ci.new_track >= 0)
3050 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3051 return Q_CODEC_REQUEST_FAILED;
3054 /* Update the playlist */
3055 last_peek_offset -= ci.new_track;
3057 if (playlist_next(ci.new_track) < 0)
3059 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3060 return Q_CODEC_REQUEST_FAILED;
3063 if (new_playlist)
3065 ci.new_track = 1;
3066 new_playlist = false;
3069 /* Save the old track */
3070 prev_ti = CUR_TI;
3072 /* Move to the new track */
3073 track_ridx += ci.new_track;
3074 track_ridx &= MAX_TRACK_MASK;
3076 if (automatic_skip)
3077 playlist_end = false;
3079 track_changed = !automatic_skip;
3081 /* If it is not safe to even skip this many track entries */
3082 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3084 ci.new_track = 0;
3085 CUR_TI->taginfo_ready = false;
3086 audio_rebuffer();
3087 goto skip_done;
3090 forward = ci.new_track > 0;
3091 ci.new_track = 0;
3093 /* If the target track is clearly not in memory */
3094 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3096 audio_rebuffer();
3097 goto skip_done;
3100 /* The track may be in memory, see if it really is */
3101 if (forward)
3103 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3104 audio_rebuffer();
3106 else
3108 int cur_idx = track_ridx;
3109 bool taginfo_ready = true;
3110 bool wrap = track_ridx > old_track_ridx;
3112 while (1)
3114 cur_idx++;
3115 cur_idx &= MAX_TRACK_MASK;
3116 if (!(wrap || cur_idx < old_track_ridx))
3117 break;
3119 /* If we hit a track in between without valid tag info, bail */
3120 if (!tracks[cur_idx].taginfo_ready)
3122 taginfo_ready = false;
3123 break;
3126 tracks[cur_idx].available = tracks[cur_idx].filesize;
3127 if (tracks[cur_idx].codecsize)
3128 tracks[cur_idx].has_codec = true;
3130 if (taginfo_ready)
3132 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3133 audio_rebuffer();
3135 else
3137 CUR_TI->taginfo_ready = false;
3138 audio_rebuffer();
3142 skip_done:
3143 audio_update_trackinfo();
3144 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3145 return Q_CODEC_REQUEST_COMPLETE;
3148 static int audio_rebuffer_and_seek(size_t newpos)
3150 size_t real_preseek;
3151 int fd;
3152 char *trackname;
3154 /* (Re-)open current track's file handle. */
3155 trackname = playlist_peek(0);
3156 fd = open(trackname, O_RDONLY);
3157 if (fd < 0)
3159 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3160 return Q_CODEC_REQUEST_FAILED;
3163 if (current_fd >= 0)
3164 close(current_fd);
3165 current_fd = fd;
3167 playlist_end = false;
3169 ci.curpos = newpos;
3171 /* Clear codec buffer. */
3172 track_widx = track_ridx;
3173 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3175 last_peek_offset = 0;
3176 filling = false;
3177 audio_initialize_buffer_fill(true);
3179 /* This may have been tweaked by the id3v1 code */
3180 CUR_TI->filesize=filesize(fd);
3181 if (newpos > conf_preseek)
3183 CUR_TI->start_pos = newpos - conf_preseek;
3184 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3185 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3186 real_preseek = conf_preseek;
3188 else
3190 CUR_TI->start_pos = 0;
3191 CUR_TI->filerem = CUR_TI->filesize;
3192 real_preseek = newpos;
3195 CUR_TI->available = 0;
3197 audio_read_file(real_preseek);
3199 /* Account for the data we just read that is 'behind' us now */
3200 CUR_TI->available -= real_preseek;
3202 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3204 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3205 return Q_CODEC_REQUEST_COMPLETE;
3208 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3209 bool last_track))
3211 track_buffer_callback = handler;
3214 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3215 bool last_track))
3217 track_unbuffer_callback = handler;
3220 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3222 track_changed_callback = handler;
3225 unsigned long audio_prev_elapsed(void)
3227 return prev_track_elapsed;
3230 static void audio_stop_codec_flush(void)
3232 ci.stop_codec = true;
3233 pcmbuf_pause(true);
3235 while (audio_codec_loaded)
3236 yield();
3238 /* If the audio codec is not loaded any more, and the audio is still
3239 * playing, it is now and _only_ now safe to call this function from the
3240 * audio thread */
3241 if (pcm_is_playing())
3242 pcmbuf_play_stop();
3243 pcmbuf_pause(paused);
3246 static void audio_stop_playback(void)
3248 /* If we were playing, save resume information */
3249 if (playing)
3251 struct mp3entry *id3 = NULL;
3253 if (!playlist_end || !ci.stop_codec)
3255 /* Set this early, the outside code yields and may allow the codec
3256 to try to wait for a reply on a buffer wait */
3257 ci.stop_codec = true;
3258 id3 = audio_current_track();
3261 /* Save the current playing spot, or NULL if the playlist has ended */
3262 playlist_update_resume_info(id3);
3264 prev_track_elapsed = curtrack_id3.elapsed;
3266 /* Increment index so runtime info is saved in audio_clear_track_entries().
3267 * Done here, as audio_stop_playback() may be called more than once.
3268 * Don't update runtime unless playback is stopped because of end of playlist.
3269 * Updating runtime when manually stopping a tracks, can destroy autoscores
3270 * and playcounts.
3272 if (playlist_end)
3274 track_ridx++;
3275 track_ridx &= MAX_TRACK_MASK;
3279 filling = false;
3280 paused = false;
3281 audio_stop_codec_flush();
3282 playing = false;
3284 if (current_fd >= 0)
3286 close(current_fd);
3287 current_fd = -1;
3290 /* Mark all entries null. */
3291 audio_clear_track_entries(false);
3294 static void audio_play_start(size_t offset)
3296 #if INPUT_SRC_CAPS != 0
3297 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3298 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3299 #endif
3301 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3302 paused = false;
3303 audio_stop_codec_flush();
3305 track_changed = true;
3306 playlist_end = false;
3308 playing = true;
3310 ci.new_track = 0;
3311 ci.seek_time = 0;
3312 wps_offset = 0;
3314 if (current_fd >= 0)
3316 close(current_fd);
3317 current_fd = -1;
3320 sound_set_volume(global_settings.volume);
3321 track_widx = track_ridx = 0;
3323 /* Mark all entries null. */
3324 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3326 last_peek_offset = -1;
3328 /* Officially playing */
3329 queue_reply(&audio_queue, 1);
3331 audio_fill_file_buffer(true, false, offset);
3333 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3334 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3338 /* Invalidates all but currently playing track. */
3339 static void audio_invalidate_tracks(void)
3341 if (audio_have_tracks())
3343 last_peek_offset = 0;
3344 playlist_end = false;
3345 track_widx = track_ridx;
3347 /* Mark all other entries null (also buffered wrong metadata). */
3348 audio_clear_track_entries(true);
3350 /* If the current track is fully buffered, advance the write pointer */
3351 if (tracks[track_widx].filerem == 0)
3352 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3354 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3356 audio_read_next_metadata();
3360 static void audio_new_playlist(void)
3362 /* Prepare to start a new fill from the beginning of the playlist */
3363 last_peek_offset = -1;
3364 if (audio_have_tracks())
3366 if (paused)
3367 skipped_during_pause = true;
3368 playlist_end = false;
3369 track_widx = track_ridx;
3370 audio_clear_track_entries(true);
3372 track_widx++;
3373 track_widx &= MAX_TRACK_MASK;
3375 /* Stop reading the current track */
3376 CUR_TI->filerem = 0;
3377 close(current_fd);
3378 current_fd = -1;
3380 /* Mark the current track as invalid to prevent skipping back to it */
3381 CUR_TI->taginfo_ready = false;
3383 /* Invalidate the buffer other than the playing track */
3384 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3387 /* Signal the codec to initiate a track change forward */
3388 new_playlist = true;
3389 ci.new_track = 1;
3391 /* Officially playing */
3392 queue_reply(&audio_queue, 1);
3394 audio_fill_file_buffer(false, true, 0);
3397 static void audio_initiate_track_change(long direction)
3399 playlist_end = false;
3400 ci.new_track += direction;
3401 wps_offset -= direction;
3402 if (paused)
3403 skipped_during_pause = true;
3406 static void audio_initiate_dir_change(long direction)
3408 playlist_end = false;
3409 dir_skip = true;
3410 ci.new_track = direction;
3411 if (paused)
3412 skipped_during_pause = true;
3416 * Layout audio buffer as follows - iram buffer depends on target:
3417 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3419 static void audio_reset_buffer(void)
3421 /* see audio_get_recording_buffer if this is modified */
3422 logf("audio_reset_buffer");
3424 /* If the setup of anything allocated before the file buffer is
3425 changed, do check the adjustments after the buffer_alloc call
3426 as it will likely be affected and need sliding over */
3428 /* Initially set up file buffer as all space available */
3429 malloc_buf = audiobuf + talk_get_bufsize();
3430 /* Align the malloc buf to line size. Especially important to cf
3431 targets that do line reads/writes. */
3432 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3433 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3434 filebuflen = audiobufend - filebuf;
3436 /* Allow for codec swap space at end of audio buffer */
3437 if (talk_voice_required())
3439 /* Layout of swap buffer:
3440 * #ifdef IRAM_STEAL (dedicated iram_buf):
3441 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3442 * #else:
3443 * audiobuf...|dram_buf|iram_buf|audiobufend
3445 #ifdef PLAYBACK_VOICE
3446 /* Check for an absolutely nasty situation which should never,
3447 ever happen - frankly should just panic */
3448 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3450 logf("buffer reset with voice swapped");
3452 /* line align length which line aligns the calculations below since
3453 all sizes are also at least line aligned - needed for memswap128 */
3454 filebuflen &= ~15;
3455 #ifdef IRAM_STEAL
3456 filebuflen -= CODEC_SIZE;
3457 #else
3458 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3459 #endif
3460 /* Allocate buffers for swapping voice <=> audio */
3461 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3462 and out of the way of buffer usage or else a call to audio_get_buffer
3463 and subsequent buffer use might trash the swap space. A plugin
3464 initializing IRAM after getting the full buffer would present similar
3465 problem. Options include: failing the request if the other buffer
3466 has been obtained already or never allowing use of the voice IRAM
3467 buffer within the audio buffer. Using buffer_alloc basically
3468 implements the second in a more convenient way. */
3469 dram_buf = filebuf + filebuflen;
3471 #ifdef IRAM_STEAL
3472 /* Allocate voice IRAM swap buffer once */
3473 if (iram_buf == NULL)
3475 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3476 /* buffer_alloc moves audiobuf; this is safe because only the end
3477 * has been touched so far in this function and the address of
3478 * filebuf + filebuflen is not changed */
3479 malloc_buf += CODEC_IRAM_SIZE;
3480 filebuf += CODEC_IRAM_SIZE;
3481 filebuflen -= CODEC_IRAM_SIZE;
3483 #else
3484 /* Allocate iram_buf after dram_buf */
3485 iram_buf = dram_buf + CODEC_SIZE;
3486 #endif /* IRAM_STEAL */
3487 #endif /* PLAYBACK_VOICE */
3489 else
3491 #ifdef PLAYBACK_VOICE
3492 /* No swap buffers needed */
3493 iram_buf = NULL;
3494 dram_buf = NULL;
3495 #endif
3498 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3499 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3501 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3502 will already be line aligned */
3503 filebuflen &= ~3;
3505 /* Set the high watermark as 75% full...or 25% empty :) */
3506 #if MEM > 8
3507 high_watermark = 3*filebuflen / 4;
3508 #endif
3510 /* Clear any references to the file buffer */
3511 buffer_state = BUFFER_STATE_INITIALIZED;
3513 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3514 /* Make sure everything adds up - yes, some info is a bit redundant but
3515 aids viewing and the sumation of certain variables should add up to
3516 the location of others. */
3518 size_t pcmbufsize;
3519 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3520 logf("mabuf: %08X", (unsigned)malloc_buf);
3521 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3522 logf("fbuf: %08X", (unsigned)filebuf);
3523 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3524 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3525 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3526 logf("pcmb: %08X", (unsigned)pcmbuf);
3527 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3528 if (dram_buf)
3530 logf("dramb: %08X", (unsigned)dram_buf);
3531 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3533 if (iram_buf)
3535 logf("iramb: %08X", (unsigned)iram_buf);
3536 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3539 #endif
3542 #if MEM > 8
3543 /* we dont want this rebuffering on targets with little ram
3544 because the disk may never spin down */
3545 static bool ata_fillbuffer_callback(void)
3547 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3548 return true;
3550 #endif
3552 static void audio_thread(void)
3554 struct queue_event ev;
3556 pcm_postinit();
3558 #ifdef PLAYBACK_VOICE
3559 /* Unlock semaphore that init stage locks before creating this thread */
3560 semaphore_release(&sem_codecthread);
3562 /* Buffers must be set up by now - should panic - really */
3563 if (buffer_state != BUFFER_STATE_INITIALIZED)
3565 logf("audio_thread start: no buffer");
3568 /* Have to wait for voice to load up or else the codec swap will be
3569 invalid when an audio codec is loaded */
3570 wait_for_voice_swap_in();
3571 #endif
3573 while (1)
3575 if (filling)
3577 queue_wait_w_tmo(&audio_queue, &ev, 0);
3578 if (ev.id == SYS_TIMEOUT)
3579 ev.id = Q_AUDIO_FILL_BUFFER;
3581 else
3583 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3584 #if MEM > 8
3585 if (playing && (ev.id == SYS_TIMEOUT) &&
3586 (FILEBUFUSED < high_watermark))
3587 register_ata_idle_func(ata_fillbuffer_callback);
3588 #endif
3591 switch (ev.id) {
3592 #if MEM > 8
3593 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3594 /* only fill if the disk is still spining */
3595 #ifndef SIMULATOR
3596 if (!ata_disk_is_active())
3597 break;
3598 #endif
3599 #endif /* MEM > 8 */
3600 /* else fall through to Q_AUDIO_FILL_BUFFER */
3601 case Q_AUDIO_FILL_BUFFER:
3602 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3603 if (!filling)
3604 if (!playing || playlist_end || ci.stop_codec)
3605 break;
3606 audio_fill_file_buffer(false, false, 0);
3607 break;
3609 case Q_AUDIO_PLAY:
3610 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3611 if (playing && ev.data <= 0)
3612 audio_new_playlist();
3613 else
3615 audio_stop_playback();
3616 audio_play_start((size_t)ev.data);
3618 break;
3620 case Q_AUDIO_STOP:
3621 LOGFQUEUE("audio < Q_AUDIO_STOP");
3622 if (playing)
3623 audio_stop_playback();
3624 if (ev.data != 0)
3625 queue_clear(&audio_queue);
3626 break;
3628 case Q_AUDIO_PAUSE:
3629 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3630 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3631 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3632 skipped_during_pause = false;
3633 if (!playing)
3634 break;
3635 pcmbuf_pause((bool)ev.data);
3636 paused = (bool)ev.data;
3637 break;
3639 case Q_AUDIO_SKIP:
3640 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3641 audio_initiate_track_change((long)ev.data);
3642 break;
3644 case Q_AUDIO_PRE_FF_REWIND:
3645 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3646 if (!playing)
3647 break;
3648 pcmbuf_pause(true);
3649 break;
3651 case Q_AUDIO_FF_REWIND:
3652 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3653 if (!playing)
3654 break;
3655 ci.seek_time = (long)ev.data+1;
3656 break;
3658 case Q_AUDIO_REBUFFER_SEEK:
3659 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3660 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3661 break;
3663 case Q_AUDIO_CHECK_NEW_TRACK:
3664 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3665 queue_reply(&audio_queue, audio_check_new_track());
3666 break;
3668 case Q_AUDIO_DIR_SKIP:
3669 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3670 playlist_end = false;
3671 audio_initiate_dir_change(ev.data);
3672 break;
3674 case Q_AUDIO_FLUSH:
3675 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3676 audio_invalidate_tracks();
3677 break;
3679 case Q_AUDIO_TRACK_CHANGED:
3680 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3681 if (track_changed_callback)
3682 track_changed_callback(&curtrack_id3);
3683 track_changed = true;
3684 playlist_update_resume_info(audio_current_track());
3685 break;
3687 #ifndef SIMULATOR
3688 case SYS_USB_CONNECTED:
3689 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3690 if (playing)
3691 audio_stop_playback();
3692 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3693 usb_wait_for_disconnect(&audio_queue);
3694 break;
3695 #endif
3697 case SYS_TIMEOUT:
3698 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3699 break;
3701 default:
3702 LOGFQUEUE("audio < default");
3703 } /* end switch */
3704 } /* end while */
3707 #ifdef ROCKBOX_HAS_LOGF
3708 static void audio_test_track_changed_event(struct mp3entry *id3)
3710 (void)id3;
3712 logf("tce:%s", id3->path);
3714 #endif
3716 /* Initialize the audio system - called from init() in main.c.
3717 * Last function because of all the references to internal symbols
3719 void audio_init(void)
3721 #ifdef PLAYBACK_VOICE
3722 static bool voicetagtrue = true;
3723 static struct mp3entry id3_voice;
3724 struct thread_entry *voice_thread_p = NULL;
3725 #endif
3726 struct thread_entry *audio_thread_p;
3728 /* Can never do this twice */
3729 if (audio_is_initialized)
3731 logf("audio: already initialized");
3732 return;
3735 logf("audio: initializing");
3737 /* Initialize queues before giving control elsewhere in case it likes
3738 to send messages. Thread creation will be delayed however so nothing
3739 starts running until ready if something yields such as talk_init. */
3740 #ifdef PLAYBACK_VOICE
3741 /* Take ownership of lock to prevent playback of anything before audio
3742 hardware is initialized - audio thread unlocks it after final init
3743 stage */
3744 semaphore_init(&sem_codecthread, 1, 0);
3745 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3746 #endif
3747 queue_init(&audio_queue, true);
3748 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3749 queue_init(&codec_queue, true);
3751 pcm_init();
3753 #ifdef ROCKBOX_HAS_LOGF
3754 audio_set_track_changed_event(audio_test_track_changed_event);
3755 #endif
3757 /* Initialize codec api. */
3758 ci.read_filebuf = codec_filebuf_callback;
3759 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3760 ci.get_codec_memory = codec_get_memory_callback;
3761 ci.request_buffer = codec_request_buffer_callback;
3762 ci.advance_buffer = codec_advance_buffer_callback;
3763 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3764 ci.request_next_track = codec_request_next_track_callback;
3765 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3766 ci.seek_buffer = codec_seek_buffer_callback;
3767 ci.seek_complete = codec_seek_complete_callback;
3768 ci.set_elapsed = codec_set_elapsed_callback;
3769 ci.set_offset = codec_set_offset_callback;
3770 ci.configure = codec_configure_callback;
3771 ci.discard_codec = codec_discard_codec_callback;
3773 /* Initialize voice codec api. */
3774 #ifdef PLAYBACK_VOICE
3775 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3776 memset(&id3_voice, 0, sizeof(id3_voice));
3777 ci_voice.read_filebuf = voice_filebuf_callback;
3778 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3779 ci_voice.get_codec_memory = voice_get_memory_callback;
3780 ci_voice.request_buffer = voice_request_buffer_callback;
3781 ci_voice.advance_buffer = voice_advance_buffer_callback;
3782 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3783 ci_voice.request_next_track = voice_request_next_track_callback;
3784 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3785 ci_voice.seek_buffer = voice_seek_buffer_callback;
3786 ci_voice.seek_complete = voice_do_nothing;
3787 ci_voice.set_elapsed = voice_set_elapsed_callback;
3788 ci_voice.set_offset = voice_set_offset_callback;
3789 ci_voice.configure = voice_configure_callback;
3790 ci_voice.discard_codec = voice_do_nothing;
3791 ci_voice.taginfo_ready = &voicetagtrue;
3792 ci_voice.id3 = &id3_voice;
3793 id3_voice.frequency = 11200;
3794 id3_voice.length = 1000000L;
3795 #endif
3797 /* initialize the buffer */
3798 filebuf = audiobuf;
3800 /* audio_reset_buffer must to know the size of voice buffer so init
3801 talk first */
3802 talk_init();
3804 codec_thread_p = create_thread(
3805 codec_thread, codec_stack, sizeof(codec_stack),
3806 CREATE_THREAD_FROZEN,
3807 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3808 IF_COP(, CPU));
3810 audio_thread_p = create_thread(audio_thread, audio_stack,
3811 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3812 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3813 IF_COP(, CPU));
3815 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
3816 sizeof(buffering_stack), CREATE_THREAD_FROZEN,
3817 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3818 IF_COP(, CPU, true));
3820 #ifdef PLAYBACK_VOICE
3821 /* TODO: Change this around when various speech codecs can be used */
3822 if (talk_voice_required())
3824 logf("Starting voice codec");
3825 queue_init(&voice_queue, true);
3826 voice_thread_p = create_thread(voice_thread, voice_stack,
3827 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3828 voice_thread_name
3829 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3831 #endif
3833 /* Set crossfade setting for next buffer init which should be about... */
3834 pcmbuf_crossfade_enable(global_settings.crossfade);
3836 /* ...now! Set up the buffers */
3837 audio_reset_buffer();
3839 buffering_init(filebuf, filebuflen);
3841 /* Probably safe to say */
3842 audio_is_initialized = true;
3844 sound_settings_apply();
3845 #ifdef HAVE_WM8758
3846 eq_hw_enable(global_settings.eq_hw_enabled);
3847 #endif
3848 #ifndef HAVE_FLASH_STORAGE
3849 audio_set_buffer_margin(global_settings.buffer_margin);
3850 #endif
3852 /* it's safe to let the threads run now */
3853 thread_thaw(codec_thread_p);
3854 #ifdef PLAYBACK_VOICE
3855 if (voice_thread_p)
3856 thread_thaw(voice_thread_p);
3857 #endif
3858 thread_thaw(audio_thread_p);
3859 thread_thaw(buffering_thread_p);
3860 } /* audio_init */