Revert to calling playlist_next() in check_new_track() as in SVN.
[Rockbox.git] / apps / playback.c
blobeb81f0b6a54298e4be87251743c3687fe7741cc3
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 /* amount of guess-space to allow for codecs that must hunt and peck
96 * for their correct seeek target, 32k seems a good size */
97 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
99 /* Define LOGF_ENABLE to enable logf output in this file */
100 #define LOGF_ENABLE
101 #include "logf.h"
103 /* macros to enable logf for queues
104 logging on SYS_TIMEOUT can be disabled */
105 #ifdef SIMULATOR
106 /* Define this for logf output of all queuing except SYS_TIMEOUT */
107 #define PLAYBACK_LOGQUEUES
108 /* Define this to logf SYS_TIMEOUT messages */
109 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
110 #endif
112 #ifdef PLAYBACK_LOGQUEUES
113 #define LOGFQUEUE logf
114 #else
115 #define LOGFQUEUE(...)
116 #endif
118 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
119 #define LOGFQUEUE_SYS_TIMEOUT logf
120 #else
121 #define LOGFQUEUE_SYS_TIMEOUT(...)
122 #endif
125 /* Define one constant that includes recording related functionality */
126 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
127 #define AUDIO_HAVE_RECORDING
128 #endif
130 enum {
131 Q_AUDIO_PLAY = 1,
132 Q_AUDIO_STOP,
133 Q_AUDIO_PAUSE,
134 Q_AUDIO_SKIP,
135 Q_AUDIO_PRE_FF_REWIND,
136 Q_AUDIO_FF_REWIND,
137 Q_AUDIO_CHECK_NEW_TRACK,
138 Q_AUDIO_FLUSH,
139 Q_AUDIO_TRACK_CHANGED,
140 Q_AUDIO_DIR_SKIP,
141 Q_AUDIO_POSTINIT,
142 Q_AUDIO_FILL_BUFFER,
143 Q_CODEC_REQUEST_COMPLETE,
144 Q_CODEC_REQUEST_FAILED,
146 Q_VOICE_PLAY,
147 Q_VOICE_STOP,
149 Q_CODEC_LOAD,
150 Q_CODEC_LOAD_DISK,
152 #ifdef AUDIO_HAVE_RECORDING
153 Q_ENCODER_LOAD_DISK,
154 Q_ENCODER_RECORD,
155 #endif
158 /* As defined in plugins/lib/xxx2wav.h */
159 #if MEM > 1
160 #define MALLOC_BUFSIZE (512*1024)
161 #define GUARD_BUFSIZE (32*1024)
162 #else
163 #define MALLOC_BUFSIZE (100*1024)
164 #define GUARD_BUFSIZE (8*1024)
165 #endif
167 /* As defined in plugin.lds */
168 #if defined(CPU_PP)
169 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
170 #define CODEC_IRAM_SIZE ((size_t)0xc000)
171 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
172 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
173 #define CODEC_IRAM_SIZE ((size_t)0x10000)
174 #else
175 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
176 #define CODEC_IRAM_SIZE ((size_t)0xc000)
177 #endif
179 #ifndef IBSS_ATTR_VOICE_STACK
180 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
181 #endif
183 bool audio_is_initialized = false;
185 /* Variables are commented with the threads that use them: *
186 * A=audio, C=codec, V=voice. A suffix of - indicates that *
187 * the variable is read but not updated on that thread. */
188 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
190 /* Main state control */
191 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
192 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
193 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
195 /* Ring buffer where compressed audio and codecs are loaded */
196 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
197 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
198 /* FIXME: make filebuflen static */
199 size_t filebuflen = 0; /* Size of buffer (A/C-) */
200 /* FIXME: make buf_ridx (C/A-) */
202 /* Possible arrangements of the buffer */
203 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
204 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
205 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
206 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
208 static struct mp3entry prevtrack_id3;
209 static struct mp3entry curtrack_id3;
210 static struct mp3entry nexttrack_id3;
212 /* Track info structure about songs in the file buffer (A/C-) */
213 struct track_info {
214 int audio_hid; /* The ID for the track's buffer handle */
215 int id3_hid; /* The ID for the track's metadata handle */
216 int codec_hid; /* The ID for the track's codec handle */
218 size_t codecsize; /* Codec length in bytes */
219 size_t filesize; /* File total length */
221 bool taginfo_ready; /* Is metadata read */
223 bool event_sent; /* Was this track's buffered event sent */
226 static struct track_info tracks[MAX_TRACK];
227 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
228 static int track_widx = 0; /* Track being buffered (A) */
230 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
232 /* Set by the audio thread when the current track information has updated
233 * and the WPS may need to update its cached information */
234 static bool track_changed = false;
236 /* Information used only for filling the buffer */
237 /* Playlist steps from playing track to next track to be buffered (A) */
238 static int last_peek_offset = 0;
240 /* Scrobbler support */
241 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
243 /* Track change controls */
244 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
245 static bool playlist_end = false; /* Has the current playlist ended? (A) */
246 static bool dir_skip = false; /* Is a directory skip pending? (A) */
247 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
248 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
249 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
251 /* Callbacks which applications or plugins may set */
252 /* When the playing track has changed from the user's perspective */
253 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
254 /* When a track has been buffered */
255 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
256 /* When a track's buffer has been overwritten or cleared */
257 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track) = NULL;
259 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
261 /* Multiple threads */
262 static void set_current_codec(int codec_idx);
263 /* Set the watermark to trigger buffer fill (A/C) FIXME */
264 static void set_filebuf_watermark(int seconds, size_t max);
266 /* Audio thread */
267 static struct event_queue audio_queue NOCACHEBSS_ATTR;
268 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
269 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
270 static const char audio_thread_name[] = "audio";
272 static void audio_thread(void);
273 static void audio_initiate_track_change(long direction);
274 static bool audio_have_tracks(void);
275 static void audio_reset_buffer(void);
277 /* Codec thread */
278 extern struct codec_api ci;
279 static struct event_queue codec_queue NOCACHEBSS_ATTR;
280 static struct queue_sender_list codec_queue_sender_list;
281 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
282 IBSS_ATTR;
283 static const char codec_thread_name[] = "codec";
284 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
286 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
288 /* Voice thread */
289 #ifdef PLAYBACK_VOICE
291 extern struct codec_api ci_voice;
293 static struct thread_entry *voice_thread_p = NULL;
294 static struct event_queue voice_queue NOCACHEBSS_ATTR;
295 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
296 IBSS_ATTR_VOICE_STACK;
297 static const char voice_thread_name[] = "voice codec";
299 /* Voice codec swapping control */
300 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
302 #ifdef SIMULATOR
303 /* IRAM codec swap buffer for sim*/
304 static unsigned char sim_iram[CODEC_IRAM_SIZE];
305 #undef CODEC_IRAM_ORIGIN
306 #define CODEC_IRAM_ORIGIN sim_iram
307 #endif
309 /* iram_buf and dram_buf are either both NULL or both non-NULL */
310 /* Pointer to IRAM buffer for codec swapping */
311 static unsigned char *iram_buf = NULL;
312 /* Pointer to DRAM buffer for codec swapping */
313 static unsigned char *dram_buf = NULL;
314 /* Parity of swap_codec calls - needed because one codec swapping itself in
315 automatically swaps in the other and the swap when unlocking should not
316 happen if the parity is even.
318 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
319 /* Locking to control which codec (normal/voice) is running */
320 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
321 static struct event event_codecthread NOCACHEBSS_ATTR;
323 /* Voice state */
324 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
325 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
326 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
327 static unsigned char *voicebuf = NULL;
328 static size_t voice_remaining = 0;
330 #ifdef IRAM_STEAL
331 /* Voice IRAM has been stolen for other use */
332 static bool voice_iram_stolen = false;
333 #endif
335 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
337 struct voice_info {
338 void (*callback)(unsigned char **start, size_t* size);
339 size_t size;
340 unsigned char *buf;
342 static void voice_thread(void);
343 static void voice_stop(void);
345 #endif /* PLAYBACK_VOICE */
348 /* --- Helper functions --- */
350 struct mp3entry *bufgetid3(int handle_id)
352 if (handle_id < 0)
353 return NULL;
355 struct mp3entry *id3;
356 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
358 if (ret < 0 || ret != sizeof(struct mp3entry))
359 return NULL;
361 return id3;
364 void *bufgetcodec(struct track_info *track)
366 void *ptr;
367 ssize_t ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
369 if (ret == -2) {
370 buf_request_buffer_handle(CUR_TI->audio_hid);
373 while (ret == -2) {
374 sleep(1);
375 ret = bufgetdata(track->codec_hid, track->codecsize, &ptr);
378 if (ret < 0)
379 return NULL;
380 else
381 return ptr;
384 bool clear_track_info(struct track_info *track)
386 if (!track)
387 return false;
389 if (track->codec_hid > 0) {
390 if (bufclose(track->codec_hid))
391 track->codec_hid = 0;
392 else
393 return false;
396 if (track->id3_hid > 0) {
397 if (bufclose(track->id3_hid))
398 track->id3_hid = 0;
399 else
400 return false;
403 if (track->audio_hid > 0) {
404 if (bufclose(track->audio_hid))
405 track->audio_hid = 0;
406 else
407 return false;
410 memset(track, 0, sizeof(struct track_info));
411 return true;
414 /* --- External interfaces --- */
416 void mp3_play_data(const unsigned char* start, int size,
417 void (*get_more)(unsigned char** start, size_t* size))
419 #ifdef PLAYBACK_VOICE
420 static struct voice_info voice_clip;
421 voice_clip.callback = get_more;
422 voice_clip.buf = (unsigned char*)start;
423 voice_clip.size = size;
424 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
425 queue_post(&voice_queue, Q_VOICE_STOP, 0);
426 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
427 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
428 voice_thread_start = true;
429 trigger_cpu_boost();
430 #else
431 (void) start;
432 (void) size;
433 (void) get_more;
434 #endif
437 void mp3_play_stop(void)
439 #ifdef PLAYBACK_VOICE
440 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
441 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
442 queue_post(&voice_queue, Q_VOICE_STOP, 1);
443 #endif
446 void mp3_play_pause(bool play)
448 /* a dummy */
449 (void)play;
452 bool mp3_is_playing(void)
454 #ifdef PLAYBACK_VOICE
455 return voice_is_playing;
456 #else
457 return false;
458 #endif
461 /* If voice could be swapped out - wait for it to return
462 * Used by buffer claming functions.
464 static void wait_for_voice_swap_in(void)
466 #ifdef PLAYBACK_VOICE
467 if (NULL == iram_buf)
468 return;
470 event_wait(&event_codecthread, STATE_NONSIGNALED);
471 #endif /* PLAYBACK_VOICE */
474 /* This sends a stop message and the audio thread will dump all it's
475 subsequenct messages */
476 static void audio_hard_stop(void)
478 /* Stop playback */
479 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
480 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
483 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
485 unsigned char *buf, *end;
487 if (audio_is_initialized)
489 audio_hard_stop();
490 wait_for_voice_swap_in();
491 #ifdef PLAYBACK_VOICE
492 voice_stop();
493 #endif
495 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
497 if (buffer_size == NULL)
499 /* Special case for talk_init to use since it already knows it's
500 trashed */
501 buffer_state = BUFFER_STATE_TRASHED;
502 return NULL;
505 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
506 || !talk_voice_required())
508 logf("get buffer: talk, audio");
509 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
510 the talk buffer is not needed because voice isn't being used, or
511 could be BUFFER_STATE_TRASHED already. If state is
512 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
513 without the caller knowing what's going on. Changing certain settings
514 may move it to a worse condition but the memory in use by something
515 else will remain undisturbed.
517 if (buffer_state != BUFFER_STATE_TRASHED)
519 talk_buffer_steal();
520 buffer_state = BUFFER_STATE_TRASHED;
523 buf = audiobuf;
524 end = audiobufend;
526 else
528 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
529 still BUFFER_STATE_INITIALIZED */
530 /* Skip talk buffer and move pcm buffer to end to maximize available
531 contiguous memory - no audio running means voice will not need the
532 swap space */
533 logf("get buffer: audio");
534 buf = audiobuf + talk_get_bufsize();
535 end = audiobufend - pcmbuf_init(audiobufend);
536 buffer_state = BUFFER_STATE_VOICED_ONLY;
539 *buffer_size = end - buf;
541 return buf;
544 #ifdef IRAM_STEAL
545 void audio_iram_steal(void)
547 /* We need to stop audio playback in order to use codec IRAM */
548 audio_hard_stop();
550 #ifdef PLAYBACK_VOICE
551 if (NULL != iram_buf)
553 /* Can't already be stolen */
554 if (voice_iram_stolen)
555 return;
557 /* Must wait for voice to be current again if it is swapped which
558 would cause the caller's buffer to get clobbered when voice locks
559 and runs - we'll wait for it to lock and yield again then make sure
560 the ride has come to a complete stop */
561 wait_for_voice_swap_in();
562 voice_stop();
564 /* Save voice IRAM but just memcpy - safe to do here since voice
565 is current and no audio codec is loaded */
566 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
567 voice_iram_stolen = true;
569 else
571 /* Nothing much to do if no voice */
572 voice_iram_stolen = false;
574 #endif
576 #endif /* IRAM_STEAL */
578 #ifdef HAVE_RECORDING
579 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
581 /* Don't allow overwrite of voice swap area or we'll trash the
582 swapped-out voice codec but can use whole thing if none */
583 unsigned char *end;
585 /* Stop audio and voice. Wait for voice to swap in and be clear
586 of pending events to ensure trouble-free operation of encoders */
587 audio_hard_stop();
588 wait_for_voice_swap_in();
589 #ifdef PLAYBACK_VOICE
590 voice_stop();
591 #endif
592 talk_buffer_steal();
594 #ifdef PLAYBACK_VOICE
595 /* If no dram_buf, swap space not used and recording gets more
596 memory. Codec swap areas will remain unaffected by the next init
597 since they're allocated at the end of the buffer and their sizes
598 don't change between calls */
599 end = dram_buf;
600 if (NULL == end)
601 #endif /* PLAYBACK_VOICE */
602 end = audiobufend;
604 buffer_state = BUFFER_STATE_TRASHED;
606 *buffer_size = end - audiobuf;
608 return (unsigned char *)audiobuf;
611 bool audio_load_encoder(int afmt)
613 #ifndef SIMULATOR
614 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
615 if (!enc_fn)
616 return false;
618 audio_remove_encoder();
619 ci.enc_codec_loaded = 0; /* clear any previous error condition */
621 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
622 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
624 while (ci.enc_codec_loaded == 0)
625 yield();
627 logf("codec loaded: %d", ci.enc_codec_loaded);
629 return ci.enc_codec_loaded > 0;
630 #else
631 (void)afmt;
632 return true;
633 #endif
634 } /* audio_load_encoder */
636 void audio_remove_encoder(void)
638 #ifndef SIMULATOR
639 /* force encoder codec unload (if currently loaded) */
640 if (ci.enc_codec_loaded <= 0)
641 return;
643 ci.stop_encoder = true;
644 while (ci.enc_codec_loaded > 0)
645 yield();
646 #endif
647 } /* audio_remove_encoder */
649 #endif /* HAVE_RECORDING */
651 struct mp3entry* audio_current_track(void)
653 const char *filename;
654 const char *p;
655 static struct mp3entry temp_id3;
656 int cur_idx;
657 int offset = ci.new_track + wps_offset;
659 cur_idx = track_ridx + offset;
660 cur_idx &= MAX_TRACK_MASK;
662 if (cur_idx == track_ridx && *curtrack_id3.path)
663 return &curtrack_id3;
664 else if (offset == -1 && *prevtrack_id3.path)
665 return &prevtrack_id3;
666 else if (tracks[cur_idx].id3_hid > 0)
667 return bufgetid3(tracks[cur_idx].id3_hid);
669 memset(&temp_id3, 0, sizeof(struct mp3entry));
671 filename = playlist_peek(0);
672 if (!filename)
673 filename = "No file!";
675 #ifdef HAVE_TC_RAMCACHE
676 if (tagcache_fill_tags(&temp_id3, filename))
677 return &temp_id3;
678 #endif
680 p = strrchr(filename, '/');
681 if (!p)
682 p = filename;
683 else
684 p++;
686 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
687 temp_id3.title = &temp_id3.path[0];
689 return &temp_id3;
692 struct mp3entry* audio_next_track(void)
694 int next_idx = track_ridx;
696 if (!audio_have_tracks())
697 return NULL;
699 if (wps_offset == -1 && *prevtrack_id3.path)
700 return &curtrack_id3;
702 next_idx++;
703 next_idx &= MAX_TRACK_MASK;
705 if (tracks[next_idx].id3_hid <= 0)
706 return NULL;
708 return &nexttrack_id3;
711 bool audio_has_changed_track(void)
713 if (track_changed)
715 track_changed = false;
716 return true;
719 return false;
722 void audio_play(long offset)
724 logf("audio_play");
726 #ifdef PLAYBACK_VOICE
727 /* Truncate any existing voice output so we don't have spelling
728 * etc. over the first part of the played track */
729 talk_force_shutup();
730 #endif
732 /* Start playback */
733 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
734 /* Don't return until playback has actually started */
735 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
738 void audio_stop(void)
740 /* Stop playback */
741 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
742 /* Don't return until playback has actually stopped */
743 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
746 void audio_pause(void)
748 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
749 /* Don't return until playback has actually paused */
750 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
753 void audio_resume(void)
755 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
756 /* Don't return until playback has actually resumed */
757 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
760 void audio_next(void)
762 if (playlist_check(ci.new_track + wps_offset + 1))
764 if (global_settings.beep)
765 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
767 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
768 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
769 /* Update wps while our message travels inside deep playback queues. */
770 wps_offset++;
771 track_changed = true;
773 else
775 /* No more tracks. */
776 if (global_settings.beep)
777 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
781 void audio_prev(void)
783 if (playlist_check(ci.new_track + wps_offset - 1))
785 if (global_settings.beep)
786 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
788 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
789 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
790 /* Update wps while our message travels inside deep playback queues. */
791 wps_offset--;
792 track_changed = true;
794 else
796 /* No more tracks. */
797 if (global_settings.beep)
798 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
802 void audio_next_dir(void)
804 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
805 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
808 void audio_prev_dir(void)
810 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
811 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
814 void audio_pre_ff_rewind(void)
816 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
817 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
820 void audio_ff_rewind(long newpos)
822 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
823 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
826 void audio_flush_and_reload_tracks(void)
828 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
829 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
832 void audio_error_clear(void)
834 #ifdef AUDIO_HAVE_RECORDING
835 pcm_rec_error_clear();
836 #endif
839 int audio_status(void)
841 int ret = 0;
843 if (playing)
844 ret |= AUDIO_STATUS_PLAY;
846 if (paused)
847 ret |= AUDIO_STATUS_PAUSE;
849 #ifdef HAVE_RECORDING
850 /* Do this here for constitency with mpeg.c version */
851 ret |= pcm_rec_status();
852 #endif
854 return ret;
857 int audio_get_file_pos(void)
859 return 0;
862 #ifndef HAVE_FLASH_STORAGE
863 void audio_set_buffer_margin(int setting)
865 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
866 buffer_margin = lookup[setting];
867 logf("buffer margin: %d", buffer_margin);
868 set_filebuf_watermark(buffer_margin, 0);
870 #endif
872 /* Take nescessary steps to enable or disable the crossfade setting */
873 void audio_set_crossfade(int enable)
875 size_t offset;
876 bool was_playing;
877 size_t size;
879 /* Tell it the next setting to use */
880 pcmbuf_crossfade_enable(enable);
882 /* Return if size hasn't changed or this is too early to determine
883 which in the second case there's no way we could be playing
884 anything at all */
885 if (pcmbuf_is_same_size())
887 /* This function is a copout and just syncs some variables -
888 to be removed at a later date */
889 pcmbuf_crossfade_enable_finished();
890 return;
893 offset = 0;
894 was_playing = playing;
896 /* Playback has to be stopped before changing the buffer size */
897 if (was_playing)
899 /* Store the track resume position */
900 offset = curtrack_id3.offset;
901 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
904 /* Blast it - audio buffer will have to be setup again next time
905 something plays */
906 audio_get_buffer(true, &size);
908 /* Restart playback if audio was running previously */
909 if (was_playing)
910 audio_play(offset);
913 /* --- Routines called from multiple threads --- */
914 static void set_current_codec(int codec_idx)
916 current_codec = codec_idx;
917 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
920 #ifdef PLAYBACK_VOICE
921 static void swap_codec(void)
923 int my_codec;
925 /* Swap nothing if no swap buffers exist */
926 if (dram_buf == NULL)
928 logf("swap: no swap buffers");
929 return;
932 my_codec = current_codec;
934 logf("swapping out codec: %d", my_codec);
936 /* Invert this when a codec thread enters and leaves */
937 swap_codec_parity = !swap_codec_parity;
939 /* If this is true, an odd number of calls has occurred and there's
940 no codec thread waiting to swap us out when it locks and runs. This
941 occurs when playback is stopped or when just starting playback and
942 the audio thread is loading a codec; parities should always be even
943 on entry when a thread calls this during playback */
944 if (swap_codec_parity)
946 /* Save our current IRAM and DRAM */
947 #ifdef IRAM_STEAL
948 if (voice_iram_stolen)
950 logf("swap: iram restore");
951 voice_iram_stolen = false;
952 /* Don't swap trashed data into buffer as the voice IRAM will
953 already be swapped out - should _always_ be the case if
954 voice_iram_stolen is true since the voice has been swapped
955 in beforehand */
956 if (my_codec == CODEC_IDX_VOICE)
958 logf("voice iram already swapped");
959 goto skip_iram_swap;
962 #endif
964 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
966 #ifdef IRAM_STEAL
967 skip_iram_swap:
968 #endif
970 memswap128(dram_buf, codecbuf, CODEC_SIZE);
971 /* No cache invalidation needed; it will be done in codec_load_ram
972 or we won't be here otherwise */
975 /* Release my semaphore */
976 semaphore_release(&sem_codecthread);
977 logf("unlocked: %d", my_codec);
979 /* Wait for other codec */
980 event_wait(&event_codecthread,
981 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
983 /* Wait for other codec to unlock */
984 logf("waiting for lock: %d", my_codec);
985 semaphore_wait(&sem_codecthread);
987 /* Take control */
988 set_current_codec(my_codec);
989 event_set_state(&event_codecthread,
990 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
992 /* Reload our IRAM and DRAM */
993 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
994 memswap128(dram_buf, codecbuf, CODEC_SIZE);
995 invalidate_icache();
997 /* Flip parity again */
998 swap_codec_parity = !swap_codec_parity;
1000 logf("resuming codec: %d", my_codec);
1003 /* This function is meant to be used by the buffer stealing functions to
1004 ensure the codec is no longer active and so voice will be swapped-in
1005 before it is called */
1006 static void voice_stop(void)
1008 /* Must have a voice codec loaded or we'll hang forever here */
1009 if (!voice_codec_loaded)
1010 return;
1012 talk_force_shutup();
1014 /* Loop until voice empties it's queue, stops and picks up on the new
1015 track; the voice thread must be stopped and waiting for messages
1016 outside the codec */
1017 while (voice_is_playing || !queue_empty(&voice_queue) ||
1018 ci_voice.new_track)
1019 yield();
1021 if (!playing)
1022 pcmbuf_play_stop();
1023 } /* voice_stop */
1025 /* Is voice still speaking */
1026 /* Unfortunately only reliable when music is not also playing. */
1027 static bool is_voice_speaking(void)
1029 return is_voice_queued()
1030 || voice_is_playing
1031 || (!playing && pcm_is_playing());
1034 #endif /* PLAYBACK_VOICE */
1036 /* Wait for voice to finish speaking. */
1037 /* Also only reliable when music is not also playing. */
1038 void voice_wait(void)
1040 #ifdef PLAYBACK_VOICE
1041 while (is_voice_speaking())
1042 sleep(HZ/10);
1043 #endif
1046 static void set_filebuf_watermark(int seconds, size_t max)
1048 size_t bytes;
1050 if (!filebuf)
1051 return; /* Audio buffers not yet set up */
1053 bytes = MAX(curtrack_id3.bitrate * seconds * (1000/8), max);
1054 bytes = MIN(bytes, filebuflen / 2);
1055 buf_set_conf(BUFFERING_SET_WATERMARK, bytes);
1058 const char * get_codec_filename(int cod_spec)
1060 const char *fname;
1062 #ifdef HAVE_RECORDING
1063 /* Can choose decoder or encoder if one available */
1064 int type = cod_spec & CODEC_TYPE_MASK;
1065 int afmt = cod_spec & CODEC_AFMT_MASK;
1067 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1068 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1070 fname = (type == CODEC_TYPE_ENCODER) ?
1071 audio_formats[afmt].codec_enc_root_fn :
1072 audio_formats[afmt].codec_root_fn;
1074 logf("%s: %d - %s",
1075 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1076 afmt, fname ? fname : "<unknown>");
1077 #else /* !HAVE_RECORDING */
1078 /* Always decoder */
1079 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1080 cod_spec = AFMT_UNKNOWN;
1081 fname = audio_formats[cod_spec].codec_root_fn;
1082 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1083 #endif /* HAVE_RECORDING */
1085 return fname;
1086 } /* get_codec_filename */
1089 /* --- Voice thread --- */
1091 #ifdef PLAYBACK_VOICE
1093 static bool voice_pcmbuf_insert_callback(
1094 const void *ch1, const void *ch2, int count)
1096 const char *src[2] = { ch1, ch2 };
1098 while (count > 0)
1100 int out_count = dsp_output_count(count);
1101 int inp_count;
1102 char *dest;
1104 while ((dest = pcmbuf_request_voice_buffer(
1105 &out_count, playing)) == NULL)
1107 if (playing && audio_codec_loaded)
1108 swap_codec();
1109 else
1110 yield();
1113 /* Get the real input_size for output_size bytes, guarding
1114 * against resampling buffer overflows. */
1115 inp_count = dsp_input_count(out_count);
1117 if (inp_count <= 0)
1118 return true;
1120 /* Input size has grown, no error, just don't write more than length */
1121 if (inp_count > count)
1122 inp_count = count;
1124 out_count = dsp_process(dest, src, inp_count);
1126 if (out_count <= 0)
1127 return true;
1129 if (playing)
1131 pcmbuf_mix_voice(out_count);
1132 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1133 audio_codec_loaded)
1134 swap_codec();
1136 else
1137 pcmbuf_write_complete(out_count);
1139 count -= inp_count;
1142 return true;
1143 } /* voice_pcmbuf_insert_callback */
1145 static void* voice_get_memory_callback(size_t *size)
1147 /* Voice should have no use for this. If it did, we'd have to
1148 swap the malloc buffer as well. */
1149 *size = 0;
1150 return NULL;
1153 static void voice_set_elapsed_callback(unsigned int value)
1155 (void)value;
1158 static void voice_set_offset_callback(size_t value)
1160 (void)value;
1163 static void voice_configure_callback(int setting, intptr_t value)
1165 if (!dsp_configure(setting, value))
1167 logf("Illegal key:%d", setting);
1171 static size_t voice_filebuf_callback(void *ptr, size_t size)
1173 (void)ptr;
1174 (void)size;
1176 return 0;
1179 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1180 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1182 if (aborting && !playing)
1184 /* Aborting: Slight hack - flush PCM buffer if
1185 only being used for voice */
1186 pcmbuf_play_stop();
1189 if (voice_is_playing)
1191 /* Clear the current buffer */
1192 voice_is_playing = false;
1193 voice_getmore = NULL;
1194 voice_remaining = 0;
1195 voicebuf = NULL;
1197 /* Cancel any automatic boost if no more clips requested. */
1198 if (!playing || !voice_thread_start)
1199 sleep(0);
1201 /* Force the codec to think it's changing tracks */
1202 ci_voice.new_track = 1;
1204 *realsize = 0;
1205 return true; /* Yes, change tracks */
1208 return false;
1211 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1213 struct queue_event ev;
1215 if (ci_voice.new_track)
1217 *realsize = 0;
1218 return NULL;
1221 while (1)
1223 if (voice_is_playing || playing)
1225 queue_wait_w_tmo(&voice_queue, &ev, 0);
1226 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1227 ev.id = Q_AUDIO_PLAY;
1229 else
1231 queue_wait(&voice_queue, &ev);
1234 switch (ev.id) {
1235 case Q_AUDIO_PLAY:
1236 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1237 if (playing)
1239 if (audio_codec_loaded)
1240 swap_codec();
1241 yield();
1243 break;
1245 #ifdef AUDIO_HAVE_RECORDING
1246 case Q_ENCODER_RECORD:
1247 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1248 swap_codec();
1249 break;
1250 #endif
1252 case Q_VOICE_STOP:
1253 LOGFQUEUE("voice < Q_VOICE_STOP");
1254 if (voice_on_voice_stop(ev.data, realsize))
1255 return NULL;
1256 break;
1258 case SYS_USB_CONNECTED:
1260 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1261 bool change_tracks = voice_on_voice_stop(ev.data, realsize);
1262 /* Voice is obviously current so let us swap ourselves away if
1263 playing so audio may stop itself - audio_codec_loaded can
1264 only be true in this case if we're here even if the codec
1265 is only about to load */
1266 if (audio_codec_loaded)
1267 swap_codec();
1268 /* Playback should be finished by now - ack and wait */
1269 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1270 usb_wait_for_disconnect(&voice_queue);
1271 if (change_tracks)
1272 return NULL;
1273 break;
1276 case Q_VOICE_PLAY:
1277 LOGFQUEUE("voice < Q_VOICE_PLAY");
1278 if (!voice_is_playing)
1280 /* Set up new voice data */
1281 struct voice_info *voice_data;
1282 #ifdef IRAM_STEAL
1283 if (voice_iram_stolen)
1285 /* Voice is the first to run again and is currently
1286 loaded */
1287 logf("voice: iram restore");
1288 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1289 voice_iram_stolen = false;
1291 #endif
1292 /* Must reset the buffer before any playback begins if
1293 needed */
1294 if (buffer_state == BUFFER_STATE_TRASHED)
1295 audio_reset_buffer();
1297 voice_is_playing = true;
1298 trigger_cpu_boost();
1299 voice_data = (struct voice_info *)ev.data;
1300 voice_remaining = voice_data->size;
1301 voicebuf = voice_data->buf;
1302 voice_getmore = voice_data->callback;
1304 goto voice_play_clip; /* To exit both switch and while */
1306 case SYS_TIMEOUT:
1307 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1308 goto voice_play_clip;
1310 default:
1311 LOGFQUEUE("voice < default");
1315 voice_play_clip:
1317 if (voice_remaining == 0 || voicebuf == NULL)
1319 if (voice_getmore)
1320 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1322 /* If this clip is done */
1323 if (voice_remaining == 0)
1325 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1326 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1327 /* Force pcm playback. */
1328 if (!pcm_is_playing())
1329 pcmbuf_play_start();
1333 *realsize = MIN(voice_remaining, reqsize);
1335 if (*realsize == 0)
1336 return NULL;
1338 return voicebuf;
1339 } /* voice_request_buffer_callback */
1341 static void voice_advance_buffer_callback(size_t amount)
1343 amount = MIN(amount, voice_remaining);
1344 voicebuf += amount;
1345 voice_remaining -= amount;
1348 static void voice_advance_buffer_loc_callback(void *ptr)
1350 size_t amount = (size_t)ptr - (size_t)voicebuf;
1352 voice_advance_buffer_callback(amount);
1355 static off_t voice_mp3_get_filepos_callback(int newtime)
1357 (void)newtime;
1359 return 0;
1362 static void voice_do_nothing(void)
1364 return;
1367 static bool voice_seek_buffer_callback(size_t newpos)
1369 (void)newpos;
1371 return false;
1374 static bool voice_request_next_track_callback(void)
1376 ci_voice.new_track = 0;
1377 return true;
1380 static void voice_thread(void)
1382 logf("Loading voice codec");
1383 voice_codec_loaded = true;
1384 semaphore_wait(&sem_codecthread);
1385 event_set_state(&event_codecthread, false);
1386 set_current_codec(CODEC_IDX_VOICE);
1387 dsp_configure(DSP_RESET, 0);
1388 voice_remaining = 0;
1389 voice_getmore = NULL;
1391 /* FIXME: If we being starting the voice thread without reboot, the
1392 voice_queue could be full of old stuff and we must flush it. */
1393 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1395 logf("Voice codec finished");
1396 voice_codec_loaded = false;
1397 voice_thread_p = NULL;
1398 semaphore_release(&sem_codecthread);
1399 } /* voice_thread */
1401 #endif /* PLAYBACK_VOICE */
1403 /* --- Codec thread --- */
1404 static bool codec_pcmbuf_insert_callback(
1405 const void *ch1, const void *ch2, int count)
1407 const char *src[2] = { ch1, ch2 };
1409 while (count > 0)
1411 int out_count = dsp_output_count(count);
1412 int inp_count;
1413 char *dest;
1415 /* Prevent audio from a previous track from playing */
1416 if (ci.new_track || ci.stop_codec)
1417 return true;
1419 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1421 sleep(1);
1422 if (ci.seek_time || ci.new_track || ci.stop_codec)
1423 return true;
1426 /* Get the real input_size for output_size bytes, guarding
1427 * against resampling buffer overflows. */
1428 inp_count = dsp_input_count(out_count);
1430 if (inp_count <= 0)
1431 return true;
1433 /* Input size has grown, no error, just don't write more than length */
1434 if (inp_count > count)
1435 inp_count = count;
1437 out_count = dsp_process(dest, src, inp_count);
1439 if (out_count <= 0)
1440 return true;
1442 pcmbuf_write_complete(out_count);
1444 #ifdef PLAYBACK_VOICE
1445 if ((voice_is_playing || voice_thread_start)
1446 && pcm_is_playing() && voice_codec_loaded &&
1447 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1449 voice_thread_start = false;
1450 swap_codec();
1452 #endif
1454 count -= inp_count;
1457 return true;
1458 } /* codec_pcmbuf_insert_callback */
1460 static void* codec_get_memory_callback(size_t *size)
1462 *size = MALLOC_BUFSIZE;
1463 return malloc_buf;
1466 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1467 static void codec_pcmbuf_position_callback(size_t size)
1469 /* This is called from an ISR, so be quick */
1470 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1471 prevtrack_id3.elapsed;
1473 if (time >= prevtrack_id3.length)
1475 pcmbuf_set_position_callback(NULL);
1476 prevtrack_id3.elapsed = prevtrack_id3.length;
1478 else
1479 prevtrack_id3.elapsed = time;
1482 static void codec_set_elapsed_callback(unsigned int value)
1484 unsigned int latency;
1485 if (ci.seek_time)
1486 return;
1488 #ifdef AB_REPEAT_ENABLE
1489 ab_position_report(value);
1490 #endif
1492 latency = pcmbuf_get_latency();
1493 if (value < latency)
1494 curtrack_id3.elapsed = 0;
1495 else if (value - latency > curtrack_id3.elapsed ||
1496 value - latency < curtrack_id3.elapsed - 2)
1498 curtrack_id3.elapsed = value - latency;
1502 static void codec_set_offset_callback(size_t value)
1504 unsigned int latency;
1506 if (ci.seek_time)
1507 return;
1509 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1510 if (value < latency)
1511 curtrack_id3.offset = 0;
1512 else
1513 curtrack_id3.offset = value - latency;
1516 static void codec_advance_buffer_counters(size_t amount)
1518 bufadvance(CUR_TI->audio_hid, amount);
1519 ci.curpos += amount;
1522 /* copy up-to size bytes into ptr and return the actual size copied */
1523 static size_t codec_filebuf_callback(void *ptr, size_t size)
1525 ssize_t copy_n;
1527 if (ci.stop_codec || !playing)
1528 return 0;
1530 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1532 /* Nothing requested OR nothing left */
1533 if (copy_n == 0)
1534 return 0;
1537 if (copy_n == -2)
1539 buf_request_buffer_handle(CUR_TI->audio_hid);
1542 /* Let the disk buffer catch fill until enough data is available */
1543 while (copy_n == -2)
1545 sleep(1);
1547 if (ci.stop_codec || ci.new_track)
1548 return 0;
1550 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1553 /* Update read and other position pointers */
1554 codec_advance_buffer_counters(copy_n);
1556 /* Return the actual amount of data copied to the buffer */
1557 return copy_n;
1558 } /* codec_filebuf_callback */
1560 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1562 size_t copy_n = reqsize;
1563 ssize_t ret;
1564 void *ptr;
1566 if (!playing)
1568 *realsize = 0;
1569 return NULL;
1572 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1573 if (ret >= 0)
1574 copy_n = MIN((size_t)ret, reqsize);
1576 if (copy_n == 0)
1578 *realsize = 0;
1579 return NULL;
1582 if (ret == -2)
1584 buf_request_buffer_handle(CUR_TI->audio_hid);
1587 /* Let the disk buffer catch fill until enough data is available */
1588 while (ret == -2)
1590 sleep(1);
1592 if (ci.stop_codec || ci.new_track)
1594 *realsize = 0;
1595 return NULL;
1597 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1599 copy_n = MIN((size_t)ret, reqsize);
1601 *realsize = copy_n;
1603 return ptr;
1604 } /* codec_request_buffer_callback */
1606 static int get_codec_base_type(int type)
1608 switch (type) {
1609 case AFMT_MPA_L1:
1610 case AFMT_MPA_L2:
1611 case AFMT_MPA_L3:
1612 return AFMT_MPA_L3;
1615 return type;
1618 static void codec_advance_buffer_callback(size_t amount)
1620 codec_advance_buffer_counters(amount);
1621 codec_set_offset_callback(ci.curpos);
1624 static void codec_advance_buffer_loc_callback(void *ptr)
1626 size_t amount = buf_get_offset(CUR_TI->audio_hid, ptr);
1628 codec_advance_buffer_callback(amount);
1631 /* Copied from mpeg.c. Should be moved somewhere else. */
1632 static int codec_get_file_pos(void)
1634 int pos = -1;
1635 struct mp3entry *id3 = audio_current_track();
1637 if (id3->vbr)
1639 if (id3->has_toc)
1641 /* Use the TOC to find the new position */
1642 unsigned int percent, remainder;
1643 int curtoc, nexttoc, plen;
1645 percent = (id3->elapsed*100)/id3->length;
1646 if (percent > 99)
1647 percent = 99;
1649 curtoc = id3->toc[percent];
1651 if (percent < 99)
1652 nexttoc = id3->toc[percent+1];
1653 else
1654 nexttoc = 256;
1656 pos = (id3->filesize/256)*curtoc;
1658 /* Use the remainder to get a more accurate position */
1659 remainder = (id3->elapsed*100)%id3->length;
1660 remainder = (remainder*100)/id3->length;
1661 plen = (nexttoc - curtoc)*(id3->filesize/256);
1662 pos += (plen/100)*remainder;
1664 else
1666 /* No TOC exists, estimate the new position */
1667 pos = (id3->filesize / (id3->length / 1000)) *
1668 (id3->elapsed / 1000);
1671 else if (id3->bitrate)
1672 pos = id3->elapsed * (id3->bitrate / 8);
1673 else
1674 return -1;
1676 pos += id3->first_frame_offset;
1678 /* Don't seek right to the end of the file so that we can
1679 transition properly to the next song */
1680 if (pos >= (int)(id3->filesize - id3->id3v1len))
1681 pos = id3->filesize - id3->id3v1len - 1;
1683 return pos;
1686 static off_t codec_mp3_get_filepos_callback(int newtime)
1688 off_t newpos;
1690 curtrack_id3.elapsed = newtime;
1691 newpos = codec_get_file_pos();
1693 return newpos;
1696 static void codec_seek_complete_callback(void)
1698 logf("seek_complete");
1699 if (pcm_is_paused())
1701 /* If this is not a seamless seek, clear the buffer */
1702 pcmbuf_play_stop();
1703 dsp_configure(DSP_FLUSH, 0);
1705 /* If playback was not 'deliberately' paused, unpause now */
1706 if (!paused)
1707 pcmbuf_pause(false);
1709 ci.seek_time = 0;
1712 static bool codec_seek_buffer_callback(size_t newpos)
1714 logf("codec_seek_buffer_callback");
1716 int ret = bufseek(CUR_TI->audio_hid, newpos);
1717 if (ret == 0) {
1718 ci.curpos = newpos;
1719 return true;
1721 else {
1722 return false;
1726 static void codec_configure_callback(int setting, intptr_t value)
1728 switch (setting) {
1729 case CODEC_SET_FILEBUF_WATERMARK:
1730 set_filebuf_watermark(buffer_margin, value);
1731 break;
1733 case CODEC_SET_FILEBUF_CHUNKSIZE:
1734 buf_set_conf(BUFFERING_SET_CHUNKSIZE, value);
1735 break;
1737 case CODEC_SET_FILEBUF_PRESEEK:
1738 buf_set_conf(BUFFERING_SET_PRESEEK, value);
1739 break;
1741 default:
1742 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1746 static void codec_track_changed(void)
1748 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1749 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1752 static void codec_pcmbuf_track_changed_callback(void)
1754 DEBUGF("codec_pcmbuf_track_changed_callback\n");
1755 pcmbuf_set_position_callback(NULL);
1756 codec_track_changed();
1759 static void codec_discard_codec_callback(void)
1761 if (CUR_TI->codec_hid > 0)
1763 bufclose(CUR_TI->codec_hid);
1764 CUR_TI->codec_hid = 0;
1765 CUR_TI->codecsize = 0;
1769 static inline void codec_gapless_track_change(void) {
1770 /* callback keeps the progress bar moving while the pcmbuf empties */
1771 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1772 /* set the pcmbuf callback for when the track really changes */
1773 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1776 static inline void codec_crossfade_track_change(void) {
1777 /* Initiate automatic crossfade mode */
1778 pcmbuf_crossfade_init(false);
1779 /* Notify the wps that the track change starts now */
1780 codec_track_changed();
1783 static void codec_track_skip_done(bool was_manual)
1785 int crossfade_mode = global_settings.crossfade;
1787 /* Manual track change (always crossfade or flush audio). */
1788 if (was_manual)
1790 pcmbuf_crossfade_init(true);
1791 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1792 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1794 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1795 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1796 && crossfade_mode != CROSSFADE_ENABLE_TRACKSKIP)
1798 if (crossfade_mode == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1800 if (global_settings.playlist_shuffle)
1801 /* shuffle mode is on, so crossfade: */
1802 codec_crossfade_track_change();
1803 else
1804 /* shuffle mode is off, so do a gapless track change */
1805 codec_gapless_track_change();
1807 else
1808 /* normal crossfade: */
1809 codec_crossfade_track_change();
1811 else
1812 /* normal gapless playback. */
1813 codec_gapless_track_change();
1816 static bool codec_load_next_track(void)
1818 intptr_t result = Q_CODEC_REQUEST_FAILED;
1820 prev_track_elapsed = curtrack_id3.elapsed;
1822 if (ci.seek_time)
1823 codec_seek_complete_callback();
1825 #ifdef AB_REPEAT_ENABLE
1826 ab_end_of_track_report();
1827 #endif
1829 logf("Request new track");
1831 if (ci.new_track == 0)
1833 ci.new_track++;
1834 automatic_skip = true;
1837 if (!ci.stop_codec)
1839 trigger_cpu_boost();
1840 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1841 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1844 switch (result)
1846 case Q_CODEC_REQUEST_COMPLETE:
1847 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1848 codec_track_skip_done(!automatic_skip);
1849 return true;
1851 case Q_CODEC_REQUEST_FAILED:
1852 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1853 ci.new_track = 0;
1854 ci.stop_codec = true;
1855 return false;
1857 default:
1858 LOGFQUEUE("codec |< default");
1859 ci.stop_codec = true;
1860 return false;
1864 static bool codec_request_next_track_callback(void)
1866 int prev_codectype;
1868 if (ci.stop_codec || !playing)
1869 return false;
1871 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1873 if (!codec_load_next_track())
1874 return false;
1876 /* Seek to the beginning of the new track because if the struct mp3entry was
1877 buffered, "elapsed" might not be zero (if the track has been played
1878 already but not unbuffered) */
1879 codec_seek_buffer_callback(0);
1881 /* Check if the next codec is the same file. */
1882 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1884 logf("New track loaded");
1885 codec_discard_codec_callback();
1886 return true;
1888 else
1890 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1891 return false;
1895 static void codec_thread(void)
1897 struct queue_event ev;
1898 int status;
1899 size_t wrap;
1901 while (1) {
1902 status = 0;
1903 queue_wait(&codec_queue, &ev);
1905 switch (ev.id) {
1906 case Q_CODEC_LOAD_DISK:
1907 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1908 queue_reply(&codec_queue, 1);
1909 audio_codec_loaded = true;
1910 #ifdef PLAYBACK_VOICE
1911 /* Don't sent messages to voice codec if it's already swapped
1912 out or it will never get this */
1913 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1915 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1916 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1918 semaphore_wait(&sem_codecthread);
1919 event_set_state(&event_codecthread, true);
1920 #endif
1921 set_current_codec(CODEC_IDX_AUDIO);
1922 ci.stop_codec = false;
1923 status = codec_load_file((const char *)ev.data, &ci);
1924 DEBUGF("codec_load = %d\n", status);
1925 #ifdef PLAYBACK_VOICE
1926 semaphore_release(&sem_codecthread);
1927 #endif
1928 break;
1930 case Q_CODEC_LOAD:
1931 LOGFQUEUE("codec < Q_CODEC_LOAD");
1932 if (CUR_TI->codec_hid <= 0) {
1933 logf("Codec slot is empty!");
1934 /* Wait for the pcm buffer to go empty */
1935 while (pcm_is_playing())
1936 yield();
1937 /* This must be set to prevent an infinite loop */
1938 ci.stop_codec = true;
1939 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1940 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1941 break;
1944 audio_codec_loaded = true;
1945 #ifdef PLAYBACK_VOICE
1946 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1948 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1949 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1951 semaphore_wait(&sem_codecthread);
1952 event_set_state(&event_codecthread, true);
1953 #endif
1954 set_current_codec(CODEC_IDX_AUDIO);
1955 ci.stop_codec = false;
1956 wrap = (size_t)&filebuf[filebuflen] - (size_t)bufgetcodec(CUR_TI);
1957 status = codec_load_ram(bufgetcodec(CUR_TI), CUR_TI->codecsize,
1958 &filebuf[0], wrap, &ci);
1959 #ifdef PLAYBACK_VOICE
1960 semaphore_release(&sem_codecthread);
1961 #endif
1962 break;
1964 #ifdef AUDIO_HAVE_RECORDING
1965 case Q_ENCODER_LOAD_DISK:
1966 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1967 audio_codec_loaded = false; /* Not audio codec! */
1968 #ifdef PLAYBACK_VOICE
1969 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1971 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1972 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
1974 semaphore_wait(&sem_codecthread);
1975 event_set_state(&event_codecthread, true);
1976 #endif
1977 logf("loading encoder");
1978 set_current_codec(CODEC_IDX_AUDIO);
1979 ci.stop_encoder = false;
1980 status = codec_load_file((const char *)ev.data, &ci);
1981 #ifdef PLAYBACK_VOICE
1982 semaphore_release(&sem_codecthread);
1983 #endif
1984 logf("encoder stopped");
1985 break;
1986 #endif /* AUDIO_HAVE_RECORDING */
1988 #ifndef SIMULATOR
1989 case SYS_USB_CONNECTED:
1990 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1991 queue_clear(&codec_queue);
1992 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1993 usb_wait_for_disconnect(&codec_queue);
1994 break;
1995 #endif
1997 default:
1998 LOGFQUEUE("codec < default");
2001 if (audio_codec_loaded)
2003 if (ci.stop_codec)
2005 status = CODEC_OK;
2006 if (!playing)
2007 pcmbuf_play_stop();
2010 audio_codec_loaded = false;
2013 switch (ev.id) {
2014 case Q_CODEC_LOAD_DISK:
2015 case Q_CODEC_LOAD:
2016 LOGFQUEUE("codec < Q_CODEC_LOAD");
2017 if (playing)
2019 if (ci.new_track || status != CODEC_OK)
2021 if (!ci.new_track)
2023 logf("Codec failure");
2024 gui_syncsplash(HZ*2, "Codec failure");
2027 if (!codec_load_next_track())
2029 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2030 /* End of playlist */
2031 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2032 break;
2035 else
2037 logf("Codec finished");
2038 if (ci.stop_codec)
2040 /* Wait for the audio to stop playing before
2041 * triggering the WPS exit */
2042 while(pcm_is_playing())
2044 curtrack_id3.elapsed =
2045 curtrack_id3.length - pcmbuf_get_latency();
2046 sleep(1);
2048 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2049 /* End of playlist */
2050 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2051 break;
2055 if (CUR_TI->codec_hid > 0)
2057 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2058 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
2060 else
2062 const char *codec_fn =
2063 get_codec_filename(curtrack_id3.codectype);
2064 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2065 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
2066 (intptr_t)codec_fn);
2069 break;
2071 #ifdef AUDIO_HAVE_RECORDING
2072 case Q_ENCODER_LOAD_DISK:
2073 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2075 if (status == CODEC_OK)
2076 break;
2078 logf("Encoder failure");
2079 gui_syncsplash(HZ*2, "Encoder failure");
2081 if (ci.enc_codec_loaded < 0)
2082 break;
2084 logf("Encoder failed to load");
2085 ci.enc_codec_loaded = -1;
2086 break;
2087 #endif /* AUDIO_HAVE_RECORDING */
2089 default:
2090 LOGFQUEUE("codec < default");
2092 } /* end switch */
2097 /* --- Audio thread --- */
2099 static bool audio_have_tracks(void)
2101 return track_ridx != track_widx || CUR_TI->filesize;
2104 static bool audio_have_free_tracks(void)
2106 if (track_widx < track_ridx)
2107 return track_widx + 1 < track_ridx;
2108 else if (track_ridx == 0)
2109 return track_widx < MAX_TRACK - 1;
2111 return true;
2114 int audio_track_count(void)
2116 if (audio_have_tracks())
2118 int relative_track_widx = track_widx;
2120 if (track_ridx > track_widx)
2121 relative_track_widx += MAX_TRACK;
2123 return relative_track_widx - track_ridx + 1;
2126 return 0;
2129 long audio_filebufused(void)
2131 return (long) buf_used();
2134 static void audio_update_trackinfo(void)
2136 if (CUR_TI->id3_hid > 0)
2137 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
2139 CUR_TI->taginfo_ready = (CUR_TI->id3_hid > 0);
2141 int next_idx = track_ridx + 1;
2142 next_idx &= MAX_TRACK_MASK;
2144 if (tracks[next_idx].id3_hid > 0)
2145 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
2147 tracks[next_idx].taginfo_ready = (tracks[next_idx].id3_hid > 0);
2149 ci.filesize = CUR_TI->filesize;
2150 curtrack_id3.elapsed = 0;
2151 curtrack_id3.offset = 0;
2152 ci.id3 = &curtrack_id3;
2153 ci.curpos = 0;
2154 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2157 static void audio_clear_track_entries(bool clear_unbuffered)
2159 int cur_idx = track_widx;
2160 int last_idx = -1;
2162 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2164 /* Loop over all tracks from write-to-read */
2165 while (1)
2167 cur_idx++;
2168 cur_idx &= MAX_TRACK_MASK;
2170 if (cur_idx == track_ridx)
2171 break;
2173 /* If the track is buffered, conditionally clear/notify,
2174 * otherwise clear the track if that option is selected */
2175 if (tracks[cur_idx].event_sent)
2177 if (last_idx >= 0)
2179 /* If there is an unbuffer callback, call it, otherwise,
2180 * just clear the track */
2181 if (track_unbuffer_callback && tracks[last_idx].id3_hid > 0)
2182 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2184 clear_track_info(&tracks[last_idx]);
2186 last_idx = cur_idx;
2188 else if (clear_unbuffered)
2189 clear_track_info(&tracks[cur_idx]);
2192 /* We clear the previous instance of a buffered track throughout
2193 * the above loop to facilitate 'last' detection. Clear/notify
2194 * the last track here */
2195 if (last_idx >= 0)
2197 if (track_unbuffer_callback && tracks[last_idx].id3_hid > 0)
2198 track_unbuffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2199 clear_track_info(&tracks[last_idx]);
2203 static bool audio_release_tracks(void)
2205 int i, cur_idx;
2207 logf("releasing all tracks");
2209 for(i = 0; i < MAX_TRACKS; i++)
2211 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
2212 if (!clear_track_info(&tracks[cur_idx]))
2213 return false;
2216 return true;
2219 #if 0
2220 /* FIXME: This code should be made more generic and move to metadata.c */
2221 static void audio_strip_tags(void)
2223 int i;
2224 static const unsigned char tag[] = "TAG";
2225 static const unsigned char apetag[] = "APETAGEX";
2226 size_t tag_idx;
2227 size_t cur_idx;
2228 size_t len, version;
2230 tag_idx = RINGBUF_SUB(buf_widx, 128);
2232 if (bufused() > 128 && tag_idx > buf_ridx)
2234 cur_idx = tag_idx;
2235 for(i = 0;i < 3;i++)
2237 if(filebuf[cur_idx] != tag[i])
2238 goto strip_ape_tag;
2240 cur_idx = RINGBUF_ADD(cur_idx, 1);
2243 /* Skip id3v1 tag */
2244 logf("Skipping ID3v1 tag");
2245 buf_widx = tag_idx;
2246 tracks[track_widx].available -= 128;
2247 tracks[track_widx].filesize -= 128;
2250 strip_ape_tag:
2251 /* Check for APE tag (look for the APE tag footer) */
2252 tag_idx = RINGBUF_SUB(buf_widx, 32);
2254 if (bufused() > 32 && tag_idx > buf_ridx)
2256 cur_idx = tag_idx;
2257 for(i = 0;i < 8;i++)
2259 if(filebuf[cur_idx] != apetag[i])
2260 return;
2262 cur_idx = RINGBUF_ADD(cur_idx, 1);
2265 /* Read the version and length from the footer */
2266 version = filebuf[tag_idx+8] | (filebuf[tag_idx+9] << 8) |
2267 (filebuf[tag_idx+10] << 16) | (filebuf[tag_idx+11] << 24);
2268 len = filebuf[tag_idx+12] | (filebuf[tag_idx+13] << 8) |
2269 (filebuf[tag_idx+14] << 16) | (filebuf[tag_idx+15] << 24);
2270 if (version == 2000)
2271 len += 32; /* APEv2 has a 32 byte header */
2273 /* Skip APE tag */
2274 if (bufused() > len)
2276 logf("Skipping APE tag (%ldB)", len);
2277 buf_widx = RINGBUF_SUB(buf_widx, len);
2278 tracks[track_widx].available -= len;
2279 tracks[track_widx].filesize -= len;
2283 #endif
2285 static bool audio_loadcodec(bool start_play)
2287 int fd;
2288 int prev_track;
2289 char codec_path[MAX_PATH]; /* Full path to codec */
2291 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play ? "true" : "false");
2293 if (tracks[track_widx].id3_hid <= 0) {
2294 DEBUGF("track ID3 info not ready\n");
2295 return false;
2298 const char * codec_fn =
2299 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2300 if (codec_fn == NULL)
2301 return false;
2303 tracks[track_widx].codec_hid = 0;
2305 if (start_play)
2307 /* Load the codec directly from disk and save some memory. */
2308 track_ridx = track_widx;
2309 ci.filesize = CUR_TI->filesize;
2310 ci.id3 = &curtrack_id3;
2311 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2312 ci.curpos = 0;
2313 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2314 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2315 return true;
2317 else
2319 /* If we already have another track than this one buffered */
2320 if (track_widx != track_ridx)
2322 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2324 /* If the previous codec is the same as this one, there is no need
2325 * to put another copy of it on the file buffer */
2326 if (get_codec_base_type(
2327 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2328 get_codec_base_type(
2329 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2330 && audio_codec_loaded)
2332 logf("Reusing prev. codec");
2333 return true;
2338 codec_get_full_path(codec_path, codec_fn);
2340 fd = open(codec_path, O_RDONLY);
2341 if (fd < 0)
2343 logf("Codec doesn't exist!");
2344 return false;
2347 tracks[track_widx].codecsize = filesize(fd);
2349 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2350 if (tracks[track_widx].codec_hid < 0)
2352 logf("Not enough space");
2353 close(fd);
2354 return false;
2357 close(fd);
2358 logf("Loaded codec");
2360 return true;
2363 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2364 static void audio_set_elapsed(struct mp3entry* id3)
2366 unsigned long offset = id3->offset > id3->first_frame_offset ?
2367 id3->offset - id3->first_frame_offset : 0;
2369 if ( id3->vbr ) {
2370 if ( id3->has_toc ) {
2371 /* calculate elapsed time using TOC */
2372 int i;
2373 unsigned int remainder, plen, relpos, nextpos;
2375 /* find wich percent we're at */
2376 for (i=0; i<100; i++ )
2377 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2378 break;
2380 i--;
2381 if (i < 0)
2382 i = 0;
2384 relpos = id3->toc[i];
2386 if (i < 99)
2387 nextpos = id3->toc[i+1];
2388 else
2389 nextpos = 256;
2391 remainder = offset - (relpos * (id3->filesize / 256));
2393 /* set time for this percent (divide before multiply to prevent
2394 overflow on long files. loss of precision is negligible on
2395 short files) */
2396 id3->elapsed = i * (id3->length / 100);
2398 /* calculate remainder time */
2399 plen = (nextpos - relpos) * (id3->filesize / 256);
2400 id3->elapsed += (((remainder * 100) / plen) *
2401 (id3->length / 10000));
2403 else {
2404 /* no TOC exists. set a rough estimate using average bitrate */
2405 int tpk = id3->length /
2406 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2407 1024);
2408 id3->elapsed = offset / 1024 * tpk;
2411 else
2413 /* constant bitrate, use exact calculation */
2414 if (id3->bitrate != 0)
2415 id3->elapsed = offset / (id3->bitrate / 8);
2419 /* Load one track by making the appropriate bufopen calls. Return true if
2420 everything required was loaded correctly, false if not. */
2421 static bool audio_load_track(int offset, bool start_play)
2423 char *trackname;
2424 char msgbuf[80];
2425 int fd = -1;
2426 int file_offset = 0;
2427 struct mp3entry id3;
2429 /* Stop buffer filling if there is no free track entries.
2430 Don't fill up the last track entry (we wan't to store next track
2431 metadata there). */
2432 if (!audio_have_free_tracks())
2434 logf("No free tracks");
2435 return false;
2438 last_peek_offset++;
2439 peek_again:
2440 logf("Buffering track:%d/%d", track_widx, track_ridx);
2441 /* Get track name from current playlist read position. */
2442 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2444 /* Handle broken playlists. */
2445 fd = open(trackname, O_RDONLY);
2446 if (fd < 0)
2448 logf("Open failed");
2449 /* Skip invalid entry from playlist. */
2450 playlist_skip_entry(NULL, last_peek_offset);
2452 else
2453 break;
2456 if (!trackname)
2458 logf("End-of-playlist");
2459 playlist_end = true;
2460 return false;
2463 tracks[track_widx].filesize = filesize(fd);
2465 /* Set default values */
2466 if (start_play)
2468 int last_codec = current_codec;
2470 set_current_codec(CODEC_IDX_AUDIO);
2471 buf_set_conf(BUFFERING_SET_WATERMARK, AUDIO_DEFAULT_WATERMARK);
2472 buf_set_conf(BUFFERING_SET_CHUNKSIZE, AUDIO_DEFAULT_FILECHUNK);
2473 buf_set_conf(BUFFERING_SET_PRESEEK, AUDIO_REBUFFER_GUESS_SIZE);
2474 dsp_configure(DSP_RESET, 0);
2475 set_current_codec(last_codec);
2477 track_changed = true;
2478 playlist_update_resume_info(audio_current_track());
2481 /* Get track metadata if we don't already have it. */
2482 if (tracks[track_widx].id3_hid <= 0)
2484 if (get_metadata(&id3, fd, trackname))
2486 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2487 TYPE_ID3);
2488 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2490 if (tracks[track_widx].id3_hid <= 0)
2492 DEBUGF("failed to allocate space for metadata\n");
2493 last_peek_offset--;
2494 close(fd);
2495 return false;
2498 if (track_widx == track_ridx)
2499 copy_mp3entry(&curtrack_id3, &id3);
2500 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2501 copy_mp3entry(&nexttrack_id3, &id3);
2503 if (start_play)
2505 track_changed = true;
2506 playlist_update_resume_info(audio_current_track());
2509 else
2511 logf("mde:%s!",trackname);
2513 /* Skip invalid entry from playlist. */
2514 playlist_skip_entry(NULL, last_peek_offset);
2515 tracks[track_widx].taginfo_ready = false;
2516 goto peek_again;
2521 close(fd);
2523 #if 0
2524 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2526 char cuepath[MAX_PATH];
2528 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2530 if (look_for_cuesheet_file(trackname, cuepath) &&
2531 parse_cuesheet(cuepath, cue))
2533 strcpy((cue)->audio_filename, trackname);
2534 if (start_play)
2535 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2538 #endif
2540 /* Load the codec. */
2541 if (!audio_loadcodec(start_play))
2543 if (tracks[track_widx].codecsize)
2545 /* No space for codec on buffer, not an error */
2546 tracks[track_widx].codecsize = 0;
2547 return false;
2550 /* This is an error condition, either no codec was found, or reading
2551 * the codec file failed part way through, either way, skip the track */
2552 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2553 /* We should not use gui_syncplash from audio thread! */
2554 gui_syncsplash(HZ*2, msgbuf);
2555 /* Skip invalid entry from playlist. */
2556 playlist_skip_entry(NULL, last_peek_offset);
2557 tracks[track_widx].taginfo_ready = false;
2558 goto peek_again;
2561 struct mp3entry *track_id3;
2563 if (track_widx == track_ridx)
2564 track_id3 = &curtrack_id3;
2565 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2566 track_id3 = &nexttrack_id3;
2567 else
2568 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2570 set_filebuf_watermark(buffer_margin, 0);
2571 track_id3->elapsed = 0;
2573 if (offset > 0)
2575 switch (track_id3->codectype) {
2576 case AFMT_MPA_L1:
2577 case AFMT_MPA_L2:
2578 case AFMT_MPA_L3:
2579 file_offset = offset;
2580 track_id3->offset = offset;
2581 audio_set_elapsed(track_id3);
2582 ci.curpos = offset;
2583 break;
2585 case AFMT_WAVPACK:
2586 file_offset = offset;
2587 track_id3->offset = offset;
2588 track_id3->elapsed = track_id3->length / 2;
2589 ci.curpos = offset;
2590 break;
2592 case AFMT_OGG_VORBIS:
2593 case AFMT_SPEEX:
2594 case AFMT_FLAC:
2595 case AFMT_PCM_WAV:
2596 case AFMT_A52:
2597 case AFMT_AAC:
2598 case AFMT_MPC:
2599 case AFMT_APE:
2600 track_id3->offset = offset;
2601 break;
2605 logf("alt:%s", trackname);
2607 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, TYPE_AUDIO);
2609 if (tracks[track_widx].audio_hid <= 0)
2610 return false;
2612 if (start_play)
2614 buf_request_buffer_handle(tracks[track_widx].audio_hid);
2617 track_widx++;
2618 track_widx &= MAX_TRACK_MASK;
2620 return true;
2623 /* Send callback events to notify about new tracks. */
2624 static void audio_generate_postbuffer_events(void)
2626 int cur_idx;
2627 int last_idx = -1;
2629 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2631 if (audio_have_tracks())
2633 cur_idx = track_ridx;
2635 while (1) {
2636 if (!tracks[cur_idx].event_sent)
2638 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2640 /* Mark the event 'sent' even if we don't really send one */
2641 tracks[last_idx].event_sent = true;
2642 if (track_buffer_callback && tracks[last_idx].id3_hid > 0)
2643 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), false);
2645 last_idx = cur_idx;
2647 if (cur_idx == track_widx)
2648 break;
2649 cur_idx++;
2650 cur_idx &= MAX_TRACK_MASK;
2653 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2655 tracks[last_idx].event_sent = true;
2656 if (track_buffer_callback && tracks[last_idx].id3_hid > 0)
2657 track_buffer_callback(bufgetid3(tracks[last_idx].id3_hid), true);
2662 static void low_buffer_callback(void)
2664 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
2665 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
2668 static void audio_fill_file_buffer(bool start_play, size_t offset)
2670 bool had_next_track = audio_next_track() != NULL;
2671 bool continue_buffering;
2673 /* Must reset the buffer before use if trashed or voice only - voice
2674 file size shouldn't have changed so we can go straight from
2675 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2676 if (buffer_state != BUFFER_STATE_INITIALIZED)
2677 audio_reset_buffer();
2679 logf("Starting buffer fill");
2681 if (!start_play)
2682 audio_clear_track_entries(false);
2684 /* Save the current resume position once. */
2685 playlist_update_resume_info(audio_current_track());
2687 do {
2688 continue_buffering = audio_load_track(offset, start_play);
2689 start_play = false;
2690 offset = 0;
2691 sleep(1);
2692 } while (continue_buffering);
2694 if (!had_next_track && audio_next_track())
2695 track_changed = true;
2697 audio_generate_postbuffer_events();
2698 register_buffer_low_callback(low_buffer_callback);
2701 static void audio_rebuffer(void)
2703 logf("Forcing rebuffer");
2705 clear_track_info(CUR_TI);
2707 /* Reset track pointers */
2708 track_widx = track_ridx;
2709 audio_clear_track_entries(true);
2711 /* Just to make sure none were forgotten */
2712 audio_release_tracks();
2714 /* Fill the buffer */
2715 last_peek_offset = -1;
2716 ci.curpos = 0;
2718 if (!CUR_TI->taginfo_ready)
2719 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2721 audio_fill_file_buffer(false, 0);
2724 static int audio_check_new_track(void)
2726 DEBUGF("audio_check_new_track\n");
2728 int track_count = audio_track_count();
2729 int old_track_ridx = track_ridx;
2730 bool forward;
2732 if (dir_skip)
2734 dir_skip = false;
2735 if (playlist_next_dir(ci.new_track))
2737 ci.new_track = 0;
2738 audio_rebuffer();
2739 goto skip_done;
2741 else
2743 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2744 return Q_CODEC_REQUEST_FAILED;
2748 if (new_playlist)
2749 ci.new_track = 0;
2751 /* If the playlist isn't that big */
2752 if (!playlist_check(ci.new_track))
2754 if (ci.new_track >= 0)
2756 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2757 return Q_CODEC_REQUEST_FAILED;
2759 /* Find the beginning backward if the user over-skips it */
2760 while (!playlist_check(++ci.new_track))
2761 if (ci.new_track >= 0)
2763 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2764 return Q_CODEC_REQUEST_FAILED;
2767 /* Update the playlist */
2768 last_peek_offset -= ci.new_track;
2770 if (playlist_next(ci.new_track) < 0)
2772 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2773 return Q_CODEC_REQUEST_FAILED;
2776 if (new_playlist)
2778 ci.new_track = 1;
2779 new_playlist = false;
2782 /* Save the old track */
2783 /* prev_ti = CUR_TI; */
2784 copy_mp3entry(&prevtrack_id3, &curtrack_id3);
2786 int i, idx;
2787 for (i = 0; i < ci.new_track; i++)
2789 idx = (track_ridx + i) & MAX_TRACK_MASK;
2790 if (buf_handle_offset(tracks[idx].audio_hid) > 0)
2791 clear_track_info(&tracks[idx]);
2794 /* Move to the new track */
2795 track_ridx += ci.new_track;
2796 track_ridx &= MAX_TRACK_MASK;
2798 buf_set_base_handle(CUR_TI->audio_hid);
2800 if (automatic_skip)
2802 playlist_end = false;
2803 wps_offset = -ci.new_track;
2806 track_changed = true;
2808 /* If it is not safe to even skip this many track entries */
2809 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
2811 ci.new_track = 0;
2812 audio_rebuffer();
2813 goto skip_done;
2816 forward = ci.new_track > 0;
2817 ci.new_track = 0;
2819 /* If the target track is clearly not in memory */
2820 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
2822 audio_rebuffer();
2823 goto skip_done;
2826 /* The track may be in memory, see if it really is */
2827 if (!forward)
2829 int cur_idx = track_ridx;
2830 bool taginfo_ready = true;
2831 bool wrap = track_ridx > old_track_ridx;
2833 while (1)
2835 cur_idx++;
2836 cur_idx &= MAX_TRACK_MASK;
2837 if (!(wrap || cur_idx < old_track_ridx))
2838 break;
2840 /* If we hit a track in between without valid tag info, bail */
2841 if (!tracks[cur_idx].taginfo_ready)
2843 taginfo_ready = false;
2844 break;
2847 if (!taginfo_ready)
2849 audio_rebuffer();
2853 skip_done:
2854 audio_update_trackinfo();
2855 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
2856 return Q_CODEC_REQUEST_COMPLETE;
2859 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
2860 bool last_track))
2862 track_buffer_callback = handler;
2865 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
2866 bool last_track))
2868 track_unbuffer_callback = handler;
2871 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
2873 track_changed_callback = handler;
2876 unsigned long audio_prev_elapsed(void)
2878 return prev_track_elapsed;
2881 static void audio_stop_codec_flush(void)
2883 ci.stop_codec = true;
2884 pcmbuf_pause(true);
2886 while (audio_codec_loaded)
2887 yield();
2889 /* If the audio codec is not loaded any more, and the audio is still
2890 * playing, it is now and _only_ now safe to call this function from the
2891 * audio thread */
2892 if (pcm_is_playing())
2893 pcmbuf_play_stop();
2894 pcmbuf_pause(paused);
2897 static void audio_stop_playback(void)
2899 /* If we were playing, save resume information */
2900 if (playing)
2902 struct mp3entry *id3 = NULL;
2904 if (!playlist_end || !ci.stop_codec)
2906 /* Set this early, the outside code yields and may allow the codec
2907 to try to wait for a reply on a buffer wait */
2908 ci.stop_codec = true;
2909 id3 = audio_current_track();
2912 /* Save the current playing spot, or NULL if the playlist has ended */
2913 playlist_update_resume_info(id3);
2915 prev_track_elapsed = curtrack_id3.elapsed;
2917 /* Increment index so runtime info is saved in audio_clear_track_entries().
2918 * Done here, as audio_stop_playback() may be called more than once.
2919 * Don't update runtime unless playback is stopped because of end of playlist.
2920 * Updating runtime when manually stopping a tracks, can destroy autoscores
2921 * and playcounts.
2923 if (playlist_end)
2925 track_ridx++;
2926 track_ridx &= MAX_TRACK_MASK;
2930 paused = false;
2931 audio_stop_codec_flush();
2932 playing = false;
2934 /* Close all tracks */
2935 audio_release_tracks();
2937 /* Mark all entries null. */
2938 audio_clear_track_entries(false);
2940 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2941 memset(&nexttrack_id3, 0, sizeof(struct mp3entry));
2944 static void audio_play_start(size_t offset)
2946 #if INPUT_SRC_CAPS != 0
2947 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2948 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2949 #endif
2951 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2952 paused = false;
2953 audio_stop_codec_flush();
2955 track_changed = true;
2956 playlist_end = false;
2958 playing = true;
2960 ci.new_track = 0;
2961 ci.seek_time = 0;
2962 wps_offset = 0;
2964 sound_set_volume(global_settings.volume);
2965 track_widx = track_ridx = 0;
2967 /* Mark all entries null. */
2968 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
2970 last_peek_offset = -1;
2972 /* Officially playing */
2973 queue_reply(&audio_queue, 1);
2975 audio_fill_file_buffer(true, offset);
2977 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
2978 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
2982 /* Invalidates all but currently playing track. */
2983 static void audio_invalidate_tracks(void)
2985 if (audio_have_tracks())
2987 last_peek_offset = 0;
2988 playlist_end = false;
2989 track_widx = track_ridx;
2991 /* Mark all other entries null (also buffered wrong metadata). */
2992 audio_clear_track_entries(true);
2994 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
2996 audio_fill_file_buffer(false, 0);
3000 static void audio_new_playlist(void)
3002 /* Prepare to start a new fill from the beginning of the playlist */
3003 last_peek_offset = -1;
3004 if (audio_have_tracks())
3006 if (paused)
3007 skipped_during_pause = true;
3008 playlist_end = false;
3009 track_widx = track_ridx;
3010 audio_clear_track_entries(true);
3012 track_widx++;
3013 track_widx &= MAX_TRACK_MASK;
3015 /* Mark the current track as invalid to prevent skipping back to it */
3016 CUR_TI->taginfo_ready = false;
3019 /* Signal the codec to initiate a track change forward */
3020 new_playlist = true;
3021 ci.new_track = 1;
3023 /* Officially playing */
3024 queue_reply(&audio_queue, 1);
3026 audio_fill_file_buffer(false, 0);
3029 static void audio_initiate_track_change(long direction)
3031 playlist_end = false;
3032 ci.new_track += direction;
3033 wps_offset -= direction;
3034 if (paused)
3035 skipped_during_pause = true;
3038 static void audio_initiate_dir_change(long direction)
3040 playlist_end = false;
3041 dir_skip = true;
3042 ci.new_track = direction;
3043 if (paused)
3044 skipped_during_pause = true;
3048 * Layout audio buffer as follows - iram buffer depends on target:
3049 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3051 static void audio_reset_buffer(void)
3053 /* see audio_get_recording_buffer if this is modified */
3054 logf("audio_reset_buffer");
3056 /* If the setup of anything allocated before the file buffer is
3057 changed, do check the adjustments after the buffer_alloc call
3058 as it will likely be affected and need sliding over */
3060 /* Initially set up file buffer as all space available */
3061 malloc_buf = audiobuf + talk_get_bufsize();
3062 /* Align the malloc buf to line size. Especially important to cf
3063 targets that do line reads/writes. */
3064 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
3065 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
3066 filebuflen = audiobufend - filebuf;
3068 /* Allow for codec swap space at end of audio buffer */
3069 if (talk_voice_required())
3071 /* Layout of swap buffer:
3072 * #ifdef IRAM_STEAL (dedicated iram_buf):
3073 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3074 * #else:
3075 * audiobuf...|dram_buf|iram_buf|audiobufend
3077 #ifdef PLAYBACK_VOICE
3078 /* Check for an absolutely nasty situation which should never,
3079 ever happen - frankly should just panic */
3080 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
3082 logf("buffer reset with voice swapped");
3084 /* line align length which line aligns the calculations below since
3085 all sizes are also at least line aligned - needed for memswap128 */
3086 filebuflen &= ~15;
3087 #ifdef IRAM_STEAL
3088 filebuflen -= CODEC_SIZE;
3089 #else
3090 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
3091 #endif
3092 /* Allocate buffers for swapping voice <=> audio */
3093 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3094 and out of the way of buffer usage or else a call to audio_get_buffer
3095 and subsequent buffer use might trash the swap space. A plugin
3096 initializing IRAM after getting the full buffer would present similar
3097 problem. Options include: failing the request if the other buffer
3098 has been obtained already or never allowing use of the voice IRAM
3099 buffer within the audio buffer. Using buffer_alloc basically
3100 implements the second in a more convenient way. */
3101 dram_buf = filebuf + filebuflen;
3103 #ifdef IRAM_STEAL
3104 /* Allocate voice IRAM swap buffer once */
3105 if (iram_buf == NULL)
3107 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
3108 /* buffer_alloc moves audiobuf; this is safe because only the end
3109 * has been touched so far in this function and the address of
3110 * filebuf + filebuflen is not changed */
3111 malloc_buf += CODEC_IRAM_SIZE;
3112 filebuf += CODEC_IRAM_SIZE;
3113 filebuflen -= CODEC_IRAM_SIZE;
3115 #else
3116 /* Allocate iram_buf after dram_buf */
3117 iram_buf = dram_buf + CODEC_SIZE;
3118 #endif /* IRAM_STEAL */
3119 #endif /* PLAYBACK_VOICE */
3121 else
3123 #ifdef PLAYBACK_VOICE
3124 /* No swap buffers needed */
3125 iram_buf = NULL;
3126 dram_buf = NULL;
3127 #endif
3130 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3131 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
3133 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3134 will already be line aligned */
3135 filebuflen &= ~3;
3137 buffering_init(filebuf, filebuflen);
3139 /* Clear any references to the file buffer */
3140 buffer_state = BUFFER_STATE_INITIALIZED;
3142 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3143 /* Make sure everything adds up - yes, some info is a bit redundant but
3144 aids viewing and the sumation of certain variables should add up to
3145 the location of others. */
3147 size_t pcmbufsize;
3148 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
3149 logf("mabuf: %08X", (unsigned)malloc_buf);
3150 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
3151 logf("fbuf: %08X", (unsigned)filebuf);
3152 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
3153 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
3154 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
3155 logf("pcmb: %08X", (unsigned)pcmbuf);
3156 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
3157 if (dram_buf)
3159 logf("dramb: %08X", (unsigned)dram_buf);
3160 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
3162 if (iram_buf)
3164 logf("iramb: %08X", (unsigned)iram_buf);
3165 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
3168 #endif
3171 static void audio_thread(void)
3173 struct queue_event ev;
3175 pcm_postinit();
3177 #ifdef PLAYBACK_VOICE
3178 /* Unlock semaphore that init stage locks before creating this thread */
3179 semaphore_release(&sem_codecthread);
3181 /* Buffers must be set up by now - should panic - really */
3182 if (buffer_state != BUFFER_STATE_INITIALIZED)
3184 logf("audio_thread start: no buffer");
3187 /* Have to wait for voice to load up or else the codec swap will be
3188 invalid when an audio codec is loaded */
3189 wait_for_voice_swap_in();
3190 #endif
3192 while (1)
3194 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3196 switch (ev.id) {
3197 case Q_AUDIO_FILL_BUFFER:
3198 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3199 if (!playing || playlist_end || ci.stop_codec)
3200 break;
3201 audio_fill_file_buffer(false, 0);
3202 break;
3204 case Q_AUDIO_PLAY:
3205 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3206 if (playing && ev.data <= 0)
3207 audio_new_playlist();
3208 else
3210 audio_stop_playback();
3211 audio_play_start((size_t)ev.data);
3213 break;
3215 case Q_AUDIO_STOP:
3216 LOGFQUEUE("audio < Q_AUDIO_STOP");
3217 if (playing)
3218 audio_stop_playback();
3219 if (ev.data != 0)
3220 queue_clear(&audio_queue);
3221 break;
3223 case Q_AUDIO_PAUSE:
3224 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3225 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3226 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3227 skipped_during_pause = false;
3228 if (!playing)
3229 break;
3230 pcmbuf_pause((bool)ev.data);
3231 paused = (bool)ev.data;
3232 break;
3234 case Q_AUDIO_SKIP:
3235 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3236 audio_initiate_track_change((long)ev.data);
3237 break;
3239 case Q_AUDIO_PRE_FF_REWIND:
3240 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3241 if (!playing)
3242 break;
3243 pcmbuf_pause(true);
3244 break;
3246 case Q_AUDIO_FF_REWIND:
3247 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3248 if (!playing)
3249 break;
3250 ci.seek_time = (long)ev.data+1;
3251 break;
3253 case Q_AUDIO_CHECK_NEW_TRACK:
3254 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3255 queue_reply(&audio_queue, audio_check_new_track());
3256 break;
3258 case Q_AUDIO_DIR_SKIP:
3259 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3260 playlist_end = false;
3261 audio_initiate_dir_change(ev.data);
3262 break;
3264 case Q_AUDIO_FLUSH:
3265 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3266 audio_invalidate_tracks();
3267 break;
3269 case Q_AUDIO_TRACK_CHANGED:
3270 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3271 if (automatic_skip)
3273 wps_offset = 0;
3274 automatic_skip = false;
3275 prevtrack_id3.path[0] = 0;
3277 if (track_changed_callback)
3278 track_changed_callback(&curtrack_id3);
3279 track_changed = true;
3280 playlist_update_resume_info(audio_current_track());
3281 break;
3283 #ifndef SIMULATOR
3284 case SYS_USB_CONNECTED:
3285 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3286 if (playing)
3287 audio_stop_playback();
3288 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3289 usb_wait_for_disconnect(&audio_queue);
3290 /* release tracks to make sure all handles are closed */
3291 audio_release_tracks();
3292 break;
3293 #endif
3295 case SYS_TIMEOUT:
3296 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3297 break;
3299 default:
3300 //LOGFQUEUE("audio < default");
3301 break;
3302 } /* end switch */
3303 } /* end while */
3306 #ifdef ROCKBOX_HAS_LOGF
3307 static void audio_test_track_changed_event(struct mp3entry *id3)
3309 (void)id3;
3311 logf("tce:%s", id3->path);
3313 #endif
3315 /* Initialize the audio system - called from init() in main.c.
3316 * Last function because of all the references to internal symbols
3318 void audio_init(void)
3320 #ifdef PLAYBACK_VOICE
3321 static bool voicetagtrue = true;
3322 static struct mp3entry id3_voice;
3323 struct thread_entry *voice_thread_p = NULL;
3324 #endif
3325 struct thread_entry *audio_thread_p;
3327 /* Can never do this twice */
3328 if (audio_is_initialized)
3330 logf("audio: already initialized");
3331 return;
3334 logf("audio: initializing");
3336 /* Initialize queues before giving control elsewhere in case it likes
3337 to send messages. Thread creation will be delayed however so nothing
3338 starts running until ready if something yields such as talk_init. */
3339 #ifdef PLAYBACK_VOICE
3340 /* Take ownership of lock to prevent playback of anything before audio
3341 hardware is initialized - audio thread unlocks it after final init
3342 stage */
3343 semaphore_init(&sem_codecthread, 1, 0);
3344 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3345 #endif
3346 queue_init(&audio_queue, true);
3347 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3348 queue_init(&codec_queue, true);
3349 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3351 pcm_init();
3353 #ifdef ROCKBOX_HAS_LOGF
3354 audio_set_track_changed_event(audio_test_track_changed_event);
3355 #endif
3357 /* Initialize codec api. */
3358 ci.read_filebuf = codec_filebuf_callback;
3359 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3360 ci.get_codec_memory = codec_get_memory_callback;
3361 ci.request_buffer = codec_request_buffer_callback;
3362 ci.advance_buffer = codec_advance_buffer_callback;
3363 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3364 ci.request_next_track = codec_request_next_track_callback;
3365 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3366 ci.seek_buffer = codec_seek_buffer_callback;
3367 ci.seek_complete = codec_seek_complete_callback;
3368 ci.set_elapsed = codec_set_elapsed_callback;
3369 ci.set_offset = codec_set_offset_callback;
3370 ci.configure = codec_configure_callback;
3371 ci.discard_codec = codec_discard_codec_callback;
3373 /* Initialize voice codec api. */
3374 #ifdef PLAYBACK_VOICE
3375 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3376 memset(&id3_voice, 0, sizeof(id3_voice));
3377 ci_voice.read_filebuf = voice_filebuf_callback;
3378 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3379 ci_voice.get_codec_memory = voice_get_memory_callback;
3380 ci_voice.request_buffer = voice_request_buffer_callback;
3381 ci_voice.advance_buffer = voice_advance_buffer_callback;
3382 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3383 ci_voice.request_next_track = voice_request_next_track_callback;
3384 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3385 ci_voice.seek_buffer = voice_seek_buffer_callback;
3386 ci_voice.seek_complete = voice_do_nothing;
3387 ci_voice.set_elapsed = voice_set_elapsed_callback;
3388 ci_voice.set_offset = voice_set_offset_callback;
3389 ci_voice.configure = voice_configure_callback;
3390 ci_voice.discard_codec = voice_do_nothing;
3391 ci_voice.taginfo_ready = &voicetagtrue;
3392 ci_voice.id3 = &id3_voice;
3393 id3_voice.frequency = 11200;
3394 id3_voice.length = 1000000L;
3395 #endif
3397 /* initialize the buffer */
3398 filebuf = audiobuf;
3400 /* audio_reset_buffer must to know the size of voice buffer so init
3401 talk first */
3402 talk_init();
3404 codec_thread_p = create_thread(
3405 codec_thread, codec_stack, sizeof(codec_stack),
3406 CREATE_THREAD_FROZEN,
3407 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3408 IF_COP(, CPU));
3410 audio_thread_p = create_thread(audio_thread, audio_stack,
3411 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3412 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3413 IF_COP(, CPU));
3415 #ifdef PLAYBACK_VOICE
3416 /* TODO: Change this around when various speech codecs can be used */
3417 if (talk_voice_required())
3419 logf("Starting voice codec");
3420 queue_init(&voice_queue, true);
3421 voice_thread_p = create_thread(voice_thread, voice_stack,
3422 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3423 voice_thread_name
3424 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3426 #endif
3428 /* Set crossfade setting for next buffer init which should be about... */
3429 pcmbuf_crossfade_enable(global_settings.crossfade);
3431 /* ...now! Set up the buffers */
3432 audio_reset_buffer();
3434 /* Probably safe to say */
3435 audio_is_initialized = true;
3437 sound_settings_apply();
3438 #ifdef HAVE_WM8758
3439 eq_hw_enable(global_settings.eq_hw_enabled);
3440 #endif
3441 #ifndef HAVE_FLASH_STORAGE
3442 audio_set_buffer_margin(global_settings.buffer_margin);
3443 #endif
3445 /* it's safe to let the threads run now */
3446 thread_thaw(codec_thread_p);
3447 #ifdef PLAYBACK_VOICE
3448 if (voice_thread_p)
3449 thread_thaw(voice_thread_p);
3450 #endif
3451 thread_thaw(audio_thread_p);
3452 } /* audio_init */