Update several codec Makefiles so that the codec libs build again on Coldfire targets...
[Rockbox.git] / apps / playback.c
blobde6646a23221519d73ac31975ff2a86243a70ad3
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 "lcd.h"
38 #include "font.h"
39 #include "button.h"
40 #include "kernel.h"
41 #include "tree.h"
42 #include "debug.h"
43 #include "sprintf.h"
44 #include "settings.h"
45 #include "codecs.h"
46 #include "audio.h"
47 #include "logf.h"
48 #include "mp3_playback.h"
49 #include "usb.h"
50 #include "status.h"
51 #include "main_menu.h"
52 #include "ata.h"
53 #include "screens.h"
54 #include "playlist.h"
55 #include "playback.h"
56 #include "pcmbuf.h"
57 #include "pcm_playback.h"
58 #include "pcm_record.h"
59 #include "buffer.h"
60 #include "dsp.h"
61 #include "abrepeat.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"
78 #ifdef HAVE_RECORDING
79 #include "recording.h"
80 #endif
82 #define PLAYBACK_VOICE
85 /* default point to start buffer refill */
86 #define AUDIO_DEFAULT_WATERMARK (1024*512)
87 /* amount of data to read in one read() call */
88 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
89 /* point at which the file buffer will fight for CPU time */
90 #define AUDIO_FILEBUF_CRITICAL (1024*128)
91 /* amount of guess-space to allow for codecs that must hunt and peck
92 * for their correct seeek target, 32k seems a good size */
93 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
95 /* macros to enable logf for queues */
96 #ifdef SIMULATOR
97 #define PLAYBACK_LOGQUEUES /* Define this for logf output of all queuing */
98 #endif
100 #ifdef PLAYBACK_LOGQUEUES
101 #define LOGFQUEUE(s) logf("%s", s)
102 #else
103 #define LOGFQUEUE(s)
104 #endif
106 enum {
107 Q_AUDIO_PLAY = 1,
108 Q_AUDIO_STOP,
109 Q_AUDIO_PAUSE,
110 Q_AUDIO_SKIP,
111 Q_AUDIO_PRE_FF_REWIND,
112 Q_AUDIO_FF_REWIND,
113 Q_AUDIO_REBUFFER_SEEK,
114 Q_AUDIO_CHECK_NEW_TRACK,
115 Q_AUDIO_FLUSH,
116 Q_AUDIO_TRACK_CHANGED,
117 Q_AUDIO_DIR_SKIP,
118 Q_AUDIO_NEW_PLAYLIST,
119 Q_AUDIO_POSTINIT,
120 Q_AUDIO_FILL_BUFFER,
122 Q_CODEC_REQUEST_PENDING,
123 Q_CODEC_REQUEST_COMPLETE,
124 Q_CODEC_REQUEST_FAILED,
126 Q_VOICE_PLAY,
127 Q_VOICE_STOP,
129 Q_CODEC_LOAD,
130 Q_CODEC_LOAD_DISK,
132 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
133 Q_ENCODER_LOAD_DISK,
134 Q_ENCODER_RECORD,
135 #endif
138 /* As defined in plugins/lib/xxx2wav.h */
139 #if MEM > 1
140 #define MALLOC_BUFSIZE (512*1024)
141 #define GUARD_BUFSIZE (32*1024)
142 #else
143 #define MALLOC_BUFSIZE (100*1024)
144 #define GUARD_BUFSIZE (8*1024)
145 #endif
147 /* As defined in plugin.lds */
148 #if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
149 #define CODEC_IRAM_ORIGIN 0x4000c000
150 #elif defined(IAUDIO_X5)
151 #define CODEC_IRAM_ORIGIN 0x10014000
152 #else
153 #define CODEC_IRAM_ORIGIN 0x1000c000
154 #endif
155 #define CODEC_IRAM_SIZE 0xc000
157 #ifndef SIMULATOR
158 extern bool audio_is_initialized;
159 #else
160 static bool audio_is_initialized = false;
161 #endif
164 /* Variables are commented with the threads that use them: *
165 * A=audio, C=codec, V=voice. A suffix of - indicates that *
166 * the variable is read but not updated on that thread. */
168 /* Main state control */
169 static struct event_queue codec_callback_queue; /* Queue for codec callback responses */
170 static volatile bool audio_codec_loaded; /* Is codec loaded? (C/A-) */
171 static volatile bool playing; /* Is audio playing? (A) */
172 static volatile bool paused; /* Is audio paused? (A/C-) */
173 static volatile bool filling IDATA_ATTR; /* Is file buffer currently being refilled? (A/C-) */
175 /* Ring buffer where tracks and codecs are loaded */
176 static char *filebuf; /* Pointer to start of ring buffer (A/C-) */
177 size_t filebuflen; /* Total size of the ring buffer FIXME: make static (A/C-)*/
178 static volatile size_t buf_ridx IDATA_ATTR; /* Ring buffer read position (A/C) FIXME? should be (C/A-) */
179 static volatile size_t buf_widx IDATA_ATTR; /* Ring buffer read position (A/C-) */
181 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
182 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
183 #define RINGBUF_ADD_CROSS(p1,v,p2) ((p1<p2)?(int)(p1+v)-(int)p2:(int)(p1+v-p2)-(int)filebuflen)
184 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx) /* Bytes available in the buffer */
186 /* Track info buffer */
187 static struct track_info tracks[MAX_TRACK]; /* Track info structure about songs in the file buffer (A/C-) */
188 static volatile int track_ridx; /* Track being decoded (A/C-) */
189 static int track_widx; /* Track being buffered (A) */
190 static bool track_changed; /* Set to indicate track has changed (A) */
191 static struct track_info *prev_ti; /* Pointer to previous track played info (A/C-) */
193 #define CUR_TI (&tracks[track_ridx]) /* Pointer to current track playing info (A/C-) */
195 /* Audio buffering controls */
196 static int last_peek_offset; /* Step count to the next unbuffered track (A) */
197 static int current_fd; /* Partially loaded track file handle to continue buffering (A) */
199 /* Scrobbler support */
200 static unsigned long prev_track_elapsed; /* Previous track elapsed time (C/A-) */
202 /* Track change controls */
203 static bool automatic_skip = false; /* Was the skip being executed manual or automatic? (C/A-) */
204 static bool playlist_end = false; /* Have we reached end of the current playlist? (A) */
205 static bool dir_skip = false; /* Is a directory skip pending? (A) */
206 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
207 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
209 /* Callbacks.. */
210 void (*track_changed_callback)(struct mp3entry *id3); /* ...when current track has really changed */
211 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track); /* ...when track has been buffered */
212 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track); /* ...when track is being unbuffered */
214 /* Configuration */
215 static size_t conf_watermark; /* Low water mark (A/C) FIXME */
216 static size_t conf_filechunk; /* Largest chunk the codec accepts (A/C) FIXME */
217 static size_t conf_preseek; /* Codec pre-seek margin (A/C) FIXME */
218 static size_t buffer_margin; /* Buffer margin aka anti-skip buffer (A/C-) */
219 static bool v1first = false; /* ID3 data control, true if V1 then V2 (A) */
221 /* Multiple threads */
222 static const char *get_codec_filename(int enc_spec); /* Returns codec filename (A-/C-/V-) */
223 static void set_filebuf_watermark(int seconds); /* Set low watermark (A/C) FIXME */
225 /* Audio thread */
226 static struct event_queue audio_queue;
227 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
228 static const char audio_thread_name[] = "audio";
230 static void audio_thread(void);
231 static void audio_initiate_track_change(long direction);
232 static bool audio_have_tracks(void);
233 static void audio_reset_buffer(void);
235 /* Codec thread */
236 extern struct codec_api ci;
237 static struct event_queue codec_queue;
238 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
239 IBSS_ATTR;
240 static const char codec_thread_name[] = "codec";
241 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
243 volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
245 /* Voice thread */
246 #ifdef PLAYBACK_VOICE
248 extern struct codec_api ci_voice;
250 static struct thread_entry *voice_thread_p = NULL;
251 static struct event_queue voice_queue;
252 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
253 IBSS_ATTR;
254 static const char voice_thread_name[] = "voice codec";
256 /* Voice codec swapping control */
257 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
259 #ifdef SIMULATOR
260 static unsigned char sim_iram[CODEC_IRAM_SIZE]; /* IRAM codec swap buffer for sim*/
261 #undef CODEC_IRAM_ORIGIN
262 #define CODEC_IRAM_ORIGIN sim_iram
263 #endif
265 static unsigned char *iram_buf[2]; /* Ptr to IRAM buffers for normal/voice codecs */
266 static unsigned char *dram_buf[2]; /* Ptr to DRAM buffers for normal/voice codecs */
267 static struct mutex mutex_codecthread; /* Mutex to control which codec (normal/voice) is running */
269 /* Voice state */
270 static volatile bool voice_thread_start; /* Set to trigger voice playback (A/V) */
271 static volatile bool voice_is_playing; /* Is voice currently playing? (V) */
272 static volatile bool voice_codec_loaded; /* Is voice codec loaded (V/A-) */
273 static char *voicebuf;
274 static size_t voice_remaining;
276 static void (*voice_getmore)(unsigned char** start, int* size);
278 struct voice_info {
279 void (*callback)(unsigned char **start, int *size);
280 int size;
281 char *buf;
283 static void voice_thread(void);
285 #endif /* PLAYBACK_VOICE */
287 /* --- External interfaces --- */
289 void mp3_play_data(const unsigned char* start, int size,
290 void (*get_more)(unsigned char** start, int* size))
292 #ifdef PLAYBACK_VOICE
293 static struct voice_info voice_clip;
294 voice_clip.callback = get_more;
295 voice_clip.buf = (char *)start;
296 voice_clip.size = size;
297 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
298 queue_post(&voice_queue, Q_VOICE_STOP, 0);
299 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
300 queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip);
301 voice_thread_start = true;
302 trigger_cpu_boost();
303 #else
304 (void) start;
305 (void) size;
306 (void) get_more;
307 #endif
310 void mp3_play_stop(void)
312 #ifdef PLAYBACK_VOICE
313 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
314 queue_post(&voice_queue, Q_VOICE_STOP, (void *)1);
315 #endif
318 bool mp3_pause_done(void)
320 return pcm_is_paused();
323 void mpeg_id3_options(bool _v1first)
325 v1first = _v1first;
328 void audio_load_encoder(int enc_id)
330 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
331 const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER);
332 if (!enc_fn)
333 return;
335 audio_remove_encoder();
337 LOGFQUEUE("audio > codec Q_ENCODER_LOAD_DISK");
338 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn);
340 while (!ci.enc_codec_loaded)
341 yield();
342 #endif
343 return;
344 (void)enc_id;
345 } /* audio_load_encoder */
347 void audio_remove_encoder(void)
349 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
350 /* force encoder codec unload (if previously loaded) */
351 if (!ci.enc_codec_loaded)
352 return;
354 ci.stop_codec = true;
355 while (ci.enc_codec_loaded)
356 yield();
357 #endif
358 } /* audio_remove_encoder */
360 struct mp3entry* audio_current_track(void)
362 const char *filename;
363 const char *p;
364 static struct mp3entry temp_id3;
365 int cur_idx;
366 int offset = ci.new_track + wps_offset;
368 cur_idx = track_ridx + offset;
369 cur_idx &= MAX_TRACK_MASK;
371 if (tracks[cur_idx].taginfo_ready)
372 return &tracks[cur_idx].id3;
374 memset(&temp_id3, 0, sizeof(struct mp3entry));
376 filename = playlist_peek(offset);
377 if (!filename)
378 filename = "No file!";
380 #ifdef HAVE_TC_RAMCACHE
381 if (tagcache_fill_tags(&temp_id3, filename))
382 return &temp_id3;
383 #endif
385 p = strrchr(filename, '/');
386 if (!p)
387 p = filename;
388 else
389 p++;
391 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
392 temp_id3.title = &temp_id3.path[0];
394 return &temp_id3;
397 struct mp3entry* audio_next_track(void)
399 int next_idx = track_ridx;
401 if (!audio_have_tracks())
402 return NULL;
404 next_idx++;
405 next_idx &= MAX_TRACK_MASK;
407 if (!tracks[next_idx].taginfo_ready)
408 return NULL;
410 return &tracks[next_idx].id3;
413 bool audio_has_changed_track(void)
415 if (track_changed)
417 track_changed = false;
418 return true;
421 return false;
424 void audio_play(long offset)
426 logf("audio_play");
428 #ifdef PLAYBACK_VOICE
429 /* Truncate any existing voice output so we don't have spelling
430 * etc. over the first part of the played track */
431 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
432 queue_post(&voice_queue, Q_VOICE_STOP, (void *)1);
433 #endif
435 /* Start playback */
436 if (playing && offset <= 0)
438 LOGFQUEUE("audio > audio Q_AUDIO_NEW_PLAYLIST");
439 queue_post(&audio_queue, Q_AUDIO_NEW_PLAYLIST, 0);
441 else
443 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
444 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
445 LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
446 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
449 /* Don't return until playback has actually started */
450 while (!playing)
451 yield();
454 void audio_stop(void)
456 /* Stop playback */
457 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
458 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
460 /* Don't return until playback has actually stopped */
461 while(playing)
462 yield();
465 void audio_pause(void)
467 LOGFQUEUE("audio > audio Q_AUDIO_PAUSE");
468 queue_post(&audio_queue, Q_AUDIO_PAUSE, (void *)true);
471 void audio_resume(void)
473 LOGFQUEUE("audio > audio Q_AUDIO_PAUSE resume");
474 queue_post(&audio_queue, Q_AUDIO_PAUSE, (void *)false);
477 void audio_next(void)
479 if (playlist_check(ci.new_track + wps_offset + 1))
481 if (global_settings.beep)
482 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
484 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
485 queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1);
486 /* Keep wps fast while our message travels inside deep playback queues. */
487 wps_offset++;
488 track_changed = true;
490 else
492 /* No more tracks. */
493 if (global_settings.beep)
494 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
498 void audio_prev(void)
500 if (playlist_check(ci.new_track + wps_offset - 1))
502 if (global_settings.beep)
503 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
505 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
506 queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1);
507 /* Keep wps fast while our message travels inside deep playback queues. */
508 wps_offset--;
509 track_changed = true;
511 else
513 /* No more tracks. */
514 if (global_settings.beep)
515 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
519 void audio_next_dir(void)
521 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
522 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, (void *)1);
525 void audio_prev_dir(void)
527 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
528 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, (void *)-1);
531 void audio_pre_ff_rewind(void)
533 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
534 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
537 void audio_ff_rewind(long newpos)
539 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
540 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos);
543 void audio_flush_and_reload_tracks(void)
545 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
546 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
549 void audio_error_clear(void)
553 int audio_status(void)
555 int ret = 0;
557 if (playing)
558 ret |= AUDIO_STATUS_PLAY;
560 if (paused)
561 ret |= AUDIO_STATUS_PAUSE;
563 #ifdef HAVE_RECORDING
564 /* Do this here for constitency with mpeg.c version */
565 ret |= pcm_rec_status();
566 #endif
568 return ret;
571 bool audio_query_poweroff(void)
573 return !(playing && paused);
576 int audio_get_file_pos(void)
578 return 0;
581 void audio_set_buffer_margin(int setting)
583 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
584 buffer_margin = lookup[setting];
585 logf("buffer margin: %ds", buffer_margin);
586 set_filebuf_watermark(buffer_margin);
589 /* Set crossfade & PCM buffer length. */
590 void audio_set_crossfade(int enable)
592 size_t size;
593 bool was_playing = (playing && audio_is_initialized);
594 size_t offset = 0;
595 #if MEM > 1
596 int seconds = 1;
597 #endif
599 if (!filebuf)
600 return; /* Audio buffers not yet set up */
602 #if MEM > 1
603 if (enable)
604 seconds = global_settings.crossfade_fade_out_delay
605 + global_settings.crossfade_fade_out_duration;
607 /* Buffer has to be at least 2s long. */
608 seconds += 2;
609 logf("buf len: %d", seconds);
610 size = seconds * (NATIVE_FREQUENCY*4);
611 #else
612 enable = 0;
613 size = NATIVE_FREQUENCY*2;
614 #endif
615 if (pcmbuf_get_bufsize() == size)
616 return ;
618 if (was_playing)
620 /* Store the track resume position */
621 offset = CUR_TI->id3.offset;
623 /* Playback has to be stopped before changing the buffer size. */
624 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK));
625 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
626 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
627 while (audio_codec_loaded)
628 yield();
631 voice_stop();
633 /* Re-initialize audio system. */
634 pcmbuf_init(size);
635 pcmbuf_crossfade_enable(enable);
636 audio_reset_buffer();
637 logf("abuf:%dB", pcmbuf_get_bufsize());
638 logf("fbuf:%dB", filebuflen);
640 voice_init();
642 /* Restart playback. */
643 if (was_playing)
645 LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
646 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
648 /* Wait for the playback to start again (and display the splash
649 screen during that period. */
650 while (!playing)
651 yield();
655 void audio_preinit(void)
657 logf("playback system pre-init");
659 filling = false;
660 current_codec = CODEC_IDX_AUDIO;
661 playing = false;
662 paused = false;
663 audio_codec_loaded = false;
664 #ifdef PLAYBACK_VOICE
665 voice_is_playing = false;
666 voice_thread_start = false;
667 voice_codec_loaded = false;
668 #endif
669 track_changed = false;
670 current_fd = -1;
671 track_buffer_callback = NULL;
672 track_unbuffer_callback = NULL;
673 track_changed_callback = NULL;
674 track_ridx = 0; /* Just to prevent CUR_TI from being anything random. */
675 prev_ti = &tracks[MAX_TRACK-1]; /* And prevent prev_ti being random too */
677 mutex_init(&mutex_codecthread);
679 queue_init(&audio_queue, true);
680 queue_init(&codec_queue, true);
681 /* create a private queue */
682 queue_init(&codec_callback_queue, false);
684 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
685 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING));
688 void audio_init(void)
690 LOGFQUEUE("audio > audio Q_AUDIO_POSTINIT");
691 queue_post(&audio_queue, Q_AUDIO_POSTINIT, 0);
694 void voice_init(void)
696 #ifdef PLAYBACK_VOICE
697 if (!filebuf)
698 return; /* Audio buffers not yet set up */
700 if (voice_thread_p)
701 return;
703 if (!talk_voice_required())
704 return;
706 logf("Starting voice codec");
707 queue_init(&voice_queue, true);
708 voice_thread_p = create_thread(voice_thread, voice_stack,
709 sizeof(voice_stack), voice_thread_name
710 IF_PRIO(, PRIORITY_PLAYBACK));
712 while (!voice_codec_loaded)
713 yield();
714 #endif
715 } /* voice_init */
717 void voice_stop(void)
719 #ifdef PLAYBACK_VOICE
720 /* Messages should not be posted to voice codec queue unless it is the
721 current codec or deadlocks happen.
722 -- jhMikeS */
723 if (current_codec != CODEC_IDX_VOICE)
724 return;
726 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
727 queue_post(&voice_queue, Q_VOICE_STOP, 0);
728 while (voice_is_playing)
729 yield();
730 if (!playing)
731 pcmbuf_play_stop();
732 #endif
733 } /* voice_stop */
737 /* --- Routines called from multiple threads --- */
739 #ifdef PLAYBACK_VOICE
740 static void swap_codec(void)
742 int my_codec = current_codec;
744 logf("swapping out codec:%d", my_codec);
746 /* Save our current IRAM and DRAM */
747 memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN,
748 CODEC_IRAM_SIZE);
749 memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE);
751 /* Release my semaphore */
752 mutex_unlock(&mutex_codecthread);
754 /* Loop until the other codec has locked and run */
755 do {
756 /* Release my semaphore and force a task switch. */
757 yield();
758 } while (my_codec == current_codec);
760 /* Wait for other codec to unlock */
761 mutex_lock(&mutex_codecthread);
763 /* Take control */
764 current_codec = my_codec;
766 /* Reload our IRAM and DRAM */
767 memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec],
768 CODEC_IRAM_SIZE);
769 invalidate_icache();
770 memcpy(codecbuf, dram_buf[my_codec], CODEC_SIZE);
772 logf("resuming codec:%d", my_codec);
774 #endif
776 static void set_filebuf_watermark(int seconds)
778 size_t bytes;
780 if (current_codec == CODEC_IDX_VOICE)
781 return;
783 if (!filebuf)
784 return; /* Audio buffers not yet set up */
786 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
787 bytes = MIN(bytes, filebuflen / 2);
788 conf_watermark = bytes;
791 static const char * get_codec_filename(int enc_spec)
793 const char *fname;
794 int type = enc_spec & CODEC_TYPE_MASK;
795 int afmt = enc_spec & CODEC_AFMT_MASK;
797 if ((unsigned)afmt >= AFMT_NUM_CODECS)
798 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
800 fname = (type == CODEC_TYPE_DECODER) ?
801 audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn;
803 logf("%s: %d - %s",
804 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
805 afmt, fname ? fname : "<unknown>");
807 return fname;
808 } /* get_codec_filename */
811 /* --- Voice thread --- */
813 #ifdef PLAYBACK_VOICE
815 static bool voice_pcmbuf_insert_split_callback(
816 const void *ch1, const void *ch2, size_t length)
818 const char* src[2];
819 char *dest;
820 long input_size;
821 size_t output_size;
823 src[0] = ch1;
824 src[1] = ch2;
826 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
827 length *= 2; /* Length is per channel */
829 while (length)
831 long est_output_size = dsp_output_size(length);
833 while ((dest = pcmbuf_request_voice_buffer(est_output_size,
834 &output_size, playing)) == NULL)
836 if (playing && audio_codec_loaded)
837 swap_codec();
838 else
839 yield();
842 /* Get the real input_size for output_size bytes, guarding
843 * against resampling buffer overflows. */
844 input_size = dsp_input_size(output_size);
846 if (input_size <= 0)
848 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
849 output_size, length, input_size);
850 /* If this happens, there are samples of codec data that don't
851 * become a number of pcm samples, and something is broken */
852 return false;
855 /* Input size has grown, no error, just don't write more than length */
856 if ((size_t)input_size > length)
857 input_size = length;
859 output_size = dsp_process(dest, src, input_size);
861 if (playing)
863 pcmbuf_mix_voice(output_size);
864 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && audio_codec_loaded)
865 swap_codec();
867 else
868 pcmbuf_write_complete(output_size);
870 length -= input_size;
873 return true;
874 } /* voice_pcmbuf_insert_split_callback */
876 static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
878 /* TODO: The audiobuffer API should probably be updated, and be based on
879 * pcmbuf_insert_split(). */
880 long real_length = length;
882 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
883 length /= 2; /* Length is per channel */
885 /* Second channel is only used for non-interleaved stereo. */
886 return voice_pcmbuf_insert_split_callback(buf, buf + (real_length / 2),
887 length);
890 static void* voice_get_memory_callback(size_t *size)
892 *size = 0;
893 return NULL;
896 static void voice_set_elapsed_callback(unsigned int value)
898 (void)value;
901 static void voice_set_offset_callback(size_t value)
903 (void)value;
906 static size_t voice_filebuf_callback(void *ptr, size_t size)
908 (void)ptr;
909 (void)size;
911 return 0;
914 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
916 struct event ev;
918 if (ci_voice.new_track)
920 *realsize = 0;
921 return NULL;
924 while (1)
926 if (voice_is_playing || playing)
927 queue_wait_w_tmo(&voice_queue, &ev, 0);
928 else
929 queue_wait(&voice_queue, &ev);
930 if (!voice_is_playing)
932 if (ev.id == SYS_TIMEOUT)
933 ev.id = Q_AUDIO_PLAY;
936 switch (ev.id) {
937 case Q_AUDIO_PLAY:
938 LOGFQUEUE("voice < Q_AUDIO_PLAY");
939 if (playing)
941 if (audio_codec_loaded)
942 swap_codec();
943 yield();
945 break;
947 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
948 case Q_ENCODER_RECORD:
949 LOGFQUEUE("voice < Q_ENCODER_RECORD");
950 swap_codec();
951 break;
952 #endif
954 case Q_VOICE_STOP:
955 LOGFQUEUE("voice < Q_VOICE_STOP");
956 if (ev.data == (void *)1 && !playing && pcm_is_playing())
957 /* Aborting: Slight hack - flush PCM buffer if
958 only being used for voice */
959 pcmbuf_play_stop();
960 if (voice_is_playing)
962 /* Clear the current buffer */
963 voice_is_playing = false;
964 voice_getmore = NULL;
965 voice_remaining = 0;
966 voicebuf = NULL;
968 /* Force the codec to think it's changing tracks */
969 ci_voice.new_track = 1;
970 *realsize = 0;
971 return NULL;
973 else
974 break;
976 case SYS_USB_CONNECTED:
977 LOGFQUEUE("voice < SYS_USB_CONNECTED");
978 usb_acknowledge(SYS_USB_CONNECTED_ACK);
979 if (audio_codec_loaded)
980 swap_codec();
981 usb_wait_for_disconnect(&voice_queue);
982 break;
984 case Q_VOICE_PLAY:
985 LOGFQUEUE("voice < Q_VOICE_PLAY");
986 if (!voice_is_playing)
988 /* Set up new voice data */
989 struct voice_info *voice_data;
990 voice_is_playing = true;
991 trigger_cpu_boost();
992 voice_data = ev.data;
993 voice_remaining = voice_data->size;
994 voicebuf = voice_data->buf;
995 voice_getmore = voice_data->callback;
997 goto voice_play_clip;
999 case SYS_TIMEOUT:
1000 LOGFQUEUE("voice < SYS_TIMEOUT");
1001 goto voice_play_clip;
1003 default:
1004 LOGFQUEUE("voice < default");
1008 voice_play_clip:
1010 if (voice_remaining == 0 || voicebuf == NULL)
1012 if (voice_getmore)
1013 voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
1015 /* If this clip is done */
1016 if (voice_remaining == 0)
1018 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1019 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1020 /* Force pcm playback. */
1021 if (!pcm_is_playing())
1022 pcmbuf_play_start();
1026 *realsize = MIN(voice_remaining, reqsize);
1028 if (*realsize == 0)
1029 return NULL;
1031 return voicebuf;
1032 } /* voice_request_buffer_callback */
1034 static void voice_advance_buffer_callback(size_t amount)
1036 amount = MIN(amount, voice_remaining);
1037 voicebuf += amount;
1038 voice_remaining -= amount;
1041 static void voice_advance_buffer_loc_callback(void *ptr)
1043 size_t amount = (size_t)ptr - (size_t)voicebuf;
1045 voice_advance_buffer_callback(amount);
1048 static off_t voice_mp3_get_filepos_callback(int newtime)
1050 (void)newtime;
1052 return 0;
1055 static void voice_do_nothing(void)
1057 return;
1060 static bool voice_seek_buffer_callback(size_t newpos)
1062 (void)newpos;
1064 return false;
1067 static bool voice_request_next_track_callback(void)
1069 ci_voice.new_track = 0;
1070 return true;
1073 static void voice_thread(void)
1075 while (1)
1077 logf("Loading voice codec");
1078 voice_codec_loaded = true;
1079 mutex_lock(&mutex_codecthread);
1080 current_codec = CODEC_IDX_VOICE;
1081 dsp_configure(DSP_RESET, 0);
1082 voice_remaining = 0;
1083 voice_getmore = NULL;
1085 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1087 logf("Voice codec finished");
1088 voice_codec_loaded = false;
1089 mutex_unlock(&mutex_codecthread);
1091 } /* voice_thread */
1093 #endif /* PLAYBACK_VOICE */
1095 /* --- Codec thread --- */
1097 static bool codec_pcmbuf_insert_split_callback(
1098 const void *ch1, const void *ch2, size_t length)
1100 const char* src[2];
1101 char *dest;
1102 long input_size;
1103 size_t output_size;
1105 src[0] = ch1;
1106 src[1] = ch2;
1108 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1109 length *= 2; /* Length is per channel */
1111 while (length)
1113 long est_output_size = dsp_output_size(length);
1114 /* Prevent audio from a previous track from playing */
1115 if (ci.new_track || ci.stop_codec)
1116 return true;
1118 while ((dest = pcmbuf_request_buffer(est_output_size,
1119 &output_size)) == NULL)
1121 sleep(1);
1122 if (ci.seek_time || ci.new_track || ci.stop_codec)
1123 return true;
1126 /* Get the real input_size for output_size bytes, guarding
1127 * against resampling buffer overflows. */
1128 input_size = dsp_input_size(output_size);
1130 if (input_size <= 0)
1132 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
1133 output_size, length, input_size);
1134 /* If this happens, there are samples of codec data that don't
1135 * become a number of pcm samples, and something is broken */
1136 return false;
1139 /* Input size has grown, no error, just don't write more than length */
1140 if ((size_t)input_size > length)
1141 input_size = length;
1143 output_size = dsp_process(dest, src, input_size);
1145 pcmbuf_write_complete(output_size);
1147 #ifdef PLAYBACK_VOICE
1148 if ((voice_is_playing || voice_thread_start)
1149 && pcm_is_playing() && voice_codec_loaded &&
1150 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1152 voice_thread_start = false;
1153 swap_codec();
1155 #endif
1157 length -= input_size;
1160 return true;
1161 } /* codec_pcmbuf_insert_split_callback */
1163 static bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
1165 /* TODO: The audiobuffer API should probably be updated, and be based on
1166 * pcmbuf_insert_split(). */
1167 long real_length = length;
1169 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1170 length /= 2; /* Length is per channel */
1172 /* Second channel is only used for non-interleaved stereo. */
1173 return codec_pcmbuf_insert_split_callback(buf, buf + (real_length / 2),
1174 length);
1177 static void* codec_get_memory_callback(size_t *size)
1179 *size = MALLOC_BUFSIZE;
1180 return &audiobuf[talk_get_bufsize()];
1183 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1184 static void codec_pcmbuf_position_callback(size_t size)
1186 /* This is called from an ISR, so be quick */
1187 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1188 prev_ti->id3.elapsed;
1190 if (time >= prev_ti->id3.length)
1192 pcmbuf_set_position_callback(NULL);
1193 prev_ti->id3.elapsed = prev_ti->id3.length;
1195 else
1196 prev_ti->id3.elapsed = time;
1199 static void codec_set_elapsed_callback(unsigned int value)
1201 unsigned int latency;
1202 if (ci.seek_time)
1203 return;
1205 #ifdef AB_REPEAT_ENABLE
1206 ab_position_report(value);
1207 #endif
1209 latency = pcmbuf_get_latency();
1210 if (value < latency)
1211 CUR_TI->id3.elapsed = 0;
1212 else if (value - latency > CUR_TI->id3.elapsed ||
1213 value - latency < CUR_TI->id3.elapsed - 2)
1215 CUR_TI->id3.elapsed = value - latency;
1219 static void codec_set_offset_callback(size_t value)
1221 unsigned int latency;
1223 if (ci.seek_time)
1224 return;
1226 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1227 if (value < latency)
1228 CUR_TI->id3.offset = 0;
1229 else
1230 CUR_TI->id3.offset = value - latency;
1233 static void codec_advance_buffer_counters(size_t amount)
1235 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1236 ci.curpos += amount;
1237 CUR_TI->available -= amount;
1239 /* Start buffer filling as necessary. */
1240 if (!pcmbuf_is_lowdata() && !filling)
1242 if (FILEBUFUSED < conf_watermark && playing && !playlist_end)
1244 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1245 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1250 /* copy up-to size bytes into ptr and return the actual size copied */
1251 static size_t codec_filebuf_callback(void *ptr, size_t size)
1253 char *buf = (char *)ptr;
1254 size_t copy_n;
1255 size_t part_n;
1257 if (ci.stop_codec || !playing)
1258 return 0;
1260 /* The ammount to copy is the lesser of the requested amount and the
1261 * amount left of the current track (both on disk and already loaded) */
1262 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1264 /* Nothing requested OR nothing left */
1265 if (copy_n == 0)
1266 return 0;
1268 /* Let the disk buffer catch fill until enough data is available */
1269 while (copy_n > CUR_TI->available)
1271 if (!filling)
1273 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1274 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1277 sleep(1);
1278 if (ci.stop_codec || ci.new_track)
1279 return 0;
1282 /* Copy as much as possible without wrapping */
1283 part_n = MIN(copy_n, filebuflen - buf_ridx);
1284 memcpy(buf, &filebuf[buf_ridx], part_n);
1285 /* Copy the rest in the case of a wrap */
1286 if (part_n < copy_n) {
1287 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1290 /* Update read and other position pointers */
1291 codec_advance_buffer_counters(copy_n);
1293 /* Return the actual amount of data copied to the buffer */
1294 return copy_n;
1295 } /* codec_filebuf_callback */
1297 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1299 size_t short_n, copy_n, buf_rem;
1301 if (!playing)
1303 *realsize = 0;
1304 return NULL;
1307 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1308 if (copy_n == 0)
1310 *realsize = 0;
1311 return NULL;
1314 while (copy_n > CUR_TI->available)
1316 if (!filling)
1318 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1319 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1322 sleep(1);
1323 if (ci.stop_codec || ci.new_track)
1325 *realsize = 0;
1326 return NULL;
1330 /* How much is left at the end of the file buffer before wrap? */
1331 buf_rem = filebuflen - buf_ridx;
1333 /* If we can't satisfy the request without wrapping */
1334 if (buf_rem < copy_n)
1336 /* How short are we? */
1337 short_n = copy_n - buf_rem;
1339 /* If we can fudge it with the guardbuf */
1340 if (short_n < GUARD_BUFSIZE)
1341 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1342 else
1343 copy_n = buf_rem;
1346 *realsize = copy_n;
1348 return (char *)&filebuf[buf_ridx];
1349 } /* codec_request_buffer_callback */
1351 static int get_codec_base_type(int type)
1353 switch (type) {
1354 case AFMT_MPA_L1:
1355 case AFMT_MPA_L2:
1356 case AFMT_MPA_L3:
1357 return AFMT_MPA_L3;
1360 return type;
1363 static void codec_advance_buffer_callback(size_t amount)
1365 if (amount > CUR_TI->available + CUR_TI->filerem)
1366 amount = CUR_TI->available + CUR_TI->filerem;
1368 while (amount > CUR_TI->available && filling)
1369 sleep(1);
1371 if (amount > CUR_TI->available)
1373 struct event ev;
1375 LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK");
1376 queue_post(&audio_queue,
1377 Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount));
1379 queue_wait(&codec_callback_queue, &ev);
1380 switch (ev.id)
1382 case Q_CODEC_REQUEST_FAILED:
1383 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1384 ci.stop_codec = true;
1385 return;
1387 case Q_CODEC_REQUEST_COMPLETE:
1388 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1389 return;
1391 default:
1392 LOGFQUEUE("codec < default");
1393 ci.stop_codec = true;
1394 return;
1398 codec_advance_buffer_counters(amount);
1400 codec_set_offset_callback(ci.curpos);
1403 static void codec_advance_buffer_loc_callback(void *ptr)
1405 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1407 codec_advance_buffer_callback(amount);
1410 /* Copied from mpeg.c. Should be moved somewhere else. */
1411 static int codec_get_file_pos(void)
1413 int pos = -1;
1414 struct mp3entry *id3 = audio_current_track();
1416 if (id3->vbr)
1418 if (id3->has_toc)
1420 /* Use the TOC to find the new position */
1421 unsigned int percent, remainder;
1422 int curtoc, nexttoc, plen;
1424 percent = (id3->elapsed*100)/id3->length;
1425 if (percent > 99)
1426 percent = 99;
1428 curtoc = id3->toc[percent];
1430 if (percent < 99)
1431 nexttoc = id3->toc[percent+1];
1432 else
1433 nexttoc = 256;
1435 pos = (id3->filesize/256)*curtoc;
1437 /* Use the remainder to get a more accurate position */
1438 remainder = (id3->elapsed*100)%id3->length;
1439 remainder = (remainder*100)/id3->length;
1440 plen = (nexttoc - curtoc)*(id3->filesize/256);
1441 pos += (plen/100)*remainder;
1443 else
1445 /* No TOC exists, estimate the new position */
1446 pos = (id3->filesize / (id3->length / 1000)) *
1447 (id3->elapsed / 1000);
1450 else if (id3->bitrate)
1451 pos = id3->elapsed * (id3->bitrate / 8);
1452 else
1453 return -1;
1455 /* Don't seek right to the end of the file so that we can
1456 transition properly to the next song */
1457 if (pos >= (int)(id3->filesize - id3->id3v1len))
1458 pos = id3->filesize - id3->id3v1len - 1;
1459 /* skip past id3v2 tag and other leading garbage */
1460 else if (pos < (int)id3->first_frame_offset)
1461 pos = id3->first_frame_offset;
1463 return pos;
1466 static off_t codec_mp3_get_filepos_callback(int newtime)
1468 off_t newpos;
1470 CUR_TI->id3.elapsed = newtime;
1471 newpos = codec_get_file_pos();
1473 return newpos;
1476 static void codec_seek_complete_callback(void)
1478 logf("seek_complete");
1479 if (pcm_is_paused())
1481 /* If this is not a seamless seek, clear the buffer */
1482 pcmbuf_play_stop();
1484 /* If playback was not 'deliberately' paused, unpause now */
1485 if (!paused)
1486 pcmbuf_pause(false);
1488 ci.seek_time = 0;
1491 static bool codec_seek_buffer_callback(size_t newpos)
1493 int difference;
1495 logf("codec_seek_buffer_callback");
1497 if (newpos >= CUR_TI->filesize)
1498 newpos = CUR_TI->filesize - 1;
1500 difference = newpos - ci.curpos;
1501 if (difference >= 0)
1503 /* Seeking forward */
1504 logf("seek: +%d", difference);
1505 codec_advance_buffer_callback(difference);
1506 return true;
1509 /* Seeking backward */
1510 difference = -difference;
1511 if (ci.curpos - difference < 0)
1512 difference = ci.curpos;
1514 /* We need to reload the song. */
1515 if (newpos < CUR_TI->start_pos)
1517 struct event ev;
1519 LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK");
1520 queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos);
1522 queue_wait(&codec_callback_queue, &ev);
1523 switch (ev.id)
1525 case Q_CODEC_REQUEST_COMPLETE:
1526 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1527 return true;
1529 case Q_CODEC_REQUEST_FAILED:
1530 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1531 ci.stop_codec = true;
1532 return false;
1534 default:
1535 LOGFQUEUE("codec < default");
1536 return false;
1540 /* Seeking inside buffer space. */
1541 logf("seek: -%d", difference);
1542 CUR_TI->available += difference;
1543 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1544 ci.curpos -= difference;
1546 return true;
1549 static void codec_configure_callback(int setting, void *value)
1551 switch (setting) {
1552 case CODEC_SET_FILEBUF_WATERMARK:
1553 conf_watermark = (unsigned long)value;
1554 set_filebuf_watermark(buffer_margin);
1555 break;
1557 case CODEC_SET_FILEBUF_CHUNKSIZE:
1558 conf_filechunk = (unsigned long)value;
1559 break;
1561 case CODEC_SET_FILEBUF_PRESEEK:
1562 conf_preseek = (unsigned long)value;
1563 break;
1565 default:
1566 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1570 static void codec_track_changed(void)
1572 automatic_skip = false;
1573 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1574 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1577 static void codec_pcmbuf_track_changed_callback(void)
1579 pcmbuf_set_position_callback(NULL);
1580 codec_track_changed();
1583 static void codec_discard_codec_callback(void)
1585 if (CUR_TI->has_codec)
1587 CUR_TI->has_codec = false;
1588 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1591 #if 0
1592 /* Check if a buffer desync has happened, log it and stop playback. */
1593 if (buf_ridx != CUR_TI->buf_idx)
1595 int offset = CUR_TI->buf_idx - buf_ridx;
1596 size_t new_used = FILEBUFUSED - offset;
1598 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1599 logf("Used off:%d",FILEBUFUSED - new_used);
1601 /* This is a fatal internal error and it's not safe to
1602 * continue playback. */
1603 ci.stop_codec = true;
1604 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1606 #endif
1609 static void codec_track_skip_done(bool was_manual)
1611 /* Manual track change (always crossfade or flush audio). */
1612 if (was_manual)
1614 pcmbuf_crossfade_init(true);
1615 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1616 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1618 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1619 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1620 && global_settings.crossfade != 2)
1622 pcmbuf_crossfade_init(false);
1623 codec_track_changed();
1625 /* Gapless playback. */
1626 else
1628 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1629 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1633 static bool codec_load_next_track(void)
1635 struct event ev;
1637 prev_track_elapsed = CUR_TI->id3.elapsed;
1639 if (ci.seek_time)
1640 codec_seek_complete_callback();
1642 #ifdef AB_REPEAT_ENABLE
1643 ab_end_of_track_report();
1644 #endif
1646 logf("Request new track");
1648 if (ci.new_track == 0)
1650 ci.new_track++;
1651 automatic_skip = true;
1654 trigger_cpu_boost();
1655 LOGFQUEUE("codec > audio Q_AUDIO_CHECK_NEW_TRACK");
1656 queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1657 while (1)
1659 queue_wait(&codec_callback_queue, &ev);
1660 if (ev.id == Q_CODEC_REQUEST_PENDING)
1662 if (!automatic_skip)
1663 pcmbuf_play_stop();
1665 else
1666 break;
1669 switch (ev.id)
1671 case Q_CODEC_REQUEST_COMPLETE:
1672 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1673 codec_track_skip_done(!automatic_skip);
1674 return true;
1676 case Q_CODEC_REQUEST_FAILED:
1677 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1678 ci.new_track = 0;
1679 ci.stop_codec = true;
1680 return false;
1682 default:
1683 LOGFQUEUE("codec < default");
1684 ci.stop_codec = true;
1685 return false;
1689 static bool codec_request_next_track_callback(void)
1691 int prev_codectype;
1693 if (ci.stop_codec || !playing)
1694 return false;
1696 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1698 if (!codec_load_next_track())
1699 return false;
1701 /* Check if the next codec is the same file. */
1702 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1704 logf("New track loaded");
1705 codec_discard_codec_callback();
1706 return true;
1708 else
1710 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1711 return false;
1715 static void codec_thread(void)
1717 struct event ev;
1718 int status;
1719 size_t wrap;
1721 while (1) {
1722 status = 0;
1723 queue_wait(&codec_queue, &ev);
1725 switch (ev.id) {
1726 case Q_CODEC_LOAD_DISK:
1727 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1728 audio_codec_loaded = true;
1729 #ifdef PLAYBACK_VOICE
1730 /* Don't sent messages to voice codec if it's not current */
1731 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1733 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1734 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1736 #endif
1737 mutex_lock(&mutex_codecthread);
1738 current_codec = CODEC_IDX_AUDIO;
1739 ci.stop_codec = false;
1740 status = codec_load_file((const char *)ev.data, &ci);
1741 mutex_unlock(&mutex_codecthread);
1742 break ;
1744 case Q_CODEC_LOAD:
1745 LOGFQUEUE("codec < Q_CODEC_LOAD");
1746 if (!CUR_TI->has_codec) {
1747 logf("Codec slot is empty!");
1748 /* Wait for the pcm buffer to go empty */
1749 while (pcm_is_playing())
1750 yield();
1751 /* This must be set to prevent an infinite loop */
1752 ci.stop_codec = true;
1753 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1754 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1755 break ;
1758 audio_codec_loaded = true;
1759 #ifdef PLAYBACK_VOICE
1760 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1762 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1763 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1765 #endif
1766 mutex_lock(&mutex_codecthread);
1767 current_codec = CODEC_IDX_AUDIO;
1768 ci.stop_codec = false;
1769 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
1770 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
1771 &filebuf[0], wrap, &ci);
1772 mutex_unlock(&mutex_codecthread);
1773 break ;
1775 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
1776 case Q_ENCODER_LOAD_DISK:
1777 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1778 audio_codec_loaded = false; /* Not audio codec! */
1779 #ifdef PLAYBACK_VOICE
1780 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1782 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1783 queue_post(&voice_queue, Q_ENCODER_RECORD, NULL);
1785 #endif
1786 mutex_lock(&mutex_codecthread);
1787 current_codec = CODEC_IDX_AUDIO;
1788 ci.stop_codec = false;
1789 status = codec_load_file((const char *)ev.data, &ci);
1790 mutex_unlock(&mutex_codecthread);
1791 break;
1792 #endif
1794 #ifndef SIMULATOR
1795 case SYS_USB_CONNECTED:
1796 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1797 queue_clear(&codec_queue);
1798 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1799 usb_wait_for_disconnect(&codec_queue);
1800 break;
1801 #endif
1803 default:
1804 LOGFQUEUE("codec < default");
1807 if (audio_codec_loaded)
1809 if (ci.stop_codec)
1811 status = CODEC_OK;
1812 if (!playing)
1813 pcmbuf_play_stop();
1815 audio_codec_loaded = false;
1818 switch (ev.id) {
1819 case Q_CODEC_LOAD_DISK:
1820 case Q_CODEC_LOAD:
1821 LOGFQUEUE("codec < Q_CODEC_LOAD");
1822 if (playing)
1824 if (ci.new_track || status != CODEC_OK)
1826 if (!ci.new_track)
1828 logf("Codec failure");
1829 gui_syncsplash(HZ*2, true, "Codec failure");
1832 if (!codec_load_next_track())
1834 // queue_post(&codec_queue, Q_AUDIO_STOP, 0);
1835 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1836 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1837 break;
1840 else
1842 logf("Codec finished");
1843 if (ci.stop_codec)
1845 /* Wait for the audio to stop playing before
1846 * triggering the WPS exit */
1847 while(pcm_is_playing())
1849 CUR_TI->id3.elapsed = CUR_TI->id3.length - pcmbuf_get_latency();
1850 sleep(1);
1852 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1853 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1854 break;
1858 if (CUR_TI->has_codec)
1860 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
1861 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
1863 else
1865 const char *codec_fn = get_codec_filename(CUR_TI->id3.codectype);
1866 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1867 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
1868 (void *)codec_fn);
1871 break;
1873 default:
1874 LOGFQUEUE("codec < default");
1876 } /* end switch */
1881 /* --- Audio thread --- */
1883 static bool audio_filebuf_is_lowdata(void)
1885 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
1888 static bool audio_have_tracks(void)
1890 return track_ridx != track_widx || CUR_TI->filesize;
1893 static bool audio_have_free_tracks(void)
1895 if (track_widx < track_ridx)
1896 return track_widx + 1 < track_ridx;
1897 else if (track_ridx == 0)
1898 return track_widx < MAX_TRACK - 1;
1900 return true;
1903 int audio_track_count(void)
1905 if (audio_have_tracks())
1907 int relative_track_widx = track_widx;
1909 if (track_ridx > track_widx)
1910 relative_track_widx += MAX_TRACK;
1912 return relative_track_widx - track_ridx + 1;
1915 return 0;
1918 long audio_filebufused(void)
1920 return (long) FILEBUFUSED;
1923 /* Count the data BETWEEN the selected tracks */
1924 static size_t audio_buffer_count_tracks(int from_track, int to_track)
1926 size_t amount = 0;
1927 bool need_wrap = to_track < from_track;
1929 while (1)
1931 if (++from_track >= MAX_TRACK)
1933 from_track -= MAX_TRACK;
1934 need_wrap = false;
1937 if (from_track >= to_track && !need_wrap)
1938 break;
1940 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
1942 return amount;
1945 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
1947 size_t amount;
1949 /* Start with the remainder of the previously playing track */
1950 amount = tracks[old_track_ridx].filesize - ci.curpos;
1951 /* Then collect all data from tracks in between them */
1952 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
1953 logf("bwf:%ldB", (long) amount);
1955 if (amount > FILEBUFUSED)
1956 return false;
1958 /* Wind the buffer to the beginning of the target track or its codec */
1959 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1961 return true;
1964 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
1966 /* Available buffer data */
1967 size_t buf_back;
1968 /* Start with the previously playing track's data and our data */
1969 size_t amount;
1971 amount = ci.curpos;
1972 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
1974 /* If we're not just resetting the current track */
1975 if (new_track_ridx != old_track_ridx)
1977 /* Need to wind to before the old track's codec and our filesize */
1978 amount += tracks[old_track_ridx].codecsize;
1979 amount += tracks[new_track_ridx].filesize;
1981 /* Rewind the old track to its beginning */
1982 tracks[old_track_ridx].available =
1983 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
1986 /* If the codec was ever buffered */
1987 if (tracks[new_track_ridx].codecsize)
1989 /* Add the codec to the needed size */
1990 amount += tracks[new_track_ridx].codecsize;
1991 tracks[new_track_ridx].has_codec = true;
1994 /* Then collect all data from tracks between new and old */
1995 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
1997 /* Do we have space to make this skip? */
1998 if (amount > buf_back)
1999 return false;
2001 logf("bwb:%ldB",amount);
2003 /* Rewind the buffer to the beginning of the target track or its codec */
2004 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2006 /* Reset to the beginning of the new track */
2007 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2009 return true;
2012 static void audio_update_trackinfo(void)
2014 ci.filesize = CUR_TI->filesize;
2015 CUR_TI->id3.elapsed = 0;
2016 CUR_TI->id3.offset = 0;
2017 ci.id3 = &CUR_TI->id3;
2018 ci.curpos = 0;
2019 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2022 /* Yield to codecs for as long as possible if they are in need of data
2023 * return true if the caller should break to let the audio thread process
2024 * new events */
2025 static bool audio_yield_codecs(void)
2027 yield();
2029 if (!queue_empty(&audio_queue))
2030 return true;
2032 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2033 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2035 sleep(1);
2036 if (!queue_empty(&audio_queue))
2037 return true;
2040 return false;
2043 static void audio_clear_track_entries(bool clear_unbuffered)
2045 int cur_idx = track_widx;
2046 int last_idx = -1;
2048 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2050 /* Loop over all tracks from write-to-read */
2051 while (1)
2053 cur_idx++;
2054 cur_idx &= MAX_TRACK_MASK;
2056 if (cur_idx == track_ridx)
2057 break;
2059 /* If the track is buffered, conditionally clear/notify,
2060 * otherwise clear the track if that option is selected */
2061 if (tracks[cur_idx].event_sent)
2063 if (last_idx >= 0)
2065 /* If there is an unbuffer callback, call it, otherwise,
2066 * just clear the track */
2067 if (track_unbuffer_callback)
2068 track_unbuffer_callback(&tracks[last_idx].id3, false);
2070 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2072 last_idx = cur_idx;
2074 else if (clear_unbuffered)
2075 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2078 /* We clear the previous instance of a buffered track throughout
2079 * the above loop to facilitate 'last' detection. Clear/notify
2080 * the last track here */
2081 if (last_idx >= 0)
2083 if (track_unbuffer_callback)
2084 track_unbuffer_callback(&tracks[last_idx].id3, true);
2085 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2089 /* FIXME: This code should be made more generic and move to metadata.c */
2090 static void audio_strip_id3v1_tag(void)
2092 int i;
2093 static const unsigned char tag[] = "TAG";
2094 size_t tag_idx;
2095 size_t cur_idx;
2097 tag_idx = RINGBUF_SUB(buf_widx, 128);
2099 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2101 cur_idx = tag_idx;
2102 for(i = 0;i < 3;i++)
2104 if(filebuf[cur_idx] != tag[i])
2105 return;
2107 cur_idx = RINGBUF_ADD(cur_idx, 1);
2110 /* Skip id3v1 tag */
2111 logf("Skipping ID3v1 tag");
2112 buf_widx = tag_idx;
2113 tracks[track_widx].available -= 128;
2114 tracks[track_widx].filesize -= 128;
2118 /* Returns true if a whole file is read, false otherwise */
2119 static bool audio_read_file(size_t minimum)
2121 bool ret_val = false;
2123 /* If we're called and no file is open, this is an error */
2124 if (current_fd < 0)
2126 logf("Bad fd in arf");
2127 /* Give some hope of miraculous recovery by forcing a track reload */
2128 tracks[track_widx].filesize = 0;
2129 /* Stop this buffering run */
2130 return ret_val;
2133 trigger_cpu_boost();
2134 while (tracks[track_widx].filerem > 0)
2136 size_t copy_n;
2137 int overlap;
2138 int rc;
2140 /* copy_n is the largest chunk that is safe to read */
2141 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2143 /* buf_widx == buf_ridx is defined as buffer empty, not buffer full */
2144 if (RINGBUF_ADD_CROSS(buf_widx,copy_n,buf_ridx) >= 0)
2145 break;
2147 /* rc is the actual amount read */
2148 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2150 if (rc < 0)
2152 logf("File ended %dB early", tracks[track_widx].filerem);
2153 tracks[track_widx].filesize -= tracks[track_widx].filerem;
2154 tracks[track_widx].filerem = 0;
2155 break;
2158 /* How much of the playing track did we overwrite */
2159 if (buf_widx == CUR_TI->buf_idx)
2161 /* Special handling; zero or full overlap? */
2162 if (track_widx == track_ridx && CUR_TI->available == 0)
2163 overlap = 0;
2164 else
2165 overlap = rc;
2167 else
2168 overlap = RINGBUF_ADD_CROSS(buf_widx,rc,CUR_TI->buf_idx);
2170 if ((unsigned)rc > tracks[track_widx].filerem)
2172 logf("Bad: rc-filerem=%d, fixing", rc-tracks[track_widx].filerem);
2173 tracks[track_widx].filesize += rc - tracks[track_widx].filerem;
2174 tracks[track_widx].filerem = rc;
2177 /* Advance buffer */
2178 buf_widx = RINGBUF_ADD(buf_widx, rc);
2179 tracks[track_widx].available += rc;
2180 tracks[track_widx].filerem -= rc;
2182 /* If we write into the playing track, adjust it's buffer info */
2183 if (overlap > 0)
2185 CUR_TI->buf_idx += overlap;
2186 CUR_TI->start_pos += overlap;
2189 /* For a rebuffer, fill at least this minimum */
2190 if (minimum > (unsigned)rc)
2191 minimum -= rc;
2192 /* Let the codec process up to the watermark */
2193 /* Break immediately if this is a quick buffer, or there is an event */
2194 else if (minimum || audio_yield_codecs())
2196 /* Exit quickly, but don't stop the overall buffering process */
2197 ret_val = true;
2198 break;
2202 if (tracks[track_widx].filerem == 0)
2204 logf("Finished buf:%dB", tracks[track_widx].filesize);
2205 close(current_fd);
2206 current_fd = -1;
2207 audio_strip_id3v1_tag();
2209 track_widx++;
2210 track_widx &= MAX_TRACK_MASK;
2212 tracks[track_widx].filesize = 0;
2213 return true;
2215 else
2217 logf("%s buf:%dB", ret_val?"Quick":"Partially",
2218 tracks[track_widx].filesize - tracks[track_widx].filerem);
2219 return ret_val;
2223 static bool audio_loadcodec(bool start_play)
2225 size_t size = 0;
2226 int fd;
2227 int rc;
2228 size_t copy_n;
2229 int prev_track;
2230 char codec_path[MAX_PATH]; /* Full path to codec */
2232 const char * codec_fn = get_codec_filename(tracks[track_widx].id3.codectype);
2233 if (codec_fn == NULL)
2234 return false;
2236 tracks[track_widx].has_codec = false;
2238 if (start_play)
2240 /* Load the codec directly from disk and save some memory. */
2241 track_ridx = track_widx;
2242 ci.filesize = CUR_TI->filesize;
2243 ci.id3 = &CUR_TI->id3;
2244 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2245 ci.curpos = 0;
2246 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2247 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
2248 return true;
2250 else
2252 /* If we already have another track than this one buffered */
2253 if (track_widx != track_ridx)
2255 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2257 /* If the previous codec is the same as this one, there is no need
2258 * to put another copy of it on the file buffer */
2259 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2260 get_codec_base_type(tracks[prev_track].id3.codectype)
2261 && audio_codec_loaded)
2263 logf("Reusing prev. codec");
2264 return true;
2269 codec_get_full_path(codec_path, codec_fn);
2271 fd = open(codec_path, O_RDONLY);
2272 if (fd < 0)
2274 logf("Codec doesn't exist!");
2275 return false;
2278 tracks[track_widx].codecsize = filesize(fd);
2280 /* Never load a partial codec */
2281 if (RINGBUF_ADD_CROSS(buf_widx,tracks[track_widx].codecsize,buf_ridx) >= 0)
2283 logf("Not enough space");
2284 close(fd);
2285 return false;
2288 while (size < tracks[track_widx].codecsize)
2290 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2291 rc = read(fd, &filebuf[buf_widx], copy_n);
2292 if (rc < 0)
2294 close(fd);
2295 /* This is an error condition, likely the codec file is corrupt */
2296 logf("Partial codec loaded");
2297 /* Must undo the buffer write of the partial codec */
2298 buf_widx = RINGBUF_SUB(buf_widx, size);
2299 tracks[track_widx].codecsize = 0;
2300 return false;
2303 buf_widx = RINGBUF_ADD(buf_widx, rc);
2305 size += rc;
2308 tracks[track_widx].has_codec = true;
2310 close(fd);
2311 logf("Done: %dB", size);
2313 return true;
2316 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2317 static void audio_set_elapsed(struct mp3entry* id3)
2319 if ( id3->vbr ) {
2320 if ( id3->has_toc ) {
2321 /* calculate elapsed time using TOC */
2322 int i;
2323 unsigned int remainder, plen, relpos, nextpos;
2325 /* find wich percent we're at */
2326 for (i=0; i<100; i++ )
2327 if ( id3->offset < id3->toc[i] * (id3->filesize / 256) )
2328 break;
2330 i--;
2331 if (i < 0)
2332 i = 0;
2334 relpos = id3->toc[i];
2336 if (i < 99)
2337 nextpos = id3->toc[i+1];
2338 else
2339 nextpos = 256;
2341 remainder = id3->offset - (relpos * (id3->filesize / 256));
2343 /* set time for this percent (divide before multiply to prevent
2344 overflow on long files. loss of precision is negligible on
2345 short files) */
2346 id3->elapsed = i * (id3->length / 100);
2348 /* calculate remainder time */
2349 plen = (nextpos - relpos) * (id3->filesize / 256);
2350 id3->elapsed += (((remainder * 100) / plen) *
2351 (id3->length / 10000));
2353 else {
2354 /* no TOC exists. set a rough estimate using average bitrate */
2355 int tpk = id3->length / (id3->filesize / 1024);
2356 id3->elapsed = id3->offset / 1024 * tpk;
2359 else
2361 /* constant bitrate, use exact calculation */
2362 if (id3->bitrate != 0)
2363 id3->elapsed = id3->offset / (id3->bitrate / 8);
2367 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2369 char *trackname;
2370 off_t size;
2371 char msgbuf[80];
2373 /* Stop buffer filling if there is no free track entries.
2374 Don't fill up the last track entry (we wan't to store next track
2375 metadata there). */
2376 if (!audio_have_free_tracks())
2378 logf("No free tracks");
2379 return false;
2382 if (current_fd >= 0)
2384 logf("Nonzero fd in alt");
2385 close(current_fd);
2386 current_fd = -1;
2389 last_peek_offset++;
2390 peek_again:
2391 logf("Buffering track:%d/%d", track_widx, track_ridx);
2392 /* Get track name from current playlist read position. */
2393 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2395 /* Handle broken playlists. */
2396 current_fd = open(trackname, O_RDONLY);
2397 if (current_fd < 0)
2399 logf("Open failed");
2400 /* Skip invalid entry from playlist. */
2401 playlist_skip_entry(NULL, last_peek_offset);
2403 else
2404 break;
2407 if (!trackname)
2409 logf("End-of-playlist");
2410 playlist_end = true;
2411 return false;
2414 /* Initialize track entry. */
2415 size = filesize(current_fd);
2416 tracks[track_widx].filerem = size;
2417 tracks[track_widx].filesize = size;
2418 tracks[track_widx].available = 0;
2420 /* Set default values */
2421 if (start_play)
2423 int last_codec = current_codec;
2425 current_codec = CODEC_IDX_AUDIO;
2426 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2427 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2428 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2429 dsp_configure(DSP_RESET, 0);
2430 current_codec = last_codec;
2433 /* Get track metadata if we don't already have it. */
2434 if (!tracks[track_widx].taginfo_ready)
2436 if (get_metadata(&tracks[track_widx],current_fd,trackname,v1first))
2438 if (start_play)
2440 track_changed = true;
2441 playlist_update_resume_info(audio_current_track());
2444 else
2446 logf("mde:%s!",trackname);
2448 /* Set filesize to zero to indicate no file was loaded. */
2449 tracks[track_widx].filesize = 0;
2450 tracks[track_widx].filerem = 0;
2451 close(current_fd);
2452 current_fd = -1;
2454 /* Skip invalid entry from playlist. */
2455 playlist_skip_entry(NULL, last_peek_offset);
2456 tracks[track_widx].taginfo_ready = false;
2457 goto peek_again;
2462 /* Load the codec. */
2463 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2464 if (!audio_loadcodec(start_play))
2466 /* Set filesize to zero to indicate no file was loaded. */
2467 tracks[track_widx].filesize = 0;
2468 tracks[track_widx].filerem = 0;
2469 close(current_fd);
2470 current_fd = -1;
2472 if (tracks[track_widx].codecsize)
2474 /* No space for codec on buffer, not an error */
2475 tracks[track_widx].codecsize = 0;
2476 return false;
2479 /* This is an error condition, either no codec was found, or reading
2480 * the codec file failed part way through, either way, skip the track */
2481 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2482 /* We should not use gui_syncplash from audio thread! */
2483 gui_syncsplash(HZ*2, true, msgbuf);
2484 /* Skip invalid entry from playlist. */
2485 playlist_skip_entry(NULL, last_peek_offset);
2486 tracks[track_widx].taginfo_ready = false;
2487 goto peek_again;
2490 tracks[track_widx].start_pos = 0;
2491 set_filebuf_watermark(buffer_margin);
2492 tracks[track_widx].id3.elapsed = 0;
2494 if (offset > 0)
2496 switch (tracks[track_widx].id3.codectype) {
2497 case AFMT_MPA_L1:
2498 case AFMT_MPA_L2:
2499 case AFMT_MPA_L3:
2500 lseek(current_fd, offset, SEEK_SET);
2501 tracks[track_widx].id3.offset = offset;
2502 audio_set_elapsed(&tracks[track_widx].id3);
2503 tracks[track_widx].filerem = size - offset;
2504 ci.curpos = offset;
2505 tracks[track_widx].start_pos = offset;
2506 break;
2508 case AFMT_WAVPACK:
2509 lseek(current_fd, offset, SEEK_SET);
2510 tracks[track_widx].id3.offset = offset;
2511 tracks[track_widx].id3.elapsed =
2512 tracks[track_widx].id3.length / 2;
2513 tracks[track_widx].filerem = size - offset;
2514 ci.curpos = offset;
2515 tracks[track_widx].start_pos = offset;
2516 break;
2518 case AFMT_OGG_VORBIS:
2519 case AFMT_FLAC:
2520 case AFMT_PCM_WAV:
2521 case AFMT_A52:
2522 case AFMT_AAC:
2523 tracks[track_widx].id3.offset = offset;
2524 break;
2528 logf("alt:%s", trackname);
2529 tracks[track_widx].buf_idx = buf_widx;
2531 return audio_read_file(rebuffer);
2534 static bool audio_read_next_metadata(void)
2536 int fd;
2537 char *trackname;
2538 int next_idx;
2539 int status;
2541 next_idx = track_widx;
2542 if (tracks[next_idx].taginfo_ready)
2544 next_idx++;
2545 next_idx &= MAX_TRACK_MASK;
2547 if (tracks[next_idx].taginfo_ready)
2548 return true;
2551 trackname = playlist_peek(last_peek_offset + 1);
2552 if (!trackname)
2553 return false;
2555 fd = open(trackname, O_RDONLY);
2556 if (fd < 0)
2557 return false;
2559 status = get_metadata(&tracks[next_idx],fd,trackname,v1first);
2560 /* Preload the glyphs in the tags */
2561 if (status)
2563 if (tracks[next_idx].id3.title)
2564 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2565 if (tracks[next_idx].id3.artist)
2566 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2567 if (tracks[next_idx].id3.album)
2568 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2570 close(fd);
2572 return status;
2575 /* Send callback events to notify about new tracks. */
2576 static void audio_generate_postbuffer_events(void)
2578 int cur_idx;
2579 int last_idx = -1;
2581 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2583 if (audio_have_tracks())
2585 cur_idx = track_ridx;
2587 while (1) {
2588 if (!tracks[cur_idx].event_sent)
2590 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2592 /* Mark the event 'sent' even if we don't really send one */
2593 tracks[last_idx].event_sent = true;
2594 if (track_buffer_callback)
2595 track_buffer_callback(&tracks[last_idx].id3, false);
2597 last_idx = cur_idx;
2599 if (cur_idx == track_widx)
2600 break;
2601 cur_idx++;
2602 cur_idx &= MAX_TRACK_MASK;
2605 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2607 tracks[last_idx].event_sent = true;
2608 if (track_buffer_callback)
2609 track_buffer_callback(&tracks[last_idx].id3, true);
2612 /* Force WPS reload. */
2613 track_changed = true;
2617 static bool audio_initialize_buffer_fill(bool clear_tracks)
2619 /* Don't initialize if we're already initialized */
2620 if (filling)
2621 return true;
2623 logf("Starting buffer fill");
2625 /* Set the filling flag true before calling audio_clear_tracks as that
2626 * function can yield and we start looping. */
2627 filling = true;
2629 if (clear_tracks)
2630 audio_clear_track_entries(false);
2632 /* Save the current resume position once. */
2633 playlist_update_resume_info(audio_current_track());
2635 return true;
2638 static void audio_fill_file_buffer(
2639 bool start_play, bool rebuffer, size_t offset)
2641 bool had_next_track = audio_next_track() != NULL;
2642 bool continue_buffering;
2644 if (!audio_initialize_buffer_fill(!start_play))
2645 return ;
2647 /* If we have a partially buffered track, continue loading,
2648 * otherwise load a new track */
2649 if (tracks[track_widx].filesize > 0)
2650 continue_buffering = audio_read_file(rebuffer);
2651 else
2652 continue_buffering = audio_load_track(offset, start_play, rebuffer);
2654 if (!had_next_track && audio_next_track())
2655 track_changed = true;
2657 /* If we're done buffering */
2658 if (!continue_buffering)
2660 audio_read_next_metadata();
2662 audio_generate_postbuffer_events();
2663 filling = false;
2665 #ifndef SIMULATOR
2666 if (playing)
2667 ata_sleep();
2668 #endif
2673 static void audio_rebuffer(void)
2675 logf("Forcing rebuffer");
2677 /* Notify the codec that this will take a while */
2678 /* Currently this can cause some problems (logf in reverse order):
2679 * Codec load error:-1
2680 * Codec load disk
2681 * Codec: Unsupported
2682 * Codec finished
2683 * New codec:0/3
2684 * Clearing tracks:7/7, 1
2685 * Forcing rebuffer
2686 * Check new track buffer
2687 * Request new track
2688 * Clearing tracks:5/5, 0
2689 * Starting buffer fill
2690 * Clearing tracks:5/5, 1
2691 * Re-buffering song w/seek
2693 //if (!filling)
2694 // queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0);
2696 /* Stop in progress fill, and clear open file descriptor */
2697 if (current_fd >= 0)
2699 close(current_fd);
2700 current_fd = -1;
2702 filling = false;
2704 /* Reset buffer and track pointers */
2705 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
2706 track_widx = track_ridx;
2707 audio_clear_track_entries(true);
2708 CUR_TI->available = 0;
2710 /* Fill the buffer */
2711 last_peek_offset = -1;
2712 CUR_TI->filesize = 0;
2713 CUR_TI->start_pos = 0;
2714 ci.curpos = 0;
2716 if (!CUR_TI->taginfo_ready)
2717 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
2719 audio_fill_file_buffer(false, true, 0);
2722 static void audio_check_new_track(void)
2724 int track_count = audio_track_count();
2725 int old_track_ridx = track_ridx;
2726 bool forward;
2728 if (dir_skip)
2730 dir_skip = false;
2731 if (playlist_next_dir(ci.new_track))
2733 ci.new_track = 0;
2734 CUR_TI->taginfo_ready = false;
2735 audio_rebuffer();
2736 goto skip_done;
2738 else
2740 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2741 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2742 return;
2746 if (new_playlist)
2747 ci.new_track = 0;
2749 /* If the playlist isn't that big */
2750 if (!playlist_check(ci.new_track))
2752 if (ci.new_track >= 0)
2754 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2755 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2756 return;
2758 /* Find the beginning backward if the user over-skips it */
2759 while (!playlist_check(++ci.new_track))
2760 if (ci.new_track >= 0)
2762 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2763 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2764 return;
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 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2774 return;
2777 if (new_playlist)
2779 ci.new_track = 1;
2780 new_playlist = false;
2783 /* Save the old track */
2784 prev_ti = CUR_TI;
2786 /* Move to the new track */
2787 track_ridx += ci.new_track;
2788 track_ridx &= MAX_TRACK_MASK;
2790 if (automatic_skip)
2791 playlist_end = false;
2793 track_changed = !automatic_skip;
2795 /* If it is not safe to even skip this many track entries */
2796 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
2798 ci.new_track = 0;
2799 CUR_TI->taginfo_ready = false;
2800 audio_rebuffer();
2801 goto skip_done;
2804 forward = ci.new_track > 0;
2805 ci.new_track = 0;
2807 /* If the target track is clearly not in memory */
2808 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
2810 audio_rebuffer();
2811 goto skip_done;
2814 /* The track may be in memory, see if it really is */
2815 if (forward)
2817 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
2818 audio_rebuffer();
2820 else
2822 int cur_idx = track_ridx;
2823 bool taginfo_ready = true;
2824 bool wrap = track_ridx > old_track_ridx;
2826 while (1)
2828 cur_idx++;
2829 cur_idx &= MAX_TRACK_MASK;
2830 if (!(wrap || cur_idx < old_track_ridx))
2831 break;
2833 /* If we hit a track in between without valid tag info, bail */
2834 if (!tracks[cur_idx].taginfo_ready)
2836 taginfo_ready = false;
2837 break;
2840 tracks[cur_idx].available = tracks[cur_idx].filesize;
2841 if (tracks[cur_idx].codecsize)
2842 tracks[cur_idx].has_codec = true;
2844 if (taginfo_ready)
2846 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
2847 audio_rebuffer();
2849 else
2851 CUR_TI->taginfo_ready = false;
2852 audio_rebuffer();
2856 skip_done:
2857 audio_update_trackinfo();
2858 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE");
2859 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0);
2862 static void audio_rebuffer_and_seek(size_t newpos)
2864 size_t real_preseek;
2865 int fd;
2866 char *trackname;
2868 /* (Re-)open current track's file handle. */
2869 trackname = playlist_peek(0);
2870 fd = open(trackname, O_RDONLY);
2871 if (fd < 0)
2873 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2874 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2875 return;
2878 if (current_fd >= 0)
2879 close(current_fd);
2880 current_fd = fd;
2882 playlist_end = false;
2884 ci.curpos = newpos;
2886 /* Clear codec buffer. */
2887 track_widx = track_ridx;
2888 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
2890 last_peek_offset = 0;
2891 filling = false;
2892 audio_initialize_buffer_fill(true);
2894 /* This may have been tweaked by the id3v1 code */
2895 CUR_TI->filesize=filesize(fd);
2896 if (newpos > conf_preseek)
2898 CUR_TI->start_pos = newpos - conf_preseek;
2899 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
2900 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
2901 real_preseek = conf_preseek;
2903 else
2905 CUR_TI->start_pos = 0;
2906 CUR_TI->filerem = CUR_TI->filesize;
2907 real_preseek = newpos;
2910 CUR_TI->available = 0;
2912 audio_read_file(real_preseek);
2914 /* Account for the data we just read that is 'behind' us now */
2915 CUR_TI->available -= real_preseek;
2917 buf_ridx = RINGBUF_ADD(buf_ridx, real_preseek);
2919 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE");
2920 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0);
2923 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
2924 bool last_track))
2926 track_buffer_callback = handler;
2929 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
2930 bool last_track))
2932 track_unbuffer_callback = handler;
2935 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
2937 track_changed_callback = handler;
2940 unsigned long audio_prev_elapsed(void)
2942 return prev_track_elapsed;
2945 static void audio_stop_codec_flush(void)
2947 ci.stop_codec = true;
2948 pcmbuf_pause(true);
2949 while (audio_codec_loaded)
2950 yield();
2951 /* If the audio codec is not loaded any more, and the audio is still
2952 * playing, it is now and _only_ now safe to call this function from the
2953 * audio thread */
2954 if (pcm_is_playing())
2955 pcmbuf_play_stop();
2956 pcmbuf_pause(paused);
2959 static void audio_stop_playback(void)
2961 /* If we were playing, save resume information */
2962 if (playing)
2964 /* Save the current playing spot, or NULL if the playlist has ended */
2965 playlist_update_resume_info(
2966 (playlist_end && ci.stop_codec)?NULL:audio_current_track());
2969 filling = false;
2970 paused = false;
2971 audio_stop_codec_flush();
2972 playing = false;
2974 if (current_fd >= 0)
2976 close(current_fd);
2977 current_fd = -1;
2980 /* Mark all entries null. */
2981 audio_clear_track_entries(false);
2982 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
2985 static void audio_play_start(size_t offset)
2987 #if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
2988 rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2989 #endif
2991 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2992 audio_stop_codec_flush();
2994 track_changed = true;
2995 playlist_end = false;
2997 playing = true;
2998 ci.new_track = 0;
2999 ci.seek_time = 0;
3000 wps_offset = 0;
3002 if (current_fd >= 0)
3004 close(current_fd);
3005 current_fd = -1;
3008 sound_set_volume(global_settings.volume);
3009 track_widx = track_ridx = 0;
3010 buf_ridx = buf_widx = 0;
3012 /* Mark all entries null. */
3013 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3015 last_peek_offset = -1;
3017 audio_fill_file_buffer(true, false, offset);
3021 /* Invalidates all but currently playing track. */
3022 static void audio_invalidate_tracks(void)
3024 if (audio_have_tracks()) {
3025 last_peek_offset = 0;
3027 playlist_end = false;
3028 track_widx = track_ridx;
3029 /* Mark all other entries null (also buffered wrong metadata). */
3030 audio_clear_track_entries(true);
3032 /* If the current track is fully buffered, advance the write pointer */
3033 if (tracks[track_widx].filerem == 0)
3034 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3036 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3038 audio_read_next_metadata();
3042 static void audio_new_playlist(void)
3044 /* Prepare to start a new fill from the beginning of the playlist */
3045 last_peek_offset = -1;
3046 if (audio_have_tracks()) {
3047 playlist_end = false;
3048 track_widx = track_ridx;
3049 audio_clear_track_entries(true);
3051 track_widx++;
3052 track_widx &= MAX_TRACK_MASK;
3054 /* Stop reading the current track */
3055 CUR_TI->filerem = 0;
3056 close(current_fd);
3057 current_fd = -1;
3059 /* Mark the current track as invalid to prevent skipping back to it */
3060 CUR_TI->taginfo_ready = false;
3062 /* Invalidate the buffer other than the playing track */
3063 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3066 /* Signal the codec to initiate a track change forward */
3067 new_playlist = true;
3068 ci.new_track = 1;
3069 audio_fill_file_buffer(false, true, 0);
3072 static void audio_initiate_track_change(long direction)
3074 playlist_end = false;
3075 ci.new_track += direction;
3076 wps_offset -= direction;
3079 static void audio_initiate_dir_change(long direction)
3081 playlist_end = false;
3082 dir_skip = true;
3083 ci.new_track = direction;
3086 static void audio_reset_buffer(void)
3088 size_t offset;
3090 /* Set up file buffer as all space available */
3091 filebuf = (char *)&audiobuf[talk_get_bufsize()+MALLOC_BUFSIZE];
3092 filebuflen = audiobufend - (unsigned char *) filebuf - GUARD_BUFSIZE -
3093 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_MIX_CHUNK * 2);
3095 /* Allow for codec(s) at end of file buffer */
3096 if (talk_voice_required())
3098 /* Allow 2 codecs at end of file buffer */
3099 filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE);
3101 iram_buf[0] = &filebuf[filebuflen];
3102 iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE];
3103 dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2];
3104 dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE];
3106 else
3108 /* Allow for 1 codec at end of file buffer */
3109 filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE;
3111 iram_buf[0] = &filebuf[filebuflen];
3112 iram_buf[1] = NULL;
3113 dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE];
3114 dram_buf[1] = NULL;
3117 /* Ensure that file buffer is aligned */
3118 offset = (-(size_t)filebuf) & 3;
3119 filebuf += offset;
3120 filebuflen -= offset;
3121 filebuflen &= ~3;
3125 #ifdef ROCKBOX_HAS_LOGF
3126 static void audio_test_track_changed_event(struct mp3entry *id3)
3128 (void)id3;
3130 logf("tce:%s", id3->path);
3132 #endif
3134 static void audio_playback_init(void)
3136 #ifdef PLAYBACK_VOICE
3137 static bool voicetagtrue = true;
3138 static struct mp3entry id3_voice;
3139 #endif
3140 struct event ev;
3142 logf("playback api init");
3143 pcm_init();
3145 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
3146 /* Set the input multiplexer to Line In */
3147 pcm_rec_mux(0);
3148 #endif
3150 #ifdef ROCKBOX_HAS_LOGF
3151 audio_set_track_changed_event(audio_test_track_changed_event);
3152 #endif
3154 /* Initialize codec api. */
3155 ci.read_filebuf = codec_filebuf_callback;
3156 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3157 ci.pcmbuf_insert_split = codec_pcmbuf_insert_split_callback;
3158 ci.get_codec_memory = codec_get_memory_callback;
3159 ci.request_buffer = codec_request_buffer_callback;
3160 ci.advance_buffer = codec_advance_buffer_callback;
3161 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3162 ci.request_next_track = codec_request_next_track_callback;
3163 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3164 ci.seek_buffer = codec_seek_buffer_callback;
3165 ci.seek_complete = codec_seek_complete_callback;
3166 ci.set_elapsed = codec_set_elapsed_callback;
3167 ci.set_offset = codec_set_offset_callback;
3168 ci.configure = codec_configure_callback;
3169 ci.discard_codec = codec_discard_codec_callback;
3171 /* Initialize voice codec api. */
3172 #ifdef PLAYBACK_VOICE
3173 memcpy(&ci_voice, &ci, sizeof(struct codec_api));
3174 memset(&id3_voice, 0, sizeof(struct mp3entry));
3175 ci_voice.read_filebuf = voice_filebuf_callback;
3176 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3177 ci_voice.pcmbuf_insert_split = voice_pcmbuf_insert_split_callback;
3178 ci_voice.get_codec_memory = voice_get_memory_callback;
3179 ci_voice.request_buffer = voice_request_buffer_callback;
3180 ci_voice.advance_buffer = voice_advance_buffer_callback;
3181 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3182 ci_voice.request_next_track = voice_request_next_track_callback;
3183 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3184 ci_voice.seek_buffer = voice_seek_buffer_callback;
3185 ci_voice.seek_complete = voice_do_nothing;
3186 ci_voice.set_elapsed = voice_set_elapsed_callback;
3187 ci_voice.set_offset = voice_set_offset_callback;
3188 ci_voice.discard_codec = voice_do_nothing;
3189 ci_voice.taginfo_ready = &voicetagtrue;
3190 ci_voice.id3 = &id3_voice;
3191 id3_voice.frequency = 11200;
3192 id3_voice.length = 1000000L;
3193 #endif
3195 codec_thread_p = create_thread(codec_thread, codec_stack,
3196 sizeof(codec_stack),
3197 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK));
3199 while (1)
3201 queue_wait(&audio_queue, &ev);
3202 if (ev.id == Q_AUDIO_POSTINIT)
3203 break ;
3205 #ifndef SIMULATOR
3206 if (ev.id == SYS_USB_CONNECTED)
3208 logf("USB: Audio preinit");
3209 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3210 usb_wait_for_disconnect(&audio_queue);
3212 #endif
3215 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; /* Will be reset by reset_buffer */
3217 audio_set_crossfade(global_settings.crossfade);
3219 audio_is_initialized = true;
3221 sound_settings_apply();
3224 static void audio_thread(void)
3226 struct event ev;
3228 /* At first initialize audio system in background. */
3229 audio_playback_init();
3231 while (1)
3233 if (filling)
3235 queue_wait_w_tmo(&audio_queue, &ev, 0);
3236 if (ev.id == SYS_TIMEOUT)
3237 ev.id = Q_AUDIO_FILL_BUFFER;
3239 else
3240 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3242 switch (ev.id) {
3243 case Q_AUDIO_FILL_BUFFER:
3244 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3245 if (!filling)
3246 if (!playing || playlist_end || ci.stop_codec)
3247 break;
3248 audio_fill_file_buffer(false, false, 0);
3249 break;
3251 case Q_AUDIO_PLAY:
3252 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3253 audio_clear_track_entries(false);
3254 audio_play_start((size_t)ev.data);
3255 break ;
3257 case Q_AUDIO_STOP:
3258 LOGFQUEUE("audio < Q_AUDIO_STOP");
3259 audio_stop_playback();
3260 break ;
3262 case Q_AUDIO_PAUSE:
3263 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3264 pcmbuf_pause((bool)ev.data);
3265 paused = (bool)ev.data;
3266 break ;
3268 case Q_AUDIO_SKIP:
3269 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3270 audio_initiate_track_change((long)ev.data);
3271 break;
3273 case Q_AUDIO_PRE_FF_REWIND:
3274 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3275 if (!playing)
3276 break;
3277 pcmbuf_pause(true);
3278 break;
3280 case Q_AUDIO_FF_REWIND:
3281 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3282 if (!playing)
3283 break ;
3284 ci.seek_time = (long)ev.data+1;
3285 break ;
3287 case Q_AUDIO_REBUFFER_SEEK:
3288 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3289 audio_rebuffer_and_seek((size_t)ev.data);
3290 break;
3292 case Q_AUDIO_CHECK_NEW_TRACK:
3293 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3294 audio_check_new_track();
3295 break;
3297 case Q_AUDIO_DIR_SKIP:
3298 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3299 playlist_end = false;
3300 audio_initiate_dir_change((long)ev.data);
3301 break;
3303 case Q_AUDIO_NEW_PLAYLIST:
3304 LOGFQUEUE("audio < Q_AUDIO_NEW_PLAYLIST");
3305 audio_new_playlist();
3306 break;
3308 case Q_AUDIO_FLUSH:
3309 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3310 audio_invalidate_tracks();
3311 break ;
3313 case Q_AUDIO_TRACK_CHANGED:
3314 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3315 if (track_changed_callback)
3316 track_changed_callback(&CUR_TI->id3);
3317 track_changed = true;
3318 playlist_update_resume_info(audio_current_track());
3319 break ;
3321 #ifndef SIMULATOR
3322 case SYS_USB_CONNECTED:
3323 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3324 audio_stop_playback();
3325 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3326 usb_wait_for_disconnect(&audio_queue);
3327 break ;
3328 #endif
3330 case SYS_TIMEOUT:
3331 LOGFQUEUE("audio < SYS_TIMEOUT");
3332 break;
3334 default:
3335 LOGFQUEUE("audio < default");