Add a get_offset API call to make codec_advance_buffer_loc_callback work.
[Rockbox.git] / apps / playback.c
blob859425fd70a30362912a90a99924c2bc7931d364
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 #if 0
237 static struct track_info *prev_ti = NULL; /* Previous track info pointer (A/C-) */
238 #endif
240 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
242 /* Set by the audio thread when the current track information has updated
243 * and the WPS may need to update its cached information */
244 static bool track_changed = false;
246 /* Information used only for filling the buffer */
247 /* Playlist steps from playing track to next track to be buffered (A) */
248 static int last_peek_offset = 0;
250 /* Scrobbler support */
251 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
253 /* Track change controls */
254 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
255 static bool playlist_end = false; /* Has the current playlist ended? (A) */
256 static bool dir_skip = false; /* Is a directory skip pending? (A) */
257 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
258 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
259 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
261 /* Callbacks which applications or plugins may set */
262 /* When the playing track has changed from the user's perspective */
263 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
264 /* When a track has been buffered */
265 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
266 /* When a track's buffer has been overwritten or cleared */
267 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
269 /* Configuration */
270 static size_t conf_watermark = 0; /* Level to trigger filebuf fill (A/C) FIXME */
271 static size_t conf_filechunk = 0; /* Largest chunk the codec accepts (A/C) FIXME */
272 static size_t conf_preseek = 0; /* Codec pre-seek margin (A/C) FIXME */
273 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
274 #if MEM > 8
275 static size_t high_watermark = 0; /* High watermark for rebuffer (A/V/other) */
276 #endif
278 /* Multiple threads */
279 static void set_current_codec(int codec_idx);
280 /* Set the watermark to trigger buffer fill (A/C) FIXME */
281 static void set_filebuf_watermark(int seconds);
283 /* Audio thread */
284 static struct event_queue audio_queue NOCACHEBSS_ATTR;
285 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
286 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
287 static const char audio_thread_name[] = "audio";
289 static void audio_thread(void);
290 static void audio_initiate_track_change(long direction);
291 static bool audio_have_tracks(void);
292 static void audio_reset_buffer(void);
294 /* Codec thread */
295 extern struct codec_api ci;
296 static struct event_queue codec_queue NOCACHEBSS_ATTR;
297 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
298 IBSS_ATTR;
299 static const char codec_thread_name[] = "codec";
300 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
302 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
304 /* Buffering thread */
305 void buffering_thread(void);
306 static long buffering_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)];
307 static const char buffering_thread_name[] = "buffering";
308 struct thread_entry *buffering_thread_p;
310 /* Voice thread */
311 #ifdef PLAYBACK_VOICE
313 extern struct codec_api ci_voice;
315 static struct thread_entry *voice_thread_p = NULL;
316 static struct event_queue voice_queue NOCACHEBSS_ATTR;
317 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
318 IBSS_ATTR_VOICE_STACK;
319 static const char voice_thread_name[] = "voice codec";
321 /* Voice codec swapping control */
322 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
324 #ifdef SIMULATOR
325 /* IRAM codec swap buffer for sim*/
326 static unsigned char sim_iram[CODEC_IRAM_SIZE];
327 #undef CODEC_IRAM_ORIGIN
328 #define CODEC_IRAM_ORIGIN sim_iram
329 #endif
331 /* iram_buf and dram_buf are either both NULL or both non-NULL */
332 /* Pointer to IRAM buffer for codec swapping */
333 static unsigned char *iram_buf = NULL;
334 /* Pointer to DRAM buffer for codec swapping */
335 static unsigned char *dram_buf = NULL;
336 /* Parity of swap_codec calls - needed because one codec swapping itself in
337 automatically swaps in the other and the swap when unlocking should not
338 happen if the parity is even.
340 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
341 /* Locking to control which codec (normal/voice) is running */
342 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
343 static struct event event_codecthread NOCACHEBSS_ATTR;
345 /* Voice state */
346 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
347 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
348 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
349 static unsigned char *voicebuf = NULL;
350 static size_t voice_remaining = 0;
352 #ifdef IRAM_STEAL
353 /* Voice IRAM has been stolen for other use */
354 static bool voice_iram_stolen = false;
355 #endif
357 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
359 struct voice_info {
360 void (*callback)(unsigned char **start, size_t* size);
361 size_t size;
362 unsigned char *buf;
364 static void voice_thread(void);
365 static void voice_stop(void);
367 #endif /* PLAYBACK_VOICE */
370 /* --- Helper functions --- */
372 struct mp3entry *bufgetid3(int handle_id)
374 struct mp3entry *id3;
375 ssize_t ret = bufgetdata(handle_id, 0, (unsigned char **)&id3);
377 if (ret < 0 || ret != sizeof(struct mp3entry))
378 return NULL;
380 return id3;
383 unsigned char *getptr(int handle_id)
385 unsigned char *ptr;
386 ssize_t ret = bufgetdata(handle_id, 0, &ptr);
388 if (ret < 0)
389 return 0;
391 return ptr;
394 /* --- External interfaces --- */
396 void mp3_play_data(const unsigned char* start, int size,
397 void (*get_more)(unsigned char** start, size_t* size))
399 #ifdef PLAYBACK_VOICE
400 static struct voice_info voice_clip;
401 voice_clip.callback = get_more;
402 voice_clip.buf = (unsigned char*)start;
403 voice_clip.size = size;
404 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
405 queue_post(&voice_queue, Q_VOICE_STOP, 0);
406 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
407 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
408 voice_thread_start = true;
409 trigger_cpu_boost();
410 #else
411 (void) start;
412 (void) size;
413 (void) get_more;
414 #endif
417 void mp3_play_stop(void)
419 #ifdef PLAYBACK_VOICE
420 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
421 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
422 queue_post(&voice_queue, Q_VOICE_STOP, 1);
423 #endif
426 void mp3_play_pause(bool play)
428 /* a dummy */
429 (void)play;
432 bool mp3_is_playing(void)
434 #ifdef PLAYBACK_VOICE
435 return voice_is_playing;
436 #else
437 return false;
438 #endif
441 /* If voice could be swapped out - wait for it to return
442 * Used by buffer claming functions.
444 static void wait_for_voice_swap_in(void)
446 #ifdef PLAYBACK_VOICE
447 if (NULL == iram_buf)
448 return;
450 event_wait(&event_codecthread, STATE_NONSIGNALED);
451 #endif /* PLAYBACK_VOICE */
454 /* This sends a stop message and the audio thread will dump all it's
455 subsequenct messages */
456 static void audio_hard_stop(void)
458 /* Stop playback */
459 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
460 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
463 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
465 unsigned char *buf, *end;
467 if (audio_is_initialized)
469 audio_hard_stop();
470 wait_for_voice_swap_in();
471 #ifdef PLAYBACK_VOICE
472 voice_stop();
473 #endif
475 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
477 if (buffer_size == NULL)
479 /* Special case for talk_init to use since it already knows it's
480 trashed */
481 buffer_state = BUFFER_STATE_TRASHED;
482 return NULL;
485 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
486 || !talk_voice_required())
488 logf("get buffer: talk, audio");
489 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
490 the talk buffer is not needed because voice isn't being used, or
491 could be BUFFER_STATE_TRASHED already. If state is
492 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
493 without the caller knowing what's going on. Changing certain settings
494 may move it to a worse condition but the memory in use by something
495 else will remain undisturbed.
497 if (buffer_state != BUFFER_STATE_TRASHED)
499 talk_buffer_steal();
500 buffer_state = BUFFER_STATE_TRASHED;
503 buf = audiobuf;
504 end = audiobufend;
506 else
508 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
509 still BUFFER_STATE_INITIALIZED */
510 /* Skip talk buffer and move pcm buffer to end to maximize available
511 contiguous memory - no audio running means voice will not need the
512 swap space */
513 logf("get buffer: audio");
514 buf = audiobuf + talk_get_bufsize();
515 end = audiobufend - pcmbuf_init(audiobufend);
516 buffer_state = BUFFER_STATE_VOICED_ONLY;
519 *buffer_size = end - buf;
521 return buf;
524 #ifdef IRAM_STEAL
525 void audio_iram_steal(void)
527 /* We need to stop audio playback in order to use codec IRAM */
528 audio_hard_stop();
530 #ifdef PLAYBACK_VOICE
531 if (NULL != iram_buf)
533 /* Can't already be stolen */
534 if (voice_iram_stolen)
535 return;
537 /* Must wait for voice to be current again if it is swapped which
538 would cause the caller's buffer to get clobbered when voice locks
539 and runs - we'll wait for it to lock and yield again then make sure
540 the ride has come to a complete stop */
541 wait_for_voice_swap_in();
542 voice_stop();
544 /* Save voice IRAM but just memcpy - safe to do here since voice
545 is current and no audio codec is loaded */
546 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
547 voice_iram_stolen = true;
549 else
551 /* Nothing much to do if no voice */
552 voice_iram_stolen = false;
554 #endif
556 #endif /* IRAM_STEAL */
558 #ifdef HAVE_RECORDING
559 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
561 /* Don't allow overwrite of voice swap area or we'll trash the
562 swapped-out voice codec but can use whole thing if none */
563 unsigned char *end;
565 /* Stop audio and voice. Wait for voice to swap in and be clear
566 of pending events to ensure trouble-free operation of encoders */
567 audio_hard_stop();
568 wait_for_voice_swap_in();
569 #ifdef PLAYBACK_VOICE
570 voice_stop();
571 #endif
572 talk_buffer_steal();
574 #ifdef PLAYBACK_VOICE
575 /* If no dram_buf, swap space not used and recording gets more
576 memory. Codec swap areas will remain unaffected by the next init
577 since they're allocated at the end of the buffer and their sizes
578 don't change between calls */
579 end = dram_buf;
580 if (NULL == end)
581 #endif /* PLAYBACK_VOICE */
582 end = audiobufend;
584 buffer_state = BUFFER_STATE_TRASHED;
586 *buffer_size = end - audiobuf;
588 return (unsigned char *)audiobuf;
591 bool audio_load_encoder(int afmt)
593 #ifndef SIMULATOR
594 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
595 if (!enc_fn)
596 return false;
598 audio_remove_encoder();
599 ci.enc_codec_loaded = 0; /* clear any previous error condition */
601 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
602 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
604 while (ci.enc_codec_loaded == 0)
605 yield();
607 logf("codec loaded: %d", ci.enc_codec_loaded);
609 return ci.enc_codec_loaded > 0;
610 #else
611 (void)afmt;
612 return true;
613 #endif
614 } /* audio_load_encoder */
616 void audio_remove_encoder(void)
618 #ifndef SIMULATOR
619 /* force encoder codec unload (if currently loaded) */
620 if (ci.enc_codec_loaded <= 0)
621 return;
623 ci.stop_encoder = true;
624 while (ci.enc_codec_loaded > 0)
625 yield();
626 #endif
627 } /* audio_remove_encoder */
629 #endif /* HAVE_RECORDING */
631 struct mp3entry* audio_current_track(void)
633 const char *filename;
634 const char *p;
635 static struct mp3entry temp_id3;
636 int cur_idx;
637 int offset = ci.new_track + wps_offset;
639 cur_idx = track_ridx + offset;
640 cur_idx &= MAX_TRACK_MASK;
642 if (tracks[cur_idx].id3_hid > 0)
643 return bufgetid3(tracks[cur_idx].id3_hid);
645 memset(&temp_id3, 0, sizeof(struct mp3entry));
647 filename = playlist_peek(0);
648 if (!filename)
649 filename = "No file!";
651 #ifdef HAVE_TC_RAMCACHE
652 if (tagcache_fill_tags(&temp_id3, filename))
653 return &temp_id3;
654 #endif
656 p = strrchr(filename, '/');
657 if (!p)
658 p = filename;
659 else
660 p++;
662 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
663 temp_id3.title = &temp_id3.path[0];
665 return &temp_id3;
668 struct mp3entry* audio_next_track(void)
670 int next_idx = track_ridx;
672 if (!audio_have_tracks())
673 return NULL;
675 next_idx++;
676 next_idx &= MAX_TRACK_MASK;
678 if (tracks[next_idx].id3_hid <= 0)
679 return NULL;
681 return bufgetid3(tracks[next_idx].id3_hid);
684 bool audio_has_changed_track(void)
686 if (track_changed)
688 track_changed = false;
689 return true;
692 return false;
695 void audio_play(long offset)
697 logf("audio_play");
699 #ifdef PLAYBACK_VOICE
700 /* Truncate any existing voice output so we don't have spelling
701 * etc. over the first part of the played track */
702 talk_force_shutup();
703 #endif
705 /* Start playback */
706 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
707 /* Don't return until playback has actually started */
708 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
711 void audio_stop(void)
713 /* Stop playback */
714 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
715 /* Don't return until playback has actually stopped */
716 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
719 void audio_pause(void)
721 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
722 /* Don't return until playback has actually paused */
723 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
726 void audio_resume(void)
728 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
729 /* Don't return until playback has actually resumed */
730 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
733 void audio_next(void)
735 if (playlist_check(ci.new_track + wps_offset + 1))
737 if (global_settings.beep)
738 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
740 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
741 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
742 /* Update wps while our message travels inside deep playback queues. */
743 wps_offset++;
744 track_changed = true;
746 else
748 /* No more tracks. */
749 if (global_settings.beep)
750 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
754 void audio_prev(void)
756 if (playlist_check(ci.new_track + wps_offset - 1))
758 if (global_settings.beep)
759 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
761 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
762 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
763 /* Update wps while our message travels inside deep playback queues. */
764 wps_offset--;
765 track_changed = true;
767 else
769 /* No more tracks. */
770 if (global_settings.beep)
771 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
775 void audio_next_dir(void)
777 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
778 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
781 void audio_prev_dir(void)
783 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
784 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
787 void audio_pre_ff_rewind(void)
789 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
790 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
793 void audio_ff_rewind(long newpos)
795 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
796 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
799 void audio_flush_and_reload_tracks(void)
801 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
802 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
805 void audio_error_clear(void)
807 #ifdef AUDIO_HAVE_RECORDING
808 pcm_rec_error_clear();
809 #endif
812 int audio_status(void)
814 int ret = 0;
816 if (playing)
817 ret |= AUDIO_STATUS_PLAY;
819 if (paused)
820 ret |= AUDIO_STATUS_PAUSE;
822 #ifdef HAVE_RECORDING
823 /* Do this here for constitency with mpeg.c version */
824 ret |= pcm_rec_status();
825 #endif
827 return ret;
830 int audio_get_file_pos(void)
832 return 0;
835 #ifndef HAVE_FLASH_STORAGE
836 void audio_set_buffer_margin(int setting)
838 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
839 buffer_margin = lookup[setting];
840 logf("buffer margin: %ld", buffer_margin);
841 set_filebuf_watermark(buffer_margin);
843 #endif
845 /* Take nescessary steps to enable or disable the crossfade setting */
846 void audio_set_crossfade(int enable)
848 size_t offset;
849 bool was_playing;
850 size_t size;
852 /* Tell it the next setting to use */
853 pcmbuf_crossfade_enable(enable);
855 /* Return if size hasn't changed or this is too early to determine
856 which in the second case there's no way we could be playing
857 anything at all */
858 if (pcmbuf_is_same_size())
860 /* This function is a copout and just syncs some variables -
861 to be removed at a later date */
862 pcmbuf_crossfade_enable_finished();
863 return;
866 offset = 0;
867 was_playing = playing;
869 /* Playback has to be stopped before changing the buffer size */
870 if (was_playing)
872 /* Store the track resume position */
873 offset = curtrack_id3.offset;
874 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
877 /* Blast it - audio buffer will have to be setup again next time
878 something plays */
879 audio_get_buffer(true, &size);
881 /* Restart playback if audio was running previously */
882 if (was_playing)
883 audio_play(offset);
886 /* --- Routines called from multiple threads --- */
887 static void set_current_codec(int codec_idx)
889 current_codec = codec_idx;
890 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
893 #ifdef PLAYBACK_VOICE
894 static void swap_codec(void)
896 int my_codec;
898 /* Swap nothing if no swap buffers exist */
899 if (dram_buf == NULL)
901 logf("swap: no swap buffers");
902 return;
905 my_codec = current_codec;
907 logf("swapping out codec: %d", my_codec);
909 /* Invert this when a codec thread enters and leaves */
910 swap_codec_parity = !swap_codec_parity;
912 /* If this is true, an odd number of calls has occurred and there's
913 no codec thread waiting to swap us out when it locks and runs. This
914 occurs when playback is stopped or when just starting playback and
915 the audio thread is loading a codec; parities should always be even
916 on entry when a thread calls this during playback */
917 if (swap_codec_parity)
919 /* Save our current IRAM and DRAM */
920 #ifdef IRAM_STEAL
921 if (voice_iram_stolen)
923 logf("swap: iram restore");
924 voice_iram_stolen = false;
925 /* Don't swap trashed data into buffer as the voice IRAM will
926 already be swapped out - should _always_ be the case if
927 voice_iram_stolen is true since the voice has been swapped
928 in beforehand */
929 if (my_codec == CODEC_IDX_VOICE)
931 logf("voice iram already swapped");
932 goto skip_iram_swap;
935 #endif
937 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
939 #ifdef IRAM_STEAL
940 skip_iram_swap:
941 #endif
943 memswap128(dram_buf, codecbuf, CODEC_SIZE);
944 /* No cache invalidation needed; it will be done in codec_load_ram
945 or we won't be here otherwise */
948 /* Release my semaphore */
949 semaphore_release(&sem_codecthread);
950 logf("unlocked: %d", my_codec);
952 /* Wait for other codec */
953 event_wait(&event_codecthread,
954 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
956 /* Wait for other codec to unlock */
957 logf("waiting for lock: %d", my_codec);
958 semaphore_wait(&sem_codecthread);
960 /* Take control */
961 set_current_codec(my_codec);
962 event_set_state(&event_codecthread,
963 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
965 /* Reload our IRAM and DRAM */
966 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
967 memswap128(dram_buf, codecbuf, CODEC_SIZE);
968 invalidate_icache();
970 /* Flip parity again */
971 swap_codec_parity = !swap_codec_parity;
973 logf("resuming codec: %d", my_codec);
976 /* This function is meant to be used by the buffer stealing functions to
977 ensure the codec is no longer active and so voice will be swapped-in
978 before it is called */
979 static void voice_stop(void)
981 /* Must have a voice codec loaded or we'll hang forever here */
982 if (!voice_codec_loaded)
983 return;
985 talk_force_shutup();
987 /* Loop until voice empties it's queue, stops and picks up on the new
988 track; the voice thread must be stopped and waiting for messages
989 outside the codec */
990 while (voice_is_playing || !queue_empty(&voice_queue) ||
991 ci_voice.new_track)
992 yield();
994 if (!playing)
995 pcmbuf_play_stop();
996 } /* voice_stop */
998 /* Is voice still speaking */
999 /* Unfortunately only reliable when music is not also playing. */
1000 static bool is_voice_speaking(void)
1002 return is_voice_queued()
1003 || voice_is_playing
1004 || (!playing && pcm_is_playing());
1007 #endif /* PLAYBACK_VOICE */
1009 /* Wait for voice to finish speaking. */
1010 /* Also only reliable when music is not also playing. */
1011 void voice_wait(void)
1013 #ifdef PLAYBACK_VOICE
1014 while (is_voice_speaking())
1015 sleep(HZ/10);
1016 #endif
1019 static void set_filebuf_watermark(int seconds)
1021 size_t bytes;
1023 if (!filebuf)
1024 return; /* Audio buffers not yet set up */
1026 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), conf_watermark);
1027 bytes = MIN(bytes, filebuflen / 2);
1028 conf_watermark = bytes;
1031 const char * get_codec_filename(int cod_spec)
1033 const char *fname;
1035 #ifdef HAVE_RECORDING
1036 /* Can choose decoder or encoder if one available */
1037 int type = cod_spec & CODEC_TYPE_MASK;
1038 int afmt = cod_spec & CODEC_AFMT_MASK;
1040 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1041 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1043 fname = (type == CODEC_TYPE_ENCODER) ?
1044 audio_formats[afmt].codec_enc_root_fn :
1045 audio_formats[afmt].codec_root_fn;
1047 logf("%s: %d - %s",
1048 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1049 afmt, fname ? fname : "<unknown>");
1050 #else /* !HAVE_RECORDING */
1051 /* Always decoder */
1052 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1053 cod_spec = AFMT_UNKNOWN;
1054 fname = audio_formats[cod_spec].codec_root_fn;
1055 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1056 #endif /* HAVE_RECORDING */
1058 return fname;
1059 } /* get_codec_filename */
1062 /* --- Voice thread --- */
1064 #ifdef PLAYBACK_VOICE
1066 static bool voice_pcmbuf_insert_callback(
1067 const void *ch1, const void *ch2, int count)
1069 const char *src[2] = { ch1, ch2 };
1071 while (count > 0)
1073 int out_count = dsp_output_count(count);
1074 int inp_count;
1075 char *dest;
1077 while ((dest = pcmbuf_request_voice_buffer(
1078 &out_count, playing)) == NULL)
1080 if (playing && audio_codec_loaded)
1081 swap_codec();
1082 else
1083 yield();
1086 /* Get the real input_size for output_size bytes, guarding
1087 * against resampling buffer overflows. */
1088 inp_count = dsp_input_count(out_count);
1090 if (inp_count <= 0)
1091 return true;
1093 /* Input size has grown, no error, just don't write more than length */
1094 if (inp_count > count)
1095 inp_count = count;
1097 out_count = dsp_process(dest, src, inp_count);
1099 if (out_count <= 0)
1100 return true;
1102 if (playing)
1104 pcmbuf_mix_voice(out_count);
1105 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1106 audio_codec_loaded)
1107 swap_codec();
1109 else
1110 pcmbuf_write_complete(out_count);
1112 count -= inp_count;
1115 return true;
1116 } /* voice_pcmbuf_insert_callback */
1118 static void* voice_get_memory_callback(size_t *size)
1120 /* Voice should have no use for this. If it did, we'd have to
1121 swap the malloc buffer as well. */
1122 *size = 0;
1123 return NULL;
1126 static void voice_set_elapsed_callback(unsigned int value)
1128 (void)value;
1131 static void voice_set_offset_callback(size_t value)
1133 (void)value;
1136 static void voice_configure_callback(int setting, intptr_t value)
1138 if (!dsp_configure(setting, value))
1140 logf("Illegal key:%d", setting);
1144 static size_t voice_filebuf_callback(void *ptr, size_t size)
1146 (void)ptr;
1147 (void)size;
1149 return 0;
1152 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1153 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1155 if (aborting && !playing)
1157 /* Aborting: Slight hack - flush PCM buffer if
1158 only being used for voice */
1159 pcmbuf_play_stop();
1162 if (voice_is_playing)
1164 /* Clear the current buffer */
1165 voice_is_playing = false;
1166 voice_getmore = NULL;
1167 voice_remaining = 0;
1168 voicebuf = NULL;
1170 /* Cancel any automatic boost if no more clips requested. */
1171 if (!playing || !voice_thread_start)
1172 sleep(0);
1174 /* Force the codec to think it's changing tracks */
1175 ci_voice.new_track = 1;
1177 *realsize = 0;
1178 return true; /* Yes, change tracks */
1181 return false;
1184 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1186 struct queue_event ev;
1188 if (ci_voice.new_track)
1190 *realsize = 0;
1191 return NULL;
1194 while (1)
1196 if (voice_is_playing || playing)
1198 queue_wait_w_tmo(&voice_queue, &ev, 0);
1199 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1200 ev.id = Q_AUDIO_PLAY;
1202 else
1204 queue_wait(&voice_queue, &ev);
1207 switch (ev.id) {
1208 case Q_AUDIO_PLAY:
1209 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1210 if (playing)
1212 if (audio_codec_loaded)
1213 swap_codec();
1214 yield();
1216 break;
1218 #ifdef AUDIO_HAVE_RECORDING
1219 case Q_ENCODER_RECORD:
1220 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1221 swap_codec();
1222 break;
1223 #endif
1225 case Q_VOICE_STOP:
1226 LOGFQUEUE("voice < Q_VOICE_STOP");
1227 if (voice_on_voice_stop(ev.data, realsize))
1228 return NULL;
1229 break;
1231 case SYS_USB_CONNECTED:
1233 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1234 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1235 /* Voice is obviously current so let us swap ourselves away if
1236 playing so audio may stop itself - audio_codec_loaded can
1237 only be true in this case if we're here even if the codec
1238 is only about to load */
1239 if (audio_codec_loaded)
1240 swap_codec();
1241 /* Playback should be finished by now - ack and wait */
1242 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1243 usb_wait_for_disconnect(&voice_queue);
1244 if (change_tracks)
1245 return NULL;
1246 break;
1249 case Q_VOICE_PLAY:
1250 LOGFQUEUE("voice < Q_VOICE_PLAY");
1251 if (!voice_is_playing)
1253 /* Set up new voice data */
1254 struct voice_info *voice_data;
1255 #ifdef IRAM_STEAL
1256 if (voice_iram_stolen)
1258 /* Voice is the first to run again and is currently
1259 loaded */
1260 logf("voice: iram restore");
1261 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1262 voice_iram_stolen = false;
1264 #endif
1265 /* Must reset the buffer before any playback begins if
1266 needed */
1267 if (buffer_state == BUFFER_STATE_TRASHED)
1268 audio_reset_buffer();
1270 voice_is_playing = true;
1271 trigger_cpu_boost();
1272 voice_data = (struct voice_info *)ev.data;
1273 voice_remaining = voice_data->size;
1274 voicebuf = voice_data->buf;
1275 voice_getmore = voice_data->callback;
1277 goto voice_play_clip; /* To exit both switch and while */
1279 case SYS_TIMEOUT:
1280 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1281 goto voice_play_clip;
1283 default:
1284 LOGFQUEUE("voice < default");
1288 voice_play_clip:
1290 if (voice_remaining == 0 || voicebuf == NULL)
1292 if (voice_getmore)
1293 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1295 /* If this clip is done */
1296 if (voice_remaining == 0)
1298 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1299 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1300 /* Force pcm playback. */
1301 if (!pcm_is_playing())
1302 pcmbuf_play_start();
1306 *realsize = MIN(voice_remaining, reqsize);
1308 if (*realsize == 0)
1309 return NULL;
1311 return voicebuf;
1312 } /* voice_request_buffer_callback */
1314 static void voice_advance_buffer_callback(size_t amount)
1316 amount = MIN(amount, voice_remaining);
1317 voicebuf += amount;
1318 voice_remaining -= amount;
1321 static void voice_advance_buffer_loc_callback(void *ptr)
1323 size_t amount = (size_t)ptr - (size_t)voicebuf;
1325 voice_advance_buffer_callback(amount);
1328 static off_t voice_mp3_get_filepos_callback(int newtime)
1330 (void)newtime;
1332 return 0;
1335 static void voice_do_nothing(void)
1337 return;
1340 static bool voice_seek_buffer_callback(size_t newpos)
1342 (void)newpos;
1344 return false;
1347 static bool voice_request_next_track_callback(void)
1349 ci_voice.new_track = 0;
1350 return true;
1353 static void voice_thread(void)
1355 logf("Loading voice codec");
1356 voice_codec_loaded = true;
1357 semaphore_wait(&sem_codecthread);
1358 event_set_state(&event_codecthread, false);
1359 set_current_codec(CODEC_IDX_VOICE);
1360 dsp_configure(DSP_RESET, 0);
1361 voice_remaining = 0;
1362 voice_getmore = NULL;
1364 /* FIXME: If we being starting the voice thread without reboot, the
1365 voice_queue could be full of old stuff and we must flush it. */
1366 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1368 logf("Voice codec finished");
1369 voice_codec_loaded = false;
1370 voice_thread_p = NULL;
1371 semaphore_release(&sem_codecthread);
1372 } /* voice_thread */
1374 #endif /* PLAYBACK_VOICE */
1376 /* --- Codec thread --- */
1377 static bool codec_pcmbuf_insert_callback(
1378 const void *ch1, const void *ch2, int count)
1380 const char *src[2] = { ch1, ch2 };
1382 while (count > 0)
1384 int out_count = dsp_output_count(count);
1385 int inp_count;
1386 char *dest;
1388 /* Prevent audio from a previous track from playing */
1389 if (ci.new_track || ci.stop_codec)
1390 return true;
1392 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1394 sleep(1);
1395 if (ci.seek_time || ci.new_track || ci.stop_codec)
1396 return true;
1399 /* Get the real input_size for output_size bytes, guarding
1400 * against resampling buffer overflows. */
1401 inp_count = dsp_input_count(out_count);
1403 if (inp_count <= 0)
1404 return true;
1406 /* Input size has grown, no error, just don't write more than length */
1407 if (inp_count > count)
1408 inp_count = count;
1410 out_count = dsp_process(dest, src, inp_count);
1412 if (out_count <= 0)
1413 return true;
1415 pcmbuf_write_complete(out_count);
1417 #ifdef PLAYBACK_VOICE
1418 if ((voice_is_playing || voice_thread_start)
1419 && pcm_is_playing() && voice_codec_loaded &&
1420 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1422 voice_thread_start = false;
1423 swap_codec();
1425 #endif
1427 count -= inp_count;
1430 return true;
1431 } /* codec_pcmbuf_insert_callback */
1433 static void* codec_get_memory_callback(size_t *size)
1435 *size = MALLOC_BUFSIZE;
1436 return malloc_buf;
1439 #if 0
1440 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1441 static void codec_pcmbuf_position_callback(size_t size)
1443 /* This is called from an ISR, so be quick */
1444 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1445 prev_ti->id3.elapsed;
1447 if (time >= prev_ti->id3.length)
1449 pcmbuf_set_position_callback(NULL);
1450 prev_ti->id3.elapsed = prev_ti->id3.length;
1452 else
1453 prev_ti->id3.elapsed = time;
1455 #endif
1457 static void codec_set_elapsed_callback(unsigned int value)
1459 unsigned int latency;
1460 if (ci.seek_time)
1461 return;
1463 #ifdef AB_REPEAT_ENABLE
1464 ab_position_report(value);
1465 #endif
1467 latency = pcmbuf_get_latency();
1468 if (value < latency)
1469 curtrack_id3.elapsed = 0;
1470 else if (value - latency > curtrack_id3.elapsed ||
1471 value - latency < curtrack_id3.elapsed - 2)
1473 curtrack_id3.elapsed = value - latency;
1477 static void codec_set_offset_callback(size_t value)
1479 unsigned int latency;
1481 if (ci.seek_time)
1482 return;
1484 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1485 if (value < latency)
1486 curtrack_id3.offset = 0;
1487 else
1488 curtrack_id3.offset = value - latency;
1491 static void codec_advance_buffer_counters(size_t amount)
1493 bufadvance(CUR_TI->audio_hid, amount);
1495 /* Start buffer filling as necessary. */
1496 if (!pcmbuf_is_lowdata() && !filling)
1498 if (bufused() < conf_watermark && playing && !playlist_end)
1500 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1501 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1506 /* copy up-to size bytes into ptr and return the actual size copied */
1507 static size_t codec_filebuf_callback(void *ptr, size_t size)
1509 size_t copy_n;
1511 if (ci.stop_codec || !playing)
1512 return 0;
1514 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1516 /* Nothing requested OR nothing left */
1517 if (copy_n == 0)
1518 return 0;
1520 /* Let the disk buffer catch fill until enough data is available */
1521 while (copy_n == -2)
1523 if (!filling)
1525 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1526 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1529 sleep(1);
1530 if (ci.stop_codec || ci.new_track)
1531 return 0;
1534 /* Update read and other position pointers */
1535 codec_advance_buffer_counters(copy_n);
1537 /* Return the actual amount of data copied to the buffer */
1538 return copy_n;
1539 } /* codec_filebuf_callback */
1541 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1543 size_t short_n, copy_n, buf_rem;
1544 char *ret;
1546 if (!playing)
1548 *realsize = 0;
1549 return NULL;
1552 copy_n = bufgetdata(CUR_TI->audio_hid, reqsize, (unsigned char **)&ret);
1553 if (copy_n == 0)
1555 *realsize = 0;
1556 return NULL;
1559 while (copy_n == -2)
1561 if (!filling)
1563 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1564 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1567 sleep(1);
1568 if (ci.stop_codec || ci.new_track)
1570 *realsize = 0;
1571 return NULL;
1575 *realsize = copy_n;
1577 return ret;
1578 } /* codec_request_buffer_callback */
1580 static int get_codec_base_type(int type)
1582 switch (type) {
1583 case AFMT_MPA_L1:
1584 case AFMT_MPA_L2:
1585 case AFMT_MPA_L3:
1586 return AFMT_MPA_L3;
1589 return type;
1592 static void codec_advance_buffer_callback(size_t amount)
1594 int ret;
1596 while (filling && (ret = bufadvance(CUR_TI->audio_hid, amount)) == -2)
1597 sleep(1);
1599 if (ret == -2)
1601 intptr_t result = Q_CODEC_REQUEST_FAILED;
1603 if (!ci.stop_codec)
1605 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1606 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1607 ci.curpos + amount);
1610 switch (result)
1612 case Q_CODEC_REQUEST_FAILED:
1613 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1614 ci.stop_codec = true;
1615 return;
1617 case Q_CODEC_REQUEST_COMPLETE:
1618 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1619 return;
1621 default:
1622 LOGFQUEUE("codec |< default");
1623 ci.stop_codec = true;
1624 return;
1628 //codec_advance_buffer_counters(amount);
1630 codec_set_offset_callback(ci.curpos);
1633 static void codec_advance_buffer_loc_callback(void *ptr)
1635 size_t amount = get_offset(CUR_TI->audio_hid, ptr);
1637 codec_advance_buffer_callback(amount);
1640 /* Copied from mpeg.c. Should be moved somewhere else. */
1641 static int codec_get_file_pos(void)
1643 int pos = -1;
1644 struct mp3entry *id3 = audio_current_track();
1646 if (id3->vbr)
1648 if (id3->has_toc)
1650 /* Use the TOC to find the new position */
1651 unsigned int percent, remainder;
1652 int curtoc, nexttoc, plen;
1654 percent = (id3->elapsed*100)/id3->length;
1655 if (percent > 99)
1656 percent = 99;
1658 curtoc = id3->toc[percent];
1660 if (percent < 99)
1661 nexttoc = id3->toc[percent+1];
1662 else
1663 nexttoc = 256;
1665 pos = (id3->filesize/256)*curtoc;
1667 /* Use the remainder to get a more accurate position */
1668 remainder = (id3->elapsed*100)%id3->length;
1669 remainder = (remainder*100)/id3->length;
1670 plen = (nexttoc - curtoc)*(id3->filesize/256);
1671 pos += (plen/100)*remainder;
1673 else
1675 /* No TOC exists, estimate the new position */
1676 pos = (id3->filesize / (id3->length / 1000)) *
1677 (id3->elapsed / 1000);
1680 else if (id3->bitrate)
1681 pos = id3->elapsed * (id3->bitrate / 8);
1682 else
1683 return -1;
1685 pos += id3->first_frame_offset;
1687 /* Don't seek right to the end of the file so that we can
1688 transition properly to the next song */
1689 if (pos >= (int)(id3->filesize - id3->id3v1len))
1690 pos = id3->filesize - id3->id3v1len - 1;
1692 return pos;
1695 static off_t codec_mp3_get_filepos_callback(int newtime)
1697 off_t newpos;
1699 curtrack_id3.elapsed = newtime;
1700 newpos = codec_get_file_pos();
1702 return newpos;
1705 static void codec_seek_complete_callback(void)
1707 logf("seek_complete");
1708 if (pcm_is_paused())
1710 /* If this is not a seamless seek, clear the buffer */
1711 pcmbuf_play_stop();
1712 dsp_configure(DSP_FLUSH, 0);
1714 /* If playback was not 'deliberately' paused, unpause now */
1715 if (!paused)
1716 pcmbuf_pause(false);
1718 ci.seek_time = 0;
1721 static bool codec_seek_buffer_callback(size_t newpos)
1723 #if 0
1724 int difference;
1726 logf("codec_seek_buffer_callback");
1728 if (newpos >= CUR_TI->filesize)
1729 newpos = CUR_TI->filesize - 1;
1731 difference = newpos - ci.curpos;
1732 if (difference >= 0)
1734 /* Seeking forward */
1735 logf("seek: +%d", difference);
1736 codec_advance_buffer_callback(difference);
1737 return true;
1740 /* Seeking backward */
1741 difference = -difference;
1742 if (ci.curpos - difference < 0)
1743 difference = ci.curpos;
1745 /* We need to reload the song. */
1746 if (newpos < CUR_TI->start_pos)
1748 intptr_t result = Q_CODEC_REQUEST_FAILED;
1750 if (!ci.stop_codec)
1752 LOGFQUEUE("codec >| audio Q_AUDIO_REBUFFER_SEEK");
1753 result = queue_send(&audio_queue, Q_AUDIO_REBUFFER_SEEK,
1754 newpos);
1757 switch (result)
1759 case Q_CODEC_REQUEST_COMPLETE:
1760 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1761 return true;
1763 case Q_CODEC_REQUEST_FAILED:
1764 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1765 ci.stop_codec = true;
1766 return false;
1768 default:
1769 LOGFQUEUE("codec |< default");
1770 return false;
1774 /* Seeking inside buffer space. */
1775 logf("seek: -%d", difference);
1776 CUR_TI->available += difference;
1777 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1778 ci.curpos -= difference;
1779 #endif
1780 return true;
1783 static void codec_configure_callback(int setting, intptr_t value)
1785 switch (setting) {
1786 case CODEC_SET_FILEBUF_WATERMARK:
1787 conf_watermark = value;
1788 set_filebuf_watermark(buffer_margin);
1789 break;
1791 case CODEC_SET_FILEBUF_CHUNKSIZE:
1792 conf_filechunk = value;
1793 break;
1795 case CODEC_SET_FILEBUF_PRESEEK:
1796 conf_preseek = value;
1797 break;
1799 default:
1800 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1804 static void codec_track_changed(void)
1806 automatic_skip = false;
1807 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1808 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1811 static void codec_pcmbuf_track_changed_callback(void)
1813 pcmbuf_set_position_callback(NULL);
1814 codec_track_changed();
1817 static void codec_discard_codec_callback(void)
1819 if (CUR_TI->codec_hid > 0)
1821 bufclose(CUR_TI->codec_hid);
1822 CUR_TI->codec_hid = 0;
1825 #if 0
1826 /* Check if a buffer desync has happened, log it and stop playback. */
1827 if (buf_ridx != CUR_TI->buf_idx)
1829 int offset = CUR_TI->buf_idx - buf_ridx;
1830 size_t new_used = bufused() - offset;
1832 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1833 logf("Used off:%d",bufused() - new_used);
1835 /* This is a fatal internal error and it's not safe to
1836 * continue playback. */
1837 ci.stop_codec = true;
1838 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1840 #endif
1843 static inline void codec_gapless_track_change(void) {
1844 /* callback keeps the progress bar moving while the pcmbuf empties */
1845 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1846 /* set the pcmbuf callback for when the track really changes */
1847 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1850 static inline void codec_crossfade_track_change(void) {
1851 /* Initiate automatic crossfade mode */
1852 pcmbuf_crossfade_init(false);
1853 /* Notify the wps that the track change starts now */
1854 codec_track_changed();
1857 static void codec_track_skip_done(bool was_manual)
1859 int crossfade_mode = global_settings.crossfade;
1861 /* Manual track change (always crossfade or flush audio). */
1862 if (was_manual)
1864 pcmbuf_crossfade_init(true);
1865 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1866 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1868 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1869 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1870 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1872 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1874 if (global_settings.playlist_shuffle)
1875 /* shuffle mode is on, so crossfade: */
1876 codec_crossfade_track_change();
1877 else
1878 /* shuffle mode is off, so do a gapless track change */
1879 codec_gapless_track_change();
1881 else
1882 /* normal crossfade: */
1883 codec_crossfade_track_change();
1885 else
1886 /* normal gapless playback. */
1887 codec_gapless_track_change();
1890 static bool codec_load_next_track(void)
1892 intptr_t result = Q_CODEC_REQUEST_FAILED;
1894 prev_track_elapsed = curtrack_id3.elapsed;
1896 if (ci.seek_time)
1897 codec_seek_complete_callback();
1899 #ifdef AB_REPEAT_ENABLE
1900 ab_end_of_track_report();
1901 #endif
1903 logf("Request new track");
1905 if (ci.new_track == 0)
1907 ci.new_track++;
1908 automatic_skip = true;
1911 if (!ci.stop_codec)
1913 trigger_cpu_boost();
1914 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1915 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1918 switch (result)
1920 case Q_CODEC_REQUEST_COMPLETE:
1921 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1922 codec_track_skip_done(!automatic_skip);
1923 return true;
1925 case Q_CODEC_REQUEST_FAILED:
1926 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1927 ci.new_track = 0;
1928 ci.stop_codec = true;
1929 return false;
1931 default:
1932 LOGFQUEUE("codec |< default");
1933 ci.stop_codec = true;
1934 return false;
1938 static bool codec_request_next_track_callback(void)
1940 int prev_codectype;
1942 if (ci.stop_codec || !playing)
1943 return false;
1945 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1947 if (!codec_load_next_track())
1948 return false;
1950 /* Check if the next codec is the same file. */
1951 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1953 logf("New track loaded");
1954 codec_discard_codec_callback();
1955 return true;
1957 else
1959 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1960 return false;
1964 static void codec_thread(void)
1966 struct queue_event ev;
1967 int status;
1968 size_t wrap;
1970 while (1) {
1971 status = 0;
1972 queue_wait(&codec_queue, &ev);
1974 switch (ev.id) {
1975 case Q_CODEC_LOAD_DISK:
1976 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1977 audio_codec_loaded = true;
1978 #ifdef PLAYBACK_VOICE
1979 /* Don't sent messages to voice codec if it's already swapped
1980 out or it will never get this */
1981 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1983 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1984 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1986 semaphore_wait(&sem_codecthread);
1987 event_set_state(&event_codecthread, true);
1988 #endif
1989 set_current_codec(CODEC_IDX_AUDIO);
1990 ci.stop_codec = false;
1991 status = codec_load_file((const char *)ev.data, &ci);
1992 #ifdef PLAYBACK_VOICE
1993 semaphore_release(&sem_codecthread);
1994 #endif
1995 break;
1997 case Q_CODEC_LOAD:
1998 LOGFQUEUE("codec < Q_CODEC_LOAD");
1999 if (CUR_TI->codec_hid <= 0) {
2000 logf("Codec slot is empty!");
2001 /* Wait for the pcm buffer to go empty */
2002 while (pcm_is_playing())
2003 yield();
2004 /* This must be set to prevent an infinite loop */
2005 ci.stop_codec = true;
2006 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
2007 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
2008 break;
2011 audio_codec_loaded = true;
2012 #ifdef PLAYBACK_VOICE
2013 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2015 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
2016 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
2018 semaphore_wait(&sem_codecthread);
2019 event_set_state(&event_codecthread, true);
2020 #endif
2021 set_current_codec(CODEC_IDX_AUDIO);
2022 ci.stop_codec = false;
2023 wrap = (size_t)&filebuf[filebuflen] - (size_t)getptr(CUR_TI->codec_hid);
2024 status = codec_load_ram(getptr(CUR_TI->codec_hid), CUR_TI->codecsize,
2025 &filebuf[0], wrap, &ci);
2026 #ifdef PLAYBACK_VOICE
2027 semaphore_release(&sem_codecthread);
2028 #endif
2029 break;
2031 #ifdef AUDIO_HAVE_RECORDING
2032 case Q_ENCODER_LOAD_DISK:
2033 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2034 audio_codec_loaded = false; /* Not audio codec! */
2035 #ifdef PLAYBACK_VOICE
2036 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
2038 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
2039 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
2041 semaphore_wait(&sem_codecthread);
2042 event_set_state(&event_codecthread, true);
2043 #endif
2044 logf("loading encoder");
2045 set_current_codec(CODEC_IDX_AUDIO);
2046 ci.stop_encoder = false;
2047 status = codec_load_file((const char *)ev.data, &ci);
2048 #ifdef PLAYBACK_VOICE
2049 semaphore_release(&sem_codecthread);
2050 #endif
2051 logf("encoder stopped");
2052 break;
2053 #endif /* AUDIO_HAVE_RECORDING */
2055 #ifndef SIMULATOR
2056 case SYS_USB_CONNECTED:
2057 LOGFQUEUE("codec < SYS_USB_CONNECTED");
2058 queue_clear(&codec_queue);
2059 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2060 usb_wait_for_disconnect(&codec_queue);
2061 break;
2062 #endif
2064 default:
2065 LOGFQUEUE("codec < default");
2068 if (audio_codec_loaded)
2070 if (ci.stop_codec)
2072 status = CODEC_OK;
2073 if (!playing)
2074 pcmbuf_play_stop();
2077 audio_codec_loaded = false;
2080 switch (ev.id) {
2081 case Q_CODEC_LOAD_DISK:
2082 case Q_CODEC_LOAD:
2083 LOGFQUEUE("codec < Q_CODEC_LOAD");
2084 if (playing)
2086 if (ci.new_track || status != CODEC_OK)
2088 if (!ci.new_track)
2090 logf("Codec failure");
2091 gui_syncsplash(HZ*2, "Codec failure");
2094 if (!codec_load_next_track())
2096 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2097 /* End of playlist */
2098 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2099 break;
2102 else
2104 logf("Codec finished");
2105 if (ci.stop_codec)
2107 /* Wait for the audio to stop playing before
2108 * triggering the WPS exit */
2109 while(pcm_is_playing())
2111 curtrack_id3.elapsed =
2112 curtrack_id3.length - pcmbuf_get_latency();
2113 sleep(1);
2115 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2116 /* End of playlist */
2117 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2118 break;
2122 if (CUR_TI->codec_hid > 0)
2124 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2125 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2127 else
2129 const char *codec_fn =
2130 get_codec_filename(curtrack_id3.codectype);
2131 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2132 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2133 (intptr_t)codec_fn);
2136 break;
2138 #ifdef AUDIO_HAVE_RECORDING
2139 case Q_ENCODER_LOAD_DISK:
2140 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2142 if (status == CODEC_OK)
2143 break;
2145 logf("Encoder failure");
2146 gui_syncsplash(HZ*2, "Encoder failure");
2148 if (ci.enc_codec_loaded < 0)
2149 break;
2151 logf("Encoder failed to load");
2152 ci.enc_codec_loaded = -1;
2153 break;
2154 #endif /* AUDIO_HAVE_RECORDING */
2156 default:
2157 LOGFQUEUE("codec < default");
2159 } /* end switch */
2164 /* --- Audio thread --- */
2166 static bool audio_filebuf_is_lowdata(void)
2168 return bufused() < AUDIO_FILEBUF_CRITICAL;
2171 static bool audio_have_tracks(void)
2173 return track_ridx != track_widx || CUR_TI->filesize;
2176 static bool audio_have_free_tracks(void)
2178 if (track_widx < track_ridx)
2179 return track_widx + 1 < track_ridx;
2180 else if (track_ridx == 0)
2181 return track_widx < MAX_TRACK - 1;
2183 return true;
2186 int audio_track_count(void)
2188 if (audio_have_tracks())
2190 int relative_track_widx = track_widx;
2192 if (track_ridx > track_widx)
2193 relative_track_widx += MAX_TRACK;
2195 return relative_track_widx - track_ridx + 1;
2198 return 0;
2201 long audio_filebufused(void)
2203 return (long) bufused();
2206 /* Count the data BETWEEN the selected tracks */
2207 static size_t audio_buffer_count_tracks(int from_track, int to_track)
2209 size_t amount = 0;
2210 bool need_wrap = to_track < from_track;
2212 while (1)
2214 if (++from_track >= MAX_TRACK)
2216 from_track -= MAX_TRACK;
2217 need_wrap = false;
2220 if (from_track >= to_track && !need_wrap)
2221 break;
2223 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
2225 return amount;
2228 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
2230 #if 0
2231 size_t amount;
2233 /* Start with the remainder of the previously playing track */
2234 amount = tracks[old_track_ridx].filesize - ci.curpos;
2235 /* Then collect all data from tracks in between them */
2236 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
2237 logf("bwf:%ldB", (long) amount);
2239 if (amount > bufused())
2240 return false;
2242 /* Wind the buffer to the beginning of the target track or its codec */
2243 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
2244 #endif
2245 return true;
2248 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
2250 #if 0
2251 /* Available buffer data */
2252 size_t buf_back;
2253 /* Start with the previously playing track's data and our data */
2254 size_t amount;
2256 amount = ci.curpos;
2257 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
2259 /* If we're not just resetting the current track */
2260 if (new_track_ridx != old_track_ridx)
2262 /* Need to wind to before the old track's codec and our filesize */
2263 amount += tracks[old_track_ridx].codecsize;
2264 amount += tracks[new_track_ridx].filesize;
2266 /* Rewind the old track to its beginning */
2267 tracks[old_track_ridx].available =
2268 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2271 /* If the codec was ever buffered */
2272 if (tracks[new_track_ridx].codecsize)
2274 /* Add the codec to the needed size */
2275 amount += tracks[new_track_ridx].codecsize;
2276 tracks[new_track_ridx].has_codec = true;
2279 /* Then collect all data from tracks between new and old */
2280 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2282 /* Do we have space to make this skip? */
2283 if (amount > buf_back)
2284 return false;
2286 logf("bwb:%ldB",amount);
2288 /* Rewind the buffer to the beginning of the target track or its codec */
2289 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2291 /* Reset to the beginning of the new track */
2292 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2293 #endif
2294 return true;
2297 static void audio_update_trackinfo(void)
2299 ci.filesize = CUR_TI->filesize;
2300 curtrack_id3.elapsed = 0;
2301 curtrack_id3.offset = 0;
2302 ci.id3 = &curtrack_id3;
2303 ci.curpos = 0;
2304 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2307 /* Yield to codecs for as long as possible if they are in need of data
2308 * return true if the caller should break to let the audio thread process
2309 * new events */
2310 static bool audio_yield_codecs(void)
2312 yield();
2314 if (!queue_empty(&audio_queue))
2315 return true;
2317 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2318 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2320 if (filling)
2321 yield();
2322 else
2323 sleep(2);
2325 if (!queue_empty(&audio_queue))
2326 return true;
2329 return false;
2332 static void audio_clear_track_entries(bool clear_unbuffered)
2334 int cur_idx = track_widx;
2335 int last_idx = -1;
2337 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2339 #if 0
2340 /* Loop over all tracks from write-to-read */
2341 while (1)
2343 cur_idx++;
2344 cur_idx &= MAX_TRACK_MASK;
2346 if (cur_idx == track_ridx)
2347 break;
2349 /* If the track is buffered, conditionally clear/notify,
2350 * otherwise clear the track if that option is selected */
2351 if (tracks[cur_idx].event_sent)
2353 if (last_idx >= 0)
2355 /* If there is an unbuffer callback, call it, otherwise,
2356 * just clear the track */
2357 if (track_unbuffer_callback)
2358 track_unbuffer_callback(&tracks[last_idx].id3, false);
2360 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2362 last_idx = cur_idx;
2364 else if (clear_unbuffered)
2365 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2368 /* We clear the previous instance of a buffered track throughout
2369 * the above loop to facilitate 'last' detection. Clear/notify
2370 * the last track here */
2371 if (last_idx >= 0)
2373 if (track_unbuffer_callback)
2374 track_unbuffer_callback(&tracks[last_idx].id3, true);
2375 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2377 #endif
2379 for (cur_idx = track_widx; cur_idx != track_ridx;
2380 cur_idx++, cur_idx &= MAX_TRACK_MASK)
2382 bufclose(tracks[cur_idx].audio_hid);
2383 bufclose(tracks[cur_idx].id3_hid);
2384 bufclose(tracks[cur_idx].codec_hid);
2388 /* FIXME: This code should be made more generic and move to metadata.c */
2389 static void audio_strip_tags(void)
2391 #if 0
2392 int i;
2393 static const unsigned char tag[] = "TAG";
2394 static const unsigned char apetag[] = "APETAGEX";
2395 size_t tag_idx;
2396 size_t cur_idx;
2397 size_t len, version;
2399 tag_idx = RINGBUF_SUB(buf_widx, 128);
2401 if (bufused() > 128 && tag_idx > buf_ridx)
2403 cur_idx = tag_idx;
2404 for(i = 0;i < 3;i++)
2406 if(filebuf[cur_idx] != tag[i])
2407 goto strip_ape_tag;
2409 cur_idx = RINGBUF_ADD(cur_idx, 1);
2412 /* Skip id3v1 tag */
2413 logf("Skipping ID3v1 tag");
2414 buf_widx = tag_idx;
2415 tracks[track_widx].available -= 128;
2416 tracks[track_widx].filesize -= 128;
2419 strip_ape_tag:
2420 /* Check for APE tag (look for the APE tag footer) */
2421 tag_idx = RINGBUF_SUB(buf_widx, 32);
2423 if (bufused() > 32 && tag_idx > buf_ridx)
2425 cur_idx = tag_idx;
2426 for(i = 0;i < 8;i++)
2428 if(filebuf[cur_idx] != apetag[i])
2429 return;
2431 cur_idx = RINGBUF_ADD(cur_idx, 1);
2434 /* Read the version and length from the footer */
2435 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2436 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2437 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2438 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2439 if (version == 2000)
2440 len += 32; /* APEv2 has a 32 byte header */
2442 /* Skip APE tag */
2443 if (bufused() > len)
2445 logf("Skipping APE tag (%ldB)", len);
2446 buf_widx = RINGBUF_SUB(buf_widx, len);
2447 tracks[track_widx].available -= len;
2448 tracks[track_widx].filesize -= len;
2451 #endif
2454 /* Returns true if a whole file is read, false otherwise */
2455 static bool audio_read_file(size_t minimum)
2457 #if 0
2458 bool ret_val = false;
2460 /* If we're called and no file is open, this is an error */
2461 if (current_fd < 0)
2463 logf("Bad fd in arf");
2464 /* Give some hope of miraculous recovery by forcing a track reload */
2465 tracks[track_widx].filesize = 0;
2466 /* Stop this buffering run */
2467 return ret_val;
2470 trigger_cpu_boost();
2471 while (tracks[track_widx].filerem > 0)
2473 size_t copy_n;
2474 int overlap;
2475 int rc;
2477 /* copy_n is the largest chunk that is safe to read */
2478 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2480 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2481 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2482 break;
2484 /* rc is the actual amount read */
2485 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2487 if (rc < 0)
2489 logf("File ended %ldB early", tracks[track_widx].filerem);
2490 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2491 tracks[track_widx].filerem = 0;
2492 break;
2495 /* How much of the playing track did we overwrite */
2496 if (buf_widx == CUR_TI->buf_idx)
2498 /* Special handling; zero or full overlap? */
2499 if (track_widx == track_ridx && CUR_TI->available == 0)
2500 overlap = 0;
2501 else
2502 overlap = rc;
2504 else
2505 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2507 if ((unsigned)rc > tracks[track_widx].filerem)
2509 logf("Bad: rc-filerem=%ld, fixing", rc-tracks[track_widx].filerem);
2510 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2511 tracks[track_widx].filerem = rc;
2514 /* Advance buffer */
2515 buf_widx = RINGBUF_ADD(buf_widx, rc);
2516 tracks[track_widx].available += rc;
2517 tracks[track_widx].filerem -= rc;
2519 /* If we write into the playing track, adjust it's buffer info */
2520 if (overlap > 0)
2522 CUR_TI->buf_idx += overlap;
2523 CUR_TI->start_pos += overlap;
2526 /* For a rebuffer, fill at least this minimum */
2527 if (minimum > (unsigned)rc)
2528 minimum -= rc;
2529 /* Let the codec process up to the watermark */
2530 /* Break immediately if this is a quick buffer, or there is an event */
2531 else if (minimum || audio_yield_codecs())
2533 /* Exit quickly, but don't stop the overall buffering process */
2534 ret_val = true;
2535 break;
2539 if (tracks[track_widx].filerem == 0)
2541 logf("Finished buf:%ldB", tracks[track_widx].filesize);
2542 close(current_fd);
2543 current_fd = -1;
2544 audio_strip_tags();
2546 track_widx++;
2547 track_widx &= MAX_TRACK_MASK;
2549 tracks[track_widx].filesize = 0;
2550 return true;
2552 else
2554 logf("%s buf:%ldB", ret_val?"Quick":"Partially",
2555 tracks[track_widx].filesize - tracks[track_widx].filerem);
2556 return ret_val;
2558 #endif
2561 static bool audio_loadcodec(bool start_play)
2563 size_t size = 0;
2564 int fd;
2565 int rc;
2566 size_t copy_n;
2567 int prev_track;
2568 char codec_path[MAX_PATH]; /* Full path to codec */
2570 if (tracks[track_widx].id3_hid <= 0)
2571 return false;
2573 const char * codec_fn =
2574 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2575 if (codec_fn == NULL)
2576 return false;
2578 tracks[track_widx].codec_hid = 0;
2580 if (start_play)
2582 /* Load the codec directly from disk and save some memory. */
2583 track_ridx = track_widx;
2584 ci.filesize = CUR_TI->filesize;
2585 ci.id3 = &curtrack_id3;
2586 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2587 ci.curpos = 0;
2588 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2589 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2590 return true;
2592 else
2594 /* If we already have another track than this one buffered */
2595 if (track_widx != track_ridx)
2597 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2599 /* If the previous codec is the same as this one, there is no need
2600 * to put another copy of it on the file buffer */
2601 if (get_codec_base_type(
2602 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2603 get_codec_base_type(
2604 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2605 && audio_codec_loaded)
2607 logf("Reusing prev. codec");
2608 return true;
2613 codec_get_full_path(codec_path, codec_fn);
2615 fd = open(codec_path, O_RDONLY);
2616 if (fd < 0)
2618 logf("Codec doesn't exist!");
2619 return false;
2622 tracks[track_widx].codecsize = filesize(fd);
2624 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2625 if (tracks[track_widx].codec_hid < 0)
2627 logf("Not enough space");
2628 close(fd);
2629 return false;
2632 close(fd);
2633 logf("Done: %ldB", size);
2635 return true;
2638 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2639 static void audio_set_elapsed(struct mp3entry* id3)
2641 unsigned long offset = id3->offset > id3->first_frame_offset ?
2642 id3->offset - id3->first_frame_offset : 0;
2644 if ( id3->vbr ) {
2645 if ( id3->has_toc ) {
2646 /* calculate elapsed time using TOC */
2647 int i;
2648 unsigned int remainder, plen, relpos, nextpos;
2650 /* find wich percent we're at */
2651 for (i=0; i<100; i++ )
2652 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2653 break;
2655 i--;
2656 if (i < 0)
2657 i = 0;
2659 relpos = id3->toc[i];
2661 if (i < 99)
2662 nextpos = id3->toc[i+1];
2663 else
2664 nextpos = 256;
2666 remainder = offset - (relpos * (id3->filesize / 256));
2668 /* set time for this percent (divide before multiply to prevent
2669 overflow on long files. loss of precision is negligible on
2670 short files) */
2671 id3->elapsed = i * (id3->length / 100);
2673 /* calculate remainder time */
2674 plen = (nextpos - relpos) * (id3->filesize / 256);
2675 id3->elapsed += (((remainder * 100) / plen) *
2676 (id3->length / 10000));
2678 else {
2679 /* no TOC exists. set a rough estimate using average bitrate */
2680 int tpk = id3->length /
2681 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2682 1024);
2683 id3->elapsed = offset / 1024 * tpk;
2686 else
2688 /* constant bitrate, use exact calculation */
2689 if (id3->bitrate != 0)
2690 id3->elapsed = offset / (id3->bitrate / 8);
2694 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2696 char *trackname;
2697 off_t size;
2698 char msgbuf[80];
2699 int fd;
2700 struct mp3entry id3;
2702 /* Stop buffer filling if there is no free track entries.
2703 Don't fill up the last track entry (we wan't to store next track
2704 metadata there). */
2705 if (!audio_have_free_tracks())
2707 logf("No free tracks");
2708 return false;
2711 last_peek_offset++;
2712 peek_again:
2713 logf("Buffering track:%d/%d", track_widx, track_ridx);
2714 /* Get track name from current playlist read position. */
2715 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2717 /* Handle broken playlists. */
2718 fd = open(trackname, O_RDONLY);
2719 if (fd < 0)
2721 logf("Open failed");
2722 /* Skip invalid entry from playlist. */
2723 playlist_skip_entry(NULL, last_peek_offset);
2725 else
2726 break;
2729 if (!trackname)
2731 logf("End-of-playlist");
2732 playlist_end = true;
2733 return false;
2736 tracks[track_widx].audio_hid = bufopen(trackname, offset, TYPE_AUDIO);
2738 if (tracks[track_widx].audio_hid <= 0)
2739 return false;
2741 /* Set default values */
2742 if (start_play)
2744 int last_codec = current_codec;
2746 set_current_codec(CODEC_IDX_AUDIO);
2747 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2748 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2749 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2750 dsp_configure(DSP_RESET, 0);
2751 set_current_codec(last_codec);
2754 /* Get track metadata if we don't already have it. */
2755 if (!tracks[track_widx].taginfo_ready)
2757 if (get_metadata(&id3, fd, trackname))
2759 tracks[track_widx].taginfo_ready = true;
2760 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2761 TYPE_ID3);
2762 if (start_play)
2764 track_changed = true;
2765 playlist_update_resume_info(audio_current_track());
2768 else
2770 logf("mde:%s!",trackname);
2772 /* Skip invalid entry from playlist. */
2773 playlist_skip_entry(NULL, last_peek_offset);
2774 tracks[track_widx].taginfo_ready = false;
2775 goto peek_again;
2780 #if 0
2781 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2783 char cuepath[MAX_PATH];
2785 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2787 if (look_for_cuesheet_file(trackname, cuepath) &&
2788 parse_cuesheet(cuepath, cue))
2790 strcpy((cue)->audio_filename, trackname);
2791 if (start_play)
2792 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2795 #endif
2797 /* Load the codec. */
2798 if (!audio_loadcodec(start_play))
2800 /* Set filesize to zero to indicate no file was loaded. */
2801 /* tracks[track_widx].filesize = 0;
2802 tracks[track_widx].filerem = 0;
2803 close(current_fd);
2804 current_fd = -1; */
2806 if (tracks[track_widx].codecsize)
2808 /* No space for codec on buffer, not an error */
2809 tracks[track_widx].codecsize = 0;
2810 return false;
2813 /* This is an error condition, either no codec was found, or reading
2814 * the codec file failed part way through, either way, skip the track */
2815 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2816 /* We should not use gui_syncplash from audio thread! */
2817 gui_syncsplash(HZ*2, msgbuf);
2818 /* Skip invalid entry from playlist. */
2819 playlist_skip_entry(NULL, last_peek_offset);
2820 tracks[track_widx].taginfo_ready = false;
2821 goto peek_again;
2824 struct mp3entry *track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2826 /* tracks[track_widx].start_pos = 0; */
2827 set_filebuf_watermark(buffer_margin);
2828 track_id3->elapsed = 0;
2831 if (offset > 0)
2833 switch (id3.codectype) {
2834 case AFMT_MPA_L1:
2835 case AFMT_MPA_L2:
2836 case AFMT_MPA_L3:
2837 track_id3->offset = offset;
2838 audio_set_elapsed(&id3);
2839 ci.curpos = offset;
2840 break;
2842 case AFMT_WAVPACK:
2843 track_id3->offset = offset;
2844 track_id3->elapsed = id3.length / 2;
2845 ci.curpos = offset;
2846 break;
2848 case AFMT_OGG_VORBIS:
2849 case AFMT_SPEEX:
2850 case AFMT_FLAC:
2851 case AFMT_PCM_WAV:
2852 case AFMT_A52:
2853 case AFMT_AAC:
2854 case AFMT_MPC:
2855 case AFMT_APE:
2856 track_id3->offset = offset;
2857 break;
2861 logf("alt:%s", trackname);
2862 /* tracks[track_widx].buf_idx = buf_widx; */
2864 yield();
2866 return audio_read_file(rebuffer);
2869 static bool audio_read_next_metadata(void)
2871 int fd;
2872 char *trackname;
2873 int next_idx;
2874 int status;
2876 next_idx = track_widx;
2877 if (tracks[next_idx].taginfo_ready)
2879 next_idx++;
2880 next_idx &= MAX_TRACK_MASK;
2882 if (tracks[next_idx].taginfo_ready)
2883 return true;
2886 trackname = playlist_peek(last_peek_offset + 1);
2887 if (!trackname)
2888 return false;
2890 fd = open(trackname, O_RDONLY);
2891 if (fd < 0)
2892 return false;
2894 struct mp3entry id3;
2896 status = get_metadata(&id3, fd, trackname);
2897 /* Preload the glyphs in the tags */
2898 if (status)
2900 tracks[next_idx].taginfo_ready = true;
2901 if (id3.title)
2902 lcd_getstringsize(id3.title, NULL, NULL);
2903 if (id3.artist)
2904 lcd_getstringsize(id3.artist, NULL, NULL);
2905 if (id3.album)
2906 lcd_getstringsize(id3.album, NULL, NULL);
2908 close(fd);
2910 return status;
2913 /* Send callback events to notify about new tracks. */
2914 static void audio_generate_postbuffer_events(void)
2916 #if 0
2917 int cur_idx;
2918 int last_idx = -1;
2920 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2922 if (audio_have_tracks())
2924 cur_idx = track_ridx;
2926 while (1) {
2927 if (!tracks[cur_idx].event_sent)
2929 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2931 /* Mark the event 'sent' even if we don't really send one */
2932 tracks[last_idx].event_sent = true;
2933 if (track_buffer_callback)
2934 track_buffer_callback(&tracks[last_idx].id3, false);
2936 last_idx = cur_idx;
2938 if (cur_idx == track_widx)
2939 break;
2940 cur_idx++;
2941 cur_idx &= MAX_TRACK_MASK;
2944 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2946 tracks[last_idx].event_sent = true;
2947 if (track_buffer_callback)
2948 track_buffer_callback(&tracks[last_idx].id3, true);
2951 #endif
2954 static bool audio_initialize_buffer_fill(bool clear_tracks)
2956 /* Don't initialize if we're already initialized */
2957 if (filling)
2958 return true;
2960 logf("Starting buffer fill");
2962 /* Set the filling flag true before calling audio_clear_tracks as that
2963 * function can yield and we start looping. */
2964 filling = true;
2966 if (clear_tracks)
2967 audio_clear_track_entries(false);
2969 /* Save the current resume position once. */
2970 playlist_update_resume_info(audio_current_track());
2972 return true;
2975 static void audio_fill_file_buffer(
2976 bool start_play, bool rebuffer, size_t offset)
2978 bool had_next_track = audio_next_track() != NULL;
2979 bool continue_buffering;
2981 /* Must reset the buffer before use if trashed or voice only - voice
2982 file size shouldn't have changed so we can go straight from
2983 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2984 if (buffer_state != BUFFER_STATE_INITIALIZED)
2985 audio_reset_buffer();
2987 if (!audio_initialize_buffer_fill(!start_play))
2988 return ;
2990 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2992 if (!had_next_track && audio_next_track())
2993 track_changed = true;
2995 audio_read_next_metadata();
2998 static void audio_rebuffer(void)
3000 logf("Forcing rebuffer");
3002 #if 0
3003 /* Stop in progress fill, and clear open file descriptor */
3004 if (current_fd >= 0)
3006 close(current_fd);
3007 current_fd = -1;
3009 filling = false;
3011 /* Reset buffer and track pointers */
3012 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
3013 track_widx = track_ridx;
3014 audio_clear_track_entries(true);
3015 CUR_TI->available = 0;
3017 /* Fill the buffer */
3018 last_peek_offset = -1;
3019 CUR_TI->filesize = 0;
3020 CUR_TI->start_pos = 0;
3021 ci.curpos = 0;
3023 if (!CUR_TI->taginfo_ready)
3024 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
3026 audio_fill_file_buffer(false, true, 0);
3027 #endif
3030 static int audio_check_new_track(void)
3032 int track_count = audio_track_count();
3033 int old_track_ridx = track_ridx;
3034 bool forward;
3036 if (dir_skip)
3038 dir_skip = false;
3039 if (playlist_next_dir(ci.new_track))
3041 ci.new_track = 0;
3042 CUR_TI->taginfo_ready = false;
3043 audio_rebuffer();
3044 goto skip_done;
3046 else
3048 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3049 return Q_CODEC_REQUEST_FAILED;
3053 if (new_playlist)
3054 ci.new_track = 0;
3056 /* If the playlist isn't that big */
3057 if (!playlist_check(ci.new_track))
3059 if (ci.new_track >= 0)
3061 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3062 return Q_CODEC_REQUEST_FAILED;
3064 /* Find the beginning backward if the user over-skips it */
3065 while (!playlist_check(++ci.new_track))
3066 if (ci.new_track >= 0)
3068 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3069 return Q_CODEC_REQUEST_FAILED;
3072 /* Update the playlist */
3073 last_peek_offset -= ci.new_track;
3075 if (playlist_next(ci.new_track) < 0)
3077 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3078 return Q_CODEC_REQUEST_FAILED;
3081 if (new_playlist)
3083 ci.new_track = 1;
3084 new_playlist = false;
3087 /* Save the old track */
3088 /* prev_ti = CUR_TI; */
3090 /* Move to the new track */
3091 track_ridx += ci.new_track;
3092 track_ridx &= MAX_TRACK_MASK;
3094 if (automatic_skip)
3095 playlist_end = false;
3097 track_changed = !automatic_skip;
3099 /* If it is not safe to even skip this many track entries */
3100 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
3102 ci.new_track = 0;
3103 CUR_TI->taginfo_ready = false;
3104 audio_rebuffer();
3105 goto skip_done;
3108 forward = ci.new_track > 0;
3109 ci.new_track = 0;
3111 /* If the target track is clearly not in memory */
3112 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
3114 audio_rebuffer();
3115 goto skip_done;
3118 /* The track may be in memory, see if it really is */
3119 if (forward)
3121 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
3122 audio_rebuffer();
3124 else
3126 int cur_idx = track_ridx;
3127 bool taginfo_ready = true;
3128 bool wrap = track_ridx > old_track_ridx;
3130 while (1)
3132 cur_idx++;
3133 cur_idx &= MAX_TRACK_MASK;
3134 if (!(wrap || cur_idx < old_track_ridx))
3135 break;
3137 /* If we hit a track in between without valid tag info, bail */
3138 if (!tracks[cur_idx].taginfo_ready)
3140 taginfo_ready = false;
3141 break;
3144 tracks[cur_idx].available = tracks[cur_idx].filesize;
3145 if (tracks[cur_idx].codecsize)
3146 tracks[cur_idx].has_codec = true;*/
3148 if (taginfo_ready)
3150 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
3151 audio_rebuffer();
3153 else
3155 CUR_TI->taginfo_ready = false;
3156 audio_rebuffer();
3160 skip_done:
3161 audio_update_trackinfo();
3162 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3163 return Q_CODEC_REQUEST_COMPLETE;
3166 static int audio_rebuffer_and_seek(size_t newpos)
3168 #if 0
3169 size_t real_preseek;
3170 int fd;
3171 char *trackname;
3173 /* (Re-)open current track's file handle. */
3174 trackname = playlist_peek(0);
3175 fd = open(trackname, O_RDONLY);
3176 if (fd < 0)
3178 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
3179 return Q_CODEC_REQUEST_FAILED;
3182 if (current_fd >= 0)
3183 close(current_fd);
3184 current_fd = fd;
3186 playlist_end = false;
3188 ci.curpos = newpos;
3190 /* Clear codec buffer. */
3191 track_widx = track_ridx;
3192 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
3194 last_peek_offset = 0;
3195 filling = false;
3196 audio_initialize_buffer_fill(true);
3198 /* This may have been tweaked by the id3v1 code */
3199 CUR_TI->filesize=filesize(fd);
3200 if (newpos > conf_preseek)
3202 CUR_TI->start_pos = newpos - conf_preseek;
3203 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
3204 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
3205 real_preseek = conf_preseek;
3207 else
3209 CUR_TI->start_pos = 0;
3210 CUR_TI->filerem = CUR_TI->filesize;
3211 real_preseek = newpos;
3214 CUR_TI->available = 0;
3216 audio_read_file(real_preseek);
3218 /* Account for the data we just read that is 'behind' us now */
3219 CUR_TI->available -= real_preseek;
3221 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
3223 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
3224 return Q_CODEC_REQUEST_COMPLETE;
3225 #endif
3228 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
3229 bool last_track))
3231 track_buffer_callback = handler;
3234 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
3235 bool last_track))
3237 track_unbuffer_callback = handler;
3240 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
3242 track_changed_callback = handler;
3245 unsigned long audio_prev_elapsed(void)
3247 return prev_track_elapsed;
3250 static void audio_stop_codec_flush(void)
3252 ci.stop_codec = true;
3253 pcmbuf_pause(true);
3255 while (audio_codec_loaded)
3256 yield();
3258 /* If the audio codec is not loaded any more, and the audio is still
3259 * playing, it is now and _only_ now safe to call this function from the
3260 * audio thread */
3261 if (pcm_is_playing())
3262 pcmbuf_play_stop();
3263 pcmbuf_pause(paused);
3266 static void audio_stop_playback(void)
3268 /* If we were playing, save resume information */
3269 if (playing)
3271 struct mp3entry *id3 = NULL;
3273 if (!playlist_end || !ci.stop_codec)
3275 /* Set this early, the outside code yields and may allow the codec
3276 to try to wait for a reply on a buffer wait */
3277 ci.stop_codec = true;
3278 id3 = audio_current_track();
3281 /* Save the current playing spot, or NULL if the playlist has ended */
3282 playlist_update_resume_info(id3);
3284 prev_track_elapsed = curtrack_id3.elapsed;
3286 /* Increment index so runtime info is saved in audio_clear_track_entries().
3287 * Done here, as audio_stop_playback() may be called more than once.
3288 * Don't update runtime unless playback is stopped because of end of playlist.
3289 * Updating runtime when manually stopping a tracks, can destroy autoscores
3290 * and playcounts.
3292 if (playlist_end)
3294 track_ridx++;
3295 track_ridx &= MAX_TRACK_MASK;
3299 filling = false;
3300 paused = false;
3301 audio_stop_codec_flush();
3302 playing = false;
3304 /* Mark all entries null. */
3305 audio_clear_track_entries(false);
3308 static void audio_play_start(size_t offset)
3310 #if INPUT_SRC_CAPS != 0
3311 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3312 audio_set_output_source(AUDIO_SRC_PLAYBACK);
3313 #endif
3315 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3316 paused = false;
3317 audio_stop_codec_flush();
3319 track_changed = true;
3320 playlist_end = false;
3322 playing = true;
3324 ci.new_track = 0;
3325 ci.seek_time = 0;
3326 wps_offset = 0;
3328 sound_set_volume(global_settings.volume);
3329 track_widx = track_ridx = 0;
3331 /* Mark all entries null. */
3332 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3334 last_peek_offset = -1;
3336 /* Officially playing */
3337 queue_reply(&audio_queue, 1);
3339 audio_fill_file_buffer(true, false, offset);
3341 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
3342 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
3346 /* Invalidates all but currently playing track. */
3347 static void audio_invalidate_tracks(void)
3349 #if 0
3350 if (audio_have_tracks())
3352 last_peek_offset = 0;
3353 playlist_end = false;
3354 track_widx = track_ridx;
3356 /* Mark all other entries null (also buffered wrong metadata). */
3357 audio_clear_track_entries(true);
3359 /* If the current track is fully buffered, advance the write pointer */
3360 if (tracks[track_widx].filerem == 0)
3361 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3363 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3365 audio_read_next_metadata();
3367 #endif
3370 static void audio_new_playlist(void)
3372 /* Prepare to start a new fill from the beginning of the playlist */
3373 last_peek_offset = -1;
3374 if (audio_have_tracks())
3376 if (paused)
3377 skipped_during_pause = true;
3378 playlist_end = false;
3379 track_widx = track_ridx;
3380 audio_clear_track_entries(true);
3382 track_widx++;
3383 track_widx &= MAX_TRACK_MASK;
3385 /* Mark the current track as invalid to prevent skipping back to it */
3386 CUR_TI->taginfo_ready = false;
3389 /* Signal the codec to initiate a track change forward */
3390 new_playlist = true;
3391 ci.new_track = 1;
3393 /* Officially playing */
3394 queue_reply(&audio_queue, 1);
3396 audio_fill_file_buffer(false, true, 0);
3399 static void audio_initiate_track_change(long direction)
3401 playlist_end = false;
3402 ci.new_track += direction;
3403 wps_offset -= direction;
3404 if (paused)
3405 skipped_during_pause = true;
3408 static void audio_initiate_dir_change(long direction)
3410 playlist_end = false;
3411 dir_skip = true;
3412 ci.new_track = direction;
3413 if (paused)
3414 skipped_during_pause = true;
3418 * Layout audio buffer as follows - iram buffer depends on target:
3419 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3421 static void audio_reset_buffer(void)
3423 /* see audio_get_recording_buffer if this is modified */
3424 logf("audio_reset_buffer");
3426 /* If the setup of anything allocated before the file buffer is
3427 changed, do check the adjustments after the buffer_alloc call
3428 as it will likely be affected and need sliding over */
3430 /* Initially set up file buffer as all space available */
3431 malloc_buf = audiobuf + talk_get_bufsize();
3432 /* Align the malloc buf to line size. Especially important to cf
3433 targets that do line reads/writes. */
3434 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3435 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3436 filebuflen = audiobufend - filebuf;
3438 /* Allow for codec swap space at end of audio buffer */
3439 if (talk_voice_required())
3441 /* Layout of swap buffer:
3442 * #ifdef IRAM_STEAL (dedicated iram_buf):
3443 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3444 * #else:
3445 * audiobuf...|dram_buf|iram_buf|audiobufend
3447 #ifdef PLAYBACK_VOICE
3448 /* Check for an absolutely nasty situation which should never,
3449 ever happen - frankly should just panic */
3450 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3452 logf("buffer reset with voice swapped");
3454 /* line align length which line aligns the calculations below since
3455 all sizes are also at least line aligned - needed for memswap128 */
3456 filebuflen &= ~15;
3457 #ifdef IRAM_STEAL
3458 filebuflen -= CODEC_SIZE;
3459 #else
3460 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3461 #endif
3462 /* Allocate buffers for swapping voice <=> audio */
3463 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3464 and out of the way of buffer usage or else a call to audio_get_buffer
3465 and subsequent buffer use might trash the swap space. A plugin
3466 initializing IRAM after getting the full buffer would present similar
3467 problem. Options include: failing the request if the other buffer
3468 has been obtained already or never allowing use of the voice IRAM
3469 buffer within the audio buffer. Using buffer_alloc basically
3470 implements the second in a more convenient way. */
3471 dram_buf = filebuf + filebuflen;
3473 #ifdef IRAM_STEAL
3474 /* Allocate voice IRAM swap buffer once */
3475 if (iram_buf == NULL)
3477 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3478 /* buffer_alloc moves audiobuf; this is safe because only the end
3479 * has been touched so far in this function and the address of
3480 * filebuf + filebuflen is not changed */
3481 malloc_buf += CODEC_IRAM_SIZE;
3482 filebuf += CODEC_IRAM_SIZE;
3483 filebuflen -= CODEC_IRAM_SIZE;
3485 #else
3486 /* Allocate iram_buf after dram_buf */
3487 iram_buf = dram_buf + CODEC_SIZE;
3488 #endif /* IRAM_STEAL */
3489 #endif /* PLAYBACK_VOICE */
3491 else
3493 #ifdef PLAYBACK_VOICE
3494 /* No swap buffers needed */
3495 iram_buf = NULL;
3496 dram_buf = NULL;
3497 #endif
3500 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3501 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3503 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3504 will already be line aligned */
3505 filebuflen &= ~3;
3507 /* Set the high watermark as 75% full...or 25% empty :) */
3508 #if MEM > 8
3509 high_watermark = 3*filebuflen / 4;
3510 #endif
3512 /* Clear any references to the file buffer */
3513 buffer_state = BUFFER_STATE_INITIALIZED;
3515 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3516 /* Make sure everything adds up - yes, some info is a bit redundant but
3517 aids viewing and the sumation of certain variables should add up to
3518 the location of others. */
3520 size_t pcmbufsize;
3521 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3522 logf("mabuf: %08X", (unsigned)malloc_buf);
3523 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3524 logf("fbuf: %08X", (unsigned)filebuf);
3525 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3526 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3527 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3528 logf("pcmb: %08X", (unsigned)pcmbuf);
3529 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3530 if (dram_buf)
3532 logf("dramb: %08X", (unsigned)dram_buf);
3533 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3535 if (iram_buf)
3537 logf("iramb: %08X", (unsigned)iram_buf);
3538 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3541 #endif
3544 #if MEM > 8
3545 /* we dont want this rebuffering on targets with little ram
3546 because the disk may never spin down */
3547 static bool ata_fillbuffer_callback(void)
3549 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
3550 return true;
3552 #endif
3554 static void audio_thread(void)
3556 struct queue_event ev;
3558 pcm_postinit();
3560 #ifdef PLAYBACK_VOICE
3561 /* Unlock semaphore that init stage locks before creating this thread */
3562 semaphore_release(&sem_codecthread);
3564 /* Buffers must be set up by now - should panic - really */
3565 if (buffer_state != BUFFER_STATE_INITIALIZED)
3567 logf("audio_thread start: no buffer");
3570 /* Have to wait for voice to load up or else the codec swap will be
3571 invalid when an audio codec is loaded */
3572 wait_for_voice_swap_in();
3573 #endif
3575 while (1)
3577 if (filling)
3579 queue_wait_w_tmo(&audio_queue, &ev, 0);
3580 if (ev.id == SYS_TIMEOUT)
3581 ev.id = Q_AUDIO_FILL_BUFFER;
3583 else
3585 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3586 #if MEM > 8
3587 if (playing && (ev.id == SYS_TIMEOUT) &&
3588 (bufused() < high_watermark))
3589 register_ata_idle_func(ata_fillbuffer_callback);
3590 #endif
3593 switch (ev.id) {
3594 #if 0
3595 #if MEM > 8
3596 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA:
3597 /* only fill if the disk is still spining */
3598 #ifndef SIMULATOR
3599 if (!ata_disk_is_active())
3600 break;
3601 #endif
3602 #endif /* MEM > 8 */
3603 /* else fall through to Q_AUDIO_FILL_BUFFER */
3604 case Q_AUDIO_FILL_BUFFER:
3605 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3606 if (!filling)
3607 if (!playing || playlist_end || ci.stop_codec)
3608 break;
3609 audio_fill_file_buffer(false, false, 0);
3610 break;
3611 #endif
3613 case Q_AUDIO_PLAY:
3614 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3615 if (playing && ev.data <= 0)
3616 audio_new_playlist();
3617 else
3619 audio_stop_playback();
3620 audio_play_start((size_t)ev.data);
3622 break;
3624 case Q_AUDIO_STOP:
3625 LOGFQUEUE("audio < Q_AUDIO_STOP");
3626 if (playing)
3627 audio_stop_playback();
3628 if (ev.data != 0)
3629 queue_clear(&audio_queue);
3630 break;
3632 case Q_AUDIO_PAUSE:
3633 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3634 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3635 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3636 skipped_during_pause = false;
3637 if (!playing)
3638 break;
3639 pcmbuf_pause((bool)ev.data);
3640 paused = (bool)ev.data;
3641 break;
3643 case Q_AUDIO_SKIP:
3644 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3645 audio_initiate_track_change((long)ev.data);
3646 break;
3648 case Q_AUDIO_PRE_FF_REWIND:
3649 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3650 if (!playing)
3651 break;
3652 pcmbuf_pause(true);
3653 break;
3655 case Q_AUDIO_FF_REWIND:
3656 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3657 if (!playing)
3658 break;
3659 ci.seek_time = (long)ev.data+1;
3660 break;
3662 case Q_AUDIO_REBUFFER_SEEK:
3663 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3664 queue_reply(&audio_queue, audio_rebuffer_and_seek(ev.data));
3665 break;
3667 case Q_AUDIO_CHECK_NEW_TRACK:
3668 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3669 queue_reply(&audio_queue, audio_check_new_track());
3670 break;
3672 case Q_AUDIO_DIR_SKIP:
3673 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3674 playlist_end = false;
3675 audio_initiate_dir_change(ev.data);
3676 break;
3678 case Q_AUDIO_FLUSH:
3679 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3680 audio_invalidate_tracks();
3681 break;
3683 case Q_AUDIO_TRACK_CHANGED:
3684 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3685 if (track_changed_callback)
3686 track_changed_callback(&curtrack_id3);
3687 track_changed = true;
3688 playlist_update_resume_info(audio_current_track());
3689 break;
3691 #ifndef SIMULATOR
3692 case SYS_USB_CONNECTED:
3693 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3694 if (playing)
3695 audio_stop_playback();
3696 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3697 usb_wait_for_disconnect(&audio_queue);
3698 break;
3699 #endif
3701 case SYS_TIMEOUT:
3702 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3703 break;
3705 default:
3706 LOGFQUEUE("audio < default");
3707 } /* end switch */
3708 } /* end while */
3711 #ifdef ROCKBOX_HAS_LOGF
3712 static void audio_test_track_changed_event(struct mp3entry *id3)
3714 (void)id3;
3716 logf("tce:%s", id3->path);
3718 #endif
3720 /* Initialize the audio system - called from init() in main.c.
3721 * Last function because of all the references to internal symbols
3723 void audio_init(void)
3725 #ifdef PLAYBACK_VOICE
3726 static bool voicetagtrue = true;
3727 static struct mp3entry id3_voice;
3728 struct thread_entry *voice_thread_p = NULL;
3729 #endif
3730 struct thread_entry *audio_thread_p;
3732 /* Can never do this twice */
3733 if (audio_is_initialized)
3735 logf("audio: already initialized");
3736 return;
3739 logf("audio: initializing");
3741 /* Initialize queues before giving control elsewhere in case it likes
3742 to send messages. Thread creation will be delayed however so nothing
3743 starts running until ready if something yields such as talk_init. */
3744 #ifdef PLAYBACK_VOICE
3745 /* Take ownership of lock to prevent playback of anything before audio
3746 hardware is initialized - audio thread unlocks it after final init
3747 stage */
3748 semaphore_init(&sem_codecthread, 1, 0);
3749 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3750 #endif
3751 queue_init(&audio_queue, true);
3752 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3753 queue_init(&codec_queue, true);
3755 pcm_init();
3757 #ifdef ROCKBOX_HAS_LOGF
3758 audio_set_track_changed_event(audio_test_track_changed_event);
3759 #endif
3761 /* Initialize codec api. */
3762 ci.read_filebuf = codec_filebuf_callback;
3763 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3764 ci.get_codec_memory = codec_get_memory_callback;
3765 ci.request_buffer = codec_request_buffer_callback;
3766 ci.advance_buffer = codec_advance_buffer_callback;
3767 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3768 ci.request_next_track = codec_request_next_track_callback;
3769 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3770 ci.seek_buffer = codec_seek_buffer_callback;
3771 ci.seek_complete = codec_seek_complete_callback;
3772 ci.set_elapsed = codec_set_elapsed_callback;
3773 ci.set_offset = codec_set_offset_callback;
3774 ci.configure = codec_configure_callback;
3775 ci.discard_codec = codec_discard_codec_callback;
3777 /* Initialize voice codec api. */
3778 #ifdef PLAYBACK_VOICE
3779 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3780 memset(&id3_voice, 0, sizeof(id3_voice));
3781 ci_voice.read_filebuf = voice_filebuf_callback;
3782 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3783 ci_voice.get_codec_memory = voice_get_memory_callback;
3784 ci_voice.request_buffer = voice_request_buffer_callback;
3785 ci_voice.advance_buffer = voice_advance_buffer_callback;
3786 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3787 ci_voice.request_next_track = voice_request_next_track_callback;
3788 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3789 ci_voice.seek_buffer = voice_seek_buffer_callback;
3790 ci_voice.seek_complete = voice_do_nothing;
3791 ci_voice.set_elapsed = voice_set_elapsed_callback;
3792 ci_voice.set_offset = voice_set_offset_callback;
3793 ci_voice.configure = voice_configure_callback;
3794 ci_voice.discard_codec = voice_do_nothing;
3795 ci_voice.taginfo_ready = &voicetagtrue;
3796 ci_voice.id3 = &id3_voice;
3797 id3_voice.frequency = 11200;
3798 id3_voice.length = 1000000L;
3799 #endif
3801 /* initialize the buffer */
3802 filebuf = audiobuf;
3804 /* audio_reset_buffer must to know the size of voice buffer so init
3805 talk first */
3806 talk_init();
3808 codec_thread_p = create_thread(
3809 codec_thread, codec_stack, sizeof(codec_stack),
3810 CREATE_THREAD_FROZEN,
3811 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3812 IF_COP(, CPU));
3814 audio_thread_p = create_thread(audio_thread, audio_stack,
3815 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3816 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3817 IF_COP(, CPU));
3819 buffering_thread_p = create_thread( buffering_thread, buffering_stack,
3820 sizeof(buffering_stack), CREATE_THREAD_FROZEN,
3821 buffering_thread_name IF_PRIO(, PRIORITY_BUFFERING)
3822 IF_COP(, CPU, true));
3824 #ifdef PLAYBACK_VOICE
3825 /* TODO: Change this around when various speech codecs can be used */
3826 if (talk_voice_required())
3828 logf("Starting voice codec");
3829 queue_init(&voice_queue, true);
3830 voice_thread_p = create_thread(voice_thread, voice_stack,
3831 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3832 voice_thread_name
3833 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3835 #endif
3837 /* Set crossfade setting for next buffer init which should be about... */
3838 pcmbuf_crossfade_enable(global_settings.crossfade);
3840 /* ...now! Set up the buffers */
3841 audio_reset_buffer();
3843 buffering_init(filebuf, filebuflen);
3845 /* Probably safe to say */
3846 audio_is_initialized = true;
3848 sound_settings_apply();
3849 #ifdef HAVE_WM8758
3850 eq_hw_enable(global_settings.eq_hw_enabled);
3851 #endif
3852 #ifndef HAVE_FLASH_STORAGE
3853 audio_set_buffer_margin(global_settings.buffer_margin);
3854 #endif
3856 /* it's safe to let the threads run now */
3857 thread_thaw(codec_thread_p);
3858 #ifdef PLAYBACK_VOICE
3859 if (voice_thread_p)
3860 thread_thaw(voice_thread_p);
3861 #endif
3862 thread_thaw(audio_thread_p);
3863 thread_thaw(buffering_thread_p);
3864 } /* audio_init */