Minor simplification #3; use macros for ring buffer arithmetic. Also fixed unlikely...
[Rockbox.git] / apps / playback.c
blobe0358cfbac6ac7b9c3053be1eab678cf441dd28d
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: Check for a possibly broken codepath on a rapid skip, stop event */
21 /* TODO: same in reverse ^^ */
22 /* TODO: Also play, stop ^^ */
23 /* TODO: Can use the track changed callback to detect end of track and seek
24 * in the previous track until this happens */
25 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
26 * play whilst audio is paused */
27 /* Design: we have prev_ti already, have a conditional for what type of seek
28 * to do on a seek request, if it is a previous track seek, skip previous,
29 * and in the request_next_track callback set the offset up the same way that
30 * starting from an offset works. */
31 /* This is also necesary to prevent the problem with buffer overwriting on
32 * automatic track changes */
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <ctype.h>
39 #include "system.h"
40 #include "thread.h"
41 #include "file.h"
42 #include "lcd.h"
43 #include "font.h"
44 #include "button.h"
45 #include "kernel.h"
46 #include "tree.h"
47 #include "debug.h"
48 #include "sprintf.h"
49 #include "settings.h"
50 #include "codecs.h"
51 #include "audio.h"
52 #include "logf.h"
53 #include "mp3_playback.h"
54 #include "usb.h"
55 #include "status.h"
56 #include "main_menu.h"
57 #include "ata.h"
58 #include "screens.h"
59 #include "playlist.h"
60 #include "playback.h"
61 #include "pcmbuf.h"
62 #include "pcm_playback.h"
63 #include "pcm_record.h"
64 #include "buffer.h"
65 #include "dsp.h"
66 #include "abrepeat.h"
67 #include "tagcache.h"
68 #ifdef HAVE_LCD_BITMAP
69 #include "icons.h"
70 #include "peakmeter.h"
71 #include "action.h"
72 #endif
73 #include "lang.h"
74 #include "bookmark.h"
75 #include "misc.h"
76 #include "sound.h"
77 #include "metadata.h"
78 #include "splash.h"
79 #include "talk.h"
81 #ifdef HAVE_RECORDING
82 #include "recording.h"
83 #endif
85 #define PLAYBACK_VOICE
88 /* default point to start buffer refill */
89 #define AUDIO_DEFAULT_WATERMARK (1024*512)
90 /* amount of data to read in one read() call */
91 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
92 /* point at which the file buffer will fight for CPU time */
93 #define AUDIO_FILEBUF_CRITICAL (1024*128)
94 /* amount of guess-space to allow for codecs that must hunt and peck
95 * for their correct seeek target, 32k seems a good size */
96 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
98 /* macros to enable logf for queues */
99 #ifdef SIMULATOR
100 #define PLAYBACK_LOGQUEUES /* Define this for logf output of all queuing */
101 #endif
103 #ifdef PLAYBACK_LOGQUEUES
104 #define LOGFQUEUE(s) logf("%s", s)
105 #else
106 #define LOGFQUEUE(s)
107 #endif
109 enum {
110 Q_AUDIO_PLAY = 1,
111 Q_AUDIO_STOP,
112 Q_AUDIO_PAUSE,
113 Q_AUDIO_SKIP,
114 Q_AUDIO_PRE_FF_REWIND,
115 Q_AUDIO_FF_REWIND,
116 Q_AUDIO_REBUFFER_SEEK,
117 Q_AUDIO_CHECK_NEW_TRACK,
118 Q_AUDIO_FLUSH,
119 Q_AUDIO_TRACK_CHANGED,
120 Q_AUDIO_DIR_SKIP,
121 Q_AUDIO_NEW_PLAYLIST,
122 Q_AUDIO_POSTINIT,
123 Q_AUDIO_FILL_BUFFER,
125 Q_CODEC_REQUEST_PENDING,
126 Q_CODEC_REQUEST_COMPLETE,
127 Q_CODEC_REQUEST_FAILED,
129 Q_VOICE_PLAY,
130 Q_VOICE_STOP,
132 Q_CODEC_LOAD,
133 Q_CODEC_LOAD_DISK,
135 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
136 Q_ENCODER_LOAD_DISK,
137 Q_ENCODER_RECORD,
138 #endif
141 /* As defined in plugins/lib/xxx2wav.h */
142 #if MEM > 1
143 #define MALLOC_BUFSIZE (512*1024)
144 #define GUARD_BUFSIZE (32*1024)
145 #else
146 #define MALLOC_BUFSIZE (100*1024)
147 #define GUARD_BUFSIZE (8*1024)
148 #endif
150 /* As defined in plugin.lds */
151 #if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
152 #define CODEC_IRAM_ORIGIN 0x4000c000
153 #elif defined(IAUDIO_X5)
154 #define CODEC_IRAM_ORIGIN 0x10014000
155 #else
156 #define CODEC_IRAM_ORIGIN 0x1000c000
157 #endif
158 #define CODEC_IRAM_SIZE 0xc000
160 #ifdef PLAYBACK_VOICE
161 #ifdef SIMULATOR
162 static unsigned char sim_iram[CODEC_IRAM_SIZE];
163 #undef CODEC_IRAM_ORIGIN
164 #define CODEC_IRAM_ORIGIN sim_iram
165 #endif
166 #endif
168 #ifndef SIMULATOR
169 extern bool audio_is_initialized;
170 #else
171 static bool audio_is_initialized = false;
172 #endif
176 static struct mutex mutex_codecthread;
177 static struct event_queue codec_callback_queue;
179 static volatile bool audio_codec_loaded;
180 static volatile bool playing;
181 static volatile bool paused;
183 /* Is file buffer currently being refilled? */
184 static volatile bool filling IDATA_ATTR;
186 volatile int current_codec IDATA_ATTR;
187 extern unsigned char codecbuf[];
189 /* Ring buffer where tracks and codecs are loaded. */
190 static char *filebuf;
192 /* Total size of the ring buffer. */
193 size_t filebuflen;
195 /* Ring buffer read and write indexes. */
196 static volatile size_t buf_ridx IDATA_ATTR;
197 static volatile size_t buf_widx IDATA_ATTR;
199 /* Ring buffer arithmetic */
200 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
201 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
203 /* Bytes available in the buffer. */
204 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
206 /* Codec swapping pointers */
207 static unsigned char *iram_buf[2];
208 static unsigned char *dram_buf[2];
210 /* Step count to the next unbuffered track. */
211 static int last_peek_offset;
213 /* Track information (count in file buffer, read/write indexes for
214 track ring structure. */
215 static int track_ridx;
216 static int track_widx;
217 static bool track_changed; /* Audio and codec threads */
219 /* Partially loaded song's file handle to continue buffering later. */
220 static int current_fd;
222 /* Information about how many bytes left on the buffer re-fill run. */
223 static size_t fill_bytesleft;
225 /* Track info structure about songs in the file buffer. */
226 static struct track_info tracks[MAX_TRACK]; /* Audio thread */
228 /* Pointer to track info structure about current song playing. */
229 #define CUR_TI (&tracks[track_ridx])
231 /* Pointer to track info structure about previous played song. */
232 static struct track_info *prev_ti; /* Audio and codec threads */
234 /* Have we reached end of the current playlist. */
235 static bool playlist_end = false; /* Audio thread */
237 /* Was the skip being executed manual or automatic? */
238 static bool automatic_skip = false; /* Audio and codec threads */
239 static bool dir_skip = false; /* Audio thread */
240 static bool new_playlist = false; /* Audio thread */
241 static int wps_offset = 0;
243 /* Callback function to call when current track has really changed. */
244 void (*track_changed_callback)(struct mp3entry *id3);
245 void (*track_buffer_callback)(struct mp3entry *id3, bool last_track);
246 void (*track_unbuffer_callback)(struct mp3entry *id3, bool last_track);
248 /* Configuration */
249 static size_t conf_watermark;
250 static size_t conf_filechunk;
251 static size_t conf_preseek;
252 static size_t buffer_margin;
253 static bool v1first = false;
255 /* Multiple threads */
256 static const char * get_codec_filename(int enc_spec);
257 static void set_filebuf_watermark(int seconds);
259 /* Audio thread */
260 static struct event_queue audio_queue;
261 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
262 static const char audio_thread_name[] = "audio";
264 static void audio_thread(void);
265 static void audio_initiate_track_change(long direction);
266 static bool audio_have_tracks(void);
267 static void audio_reset_buffer(void);
269 /* Codec thread */
270 extern struct codec_api ci;
271 static struct event_queue codec_queue;
272 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
273 IBSS_ATTR;
274 static const char codec_thread_name[] = "codec";
275 /* For modifying thread priority later. */
276 struct thread_entry *codec_thread_p;
278 /* Voice thread */
279 #ifdef PLAYBACK_VOICE
280 extern struct codec_api ci_voice;
282 static volatile bool voice_thread_start;
283 static volatile bool voice_is_playing;
284 static volatile bool voice_codec_loaded;
285 static void (*voice_getmore)(unsigned char** start, int* size);
286 static char *voicebuf;
287 static size_t voice_remaining;
288 static struct thread_entry *voice_thread_p = NULL;
290 static struct event_queue voice_queue;
291 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
292 IBSS_ATTR;
293 static const char voice_thread_name[] = "voice codec";
294 struct voice_info {
295 void (*callback)(unsigned char **start, int *size);
296 int size;
297 char *buf;
300 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
301 static void voice_boost_cpu(bool state);
302 #else
303 #define voice_boost_cpu(state) do { } while(0)
304 #endif
305 static void voice_thread(void);
307 #endif /* PLAYBACK_VOICE */
309 /* --- External interfaces --- */
311 void mp3_play_data(const unsigned char* start, int size,
312 void (*get_more)(unsigned char** start, int* size))
314 #ifdef PLAYBACK_VOICE
315 static struct voice_info voice_clip;
316 voice_clip.callback = get_more;
317 voice_clip.buf = (char *)start;
318 voice_clip.size = size;
319 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
320 queue_post(&voice_queue, Q_VOICE_STOP, 0);
321 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
322 queue_post(&voice_queue, Q_VOICE_PLAY, &voice_clip);
323 voice_thread_start = true;
324 voice_boost_cpu(true);
325 #else
326 (void) start;
327 (void) size;
328 (void) get_more;
329 #endif
332 void mp3_play_stop(void)
334 #ifdef PLAYBACK_VOICE
335 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
336 queue_post(&voice_queue, Q_VOICE_STOP, 0);
337 #endif
340 bool mp3_pause_done(void)
342 return pcm_is_paused();
345 void mpeg_id3_options(bool _v1first)
347 v1first = _v1first;
350 void audio_load_encoder(int enc_id)
352 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
353 const char *enc_fn = get_codec_filename(enc_id | CODEC_TYPE_ENCODER);
354 if (!enc_fn)
355 return;
357 audio_remove_encoder();
359 LOGFQUEUE("audio > codec Q_ENCODER_LOAD_DISK");
360 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (void *)enc_fn);
362 while (!ci.enc_codec_loaded)
363 yield();
364 #endif
365 return;
366 (void)enc_id;
367 } /* audio_load_encoder */
369 void audio_remove_encoder(void)
371 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
372 /* force encoder codec unload (if previously loaded) */
373 if (!ci.enc_codec_loaded)
374 return;
376 ci.stop_codec = true;
377 while (ci.enc_codec_loaded)
378 yield();
379 #endif
380 } /* audio_remove_encoder */
382 struct mp3entry* audio_current_track(void)
384 const char *filename;
385 const char *p;
386 static struct mp3entry temp_id3;
387 int cur_idx;
388 int offset = ci.new_track + wps_offset;
390 cur_idx = track_ridx + offset;
391 cur_idx &= MAX_TRACK_MASK;
393 if (tracks[cur_idx].taginfo_ready)
394 return &tracks[cur_idx].id3;
396 memset(&temp_id3, 0, sizeof(struct mp3entry));
398 filename = playlist_peek(offset);
399 if (!filename)
400 filename = "No file!";
402 #ifdef HAVE_TC_RAMCACHE
403 if (tagcache_fill_tags(&temp_id3, filename))
404 return &temp_id3;
405 #endif
407 p = strrchr(filename, '/');
408 if (!p)
409 p = filename;
410 else
411 p++;
413 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
414 temp_id3.title = &temp_id3.path[0];
416 return &temp_id3;
419 struct mp3entry* audio_next_track(void)
421 int next_idx = track_ridx;
423 if (!audio_have_tracks())
424 return NULL;
426 next_idx++;
427 next_idx &= MAX_TRACK_MASK;
429 if (!tracks[next_idx].taginfo_ready)
430 return NULL;
432 return &tracks[next_idx].id3;
435 bool audio_has_changed_track(void)
437 if (track_changed)
439 track_changed = false;
440 return true;
443 return false;
446 void audio_play(long offset)
448 logf("audio_play");
449 if (playing && offset <= 0)
451 LOGFQUEUE("audio > audio Q_AUDIO_NEW_PLAYLIST");
452 queue_post(&audio_queue, Q_AUDIO_NEW_PLAYLIST, 0);
454 else
456 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
457 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
458 LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
459 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
461 while (!playing)
462 yield();
465 void audio_stop(void)
467 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
468 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
469 while(playing)
470 yield();
473 void audio_pause(void)
475 LOGFQUEUE("audio > audio Q_AUDIO_PAUSE");
476 queue_post(&audio_queue, Q_AUDIO_PAUSE, (void *)true);
479 void audio_resume(void)
481 LOGFQUEUE("audio > audio Q_AUDIO_PAUSE resume");
482 queue_post(&audio_queue, Q_AUDIO_PAUSE, (void *)false);
485 void audio_next(void)
487 if (playlist_check(ci.new_track + wps_offset + 1))
489 if (global_settings.beep)
490 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
492 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
493 queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1);
494 /* Keep wps fast while our message travels inside deep playback queues. */
495 wps_offset++;
496 track_changed = true;
498 else
500 /* No more tracks. */
501 if (global_settings.beep)
502 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
506 void audio_prev(void)
508 if (playlist_check(ci.new_track + wps_offset - 1))
510 if (global_settings.beep)
511 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
513 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
514 queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1);
515 /* Keep wps fast while our message travels inside deep playback queues. */
516 wps_offset--;
517 track_changed = true;
519 else
521 /* No more tracks. */
522 if (global_settings.beep)
523 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
527 void audio_next_dir(void)
529 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
530 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, (void *)1);
533 void audio_prev_dir(void)
535 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
536 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, (void *)-1);
539 void audio_pre_ff_rewind(void)
541 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
542 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
545 void audio_ff_rewind(long newpos)
547 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
548 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, (int *)newpos);
551 void audio_flush_and_reload_tracks(void)
553 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
554 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
557 void audio_error_clear(void)
561 int audio_status(void)
563 int ret = 0;
565 if (playing)
566 ret |= AUDIO_STATUS_PLAY;
568 if (paused)
569 ret |= AUDIO_STATUS_PAUSE;
571 #ifdef HAVE_RECORDING
572 /* Do this here for constitency with mpeg.c version */
573 ret |= pcm_rec_status();
574 #endif
576 return ret;
579 bool audio_query_poweroff(void)
581 return !(playing && paused);
584 int audio_get_file_pos(void)
586 return 0;
589 void audio_set_buffer_margin(int setting)
591 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
592 buffer_margin = lookup[setting];
593 logf("buffer margin: %ds", buffer_margin);
594 set_filebuf_watermark(buffer_margin);
597 /* Set crossfade & PCM buffer length. */
598 void audio_set_crossfade(int enable)
600 size_t size;
601 bool was_playing = (playing && audio_is_initialized);
602 size_t offset = 0;
603 #if MEM > 1
604 int seconds = 1;
605 #endif
607 if (!filebuf)
608 return; /* Audio buffers not yet set up */
610 #if MEM > 1
611 if (enable)
612 seconds = global_settings.crossfade_fade_out_delay
613 + global_settings.crossfade_fade_out_duration;
615 /* Buffer has to be at least 2s long. */
616 seconds += 2;
617 logf("buf len: %d", seconds);
618 size = seconds * (NATIVE_FREQUENCY*4);
619 #else
620 enable = 0;
621 size = NATIVE_FREQUENCY*2;
622 #endif
623 if (pcmbuf_get_bufsize() == size)
624 return ;
626 if (was_playing)
628 /* Store the track resume position */
629 offset = CUR_TI->id3.offset;
631 /* Playback has to be stopped before changing the buffer size. */
632 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK));
633 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
634 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
635 while (audio_codec_loaded)
636 yield();
639 voice_stop();
641 /* Re-initialize audio system. */
642 pcmbuf_init(size);
643 pcmbuf_crossfade_enable(enable);
644 audio_reset_buffer();
645 logf("abuf:%dB", pcmbuf_get_bufsize());
646 logf("fbuf:%dB", filebuflen);
648 voice_init();
650 /* Restart playback. */
651 if (was_playing)
653 LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
654 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
656 /* Wait for the playback to start again (and display the splash
657 screen during that period. */
658 while (!playing)
659 yield();
663 void audio_preinit(void)
665 logf("playback system pre-init");
667 filling = false;
668 current_codec = CODEC_IDX_AUDIO;
669 playing = false;
670 paused = false;
671 audio_codec_loaded = false;
672 #ifdef PLAYBACK_VOICE
673 voice_is_playing = false;
674 voice_thread_start = false;
675 voice_codec_loaded = false;
676 #endif
677 track_changed = false;
678 current_fd = -1;
679 track_buffer_callback = NULL;
680 track_unbuffer_callback = NULL;
681 track_changed_callback = NULL;
682 /* Just to prevent CUR_TI never be anything random. */
683 track_ridx = 0;
685 mutex_init(&mutex_codecthread);
687 queue_init(&audio_queue, true);
688 queue_init(&codec_queue, true);
689 /* create a private queue */
690 queue_init(&codec_callback_queue, false);
692 create_thread(audio_thread, audio_stack, sizeof(audio_stack),
693 audio_thread_name IF_PRIO(, PRIORITY_BUFFERING));
696 void audio_init(void)
698 LOGFQUEUE("audio > audio Q_AUDIO_POSTINIT");
699 queue_post(&audio_queue, Q_AUDIO_POSTINIT, 0);
702 void voice_init(void)
704 #ifdef PLAYBACK_VOICE
705 if (!filebuf)
706 return; /* Audio buffers not yet set up */
708 if (voice_thread_p)
709 return;
711 if (!talk_voice_required())
712 return;
714 logf("Starting voice codec");
715 queue_init(&voice_queue, true);
716 voice_thread_p = create_thread(voice_thread, voice_stack,
717 sizeof(voice_stack), voice_thread_name
718 IF_PRIO(, PRIORITY_PLAYBACK));
720 while (!voice_codec_loaded)
721 yield();
722 #endif
723 } /* voice_init */
725 void voice_stop(void)
727 #ifdef PLAYBACK_VOICE
728 /* Messages should not be posted to voice codec queue unless it is the
729 current codec or deadlocks happen.
730 -- jhMikeS */
731 if (current_codec != CODEC_IDX_VOICE)
732 return;
734 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
735 queue_post(&voice_queue, Q_VOICE_STOP, 0);
736 while (voice_is_playing)
737 yield();
738 if (!playing)
739 pcmbuf_play_stop();
740 #endif
741 } /* voice_stop */
745 /* --- Routines called from multiple threads --- */
747 #ifdef PLAYBACK_VOICE
748 static void swap_codec(void)
750 int my_codec = current_codec;
752 logf("swapping out codec:%d", my_codec);
754 /* Save our current IRAM and DRAM */
755 memcpy(iram_buf[my_codec], (unsigned char *)CODEC_IRAM_ORIGIN,
756 CODEC_IRAM_SIZE);
757 memcpy(dram_buf[my_codec], codecbuf, CODEC_SIZE);
759 /* Release my semaphore */
760 mutex_unlock(&mutex_codecthread);
762 /* Loop until the other codec has locked and run */
763 do {
764 /* Release my semaphore and force a task switch. */
765 yield();
766 } while (my_codec == current_codec);
768 /* Wait for other codec to unlock */
769 mutex_lock(&mutex_codecthread);
771 /* Take control */
772 current_codec = my_codec;
774 /* Reload our IRAM and DRAM */
775 memcpy((unsigned char *)CODEC_IRAM_ORIGIN, iram_buf[my_codec],
776 CODEC_IRAM_SIZE);
777 invalidate_icache();
778 memcpy(codecbuf, dram_buf[my_codec], CODEC_SIZE);
780 logf("resuming codec:%d", my_codec);
782 #endif
784 static void set_filebuf_watermark(int seconds)
786 size_t bytes;
788 if (current_codec == CODEC_IDX_VOICE)
789 return;
791 if (!filebuf)
792 return; /* Audio buffers not yet set up */
794 bytes = MAX(CUR_TI->id3.bitrate * seconds * (1000/8), conf_watermark);
795 bytes = MIN(bytes, filebuflen / 2);
796 conf_watermark = bytes;
799 static const char * get_codec_filename(int enc_spec)
801 const char *fname;
802 int type = enc_spec & CODEC_TYPE_MASK;
803 int afmt = enc_spec & CODEC_AFMT_MASK;
805 if ((unsigned)afmt >= AFMT_NUM_CODECS)
806 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
808 fname = (type == CODEC_TYPE_DECODER) ?
809 audio_formats[afmt].codec_fn : audio_formats[afmt].codec_enc_fn;
811 logf("%s: %d - %s",
812 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
813 afmt, fname ? fname : "<unknown>");
815 return fname;
816 } /* get_codec_filename */
819 /* --- Voice thread --- */
821 #ifdef PLAYBACK_VOICE
823 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
824 static void voice_boost_cpu(bool state)
826 static bool voice_cpu_boosted = false;
828 if (state != voice_cpu_boosted)
830 voice_cpu_boosted = state;
831 cpu_boost_id(state, CPUBOOSTID_PLAYBACK_VOICE);
834 #endif
836 static bool voice_pcmbuf_insert_split_callback(
837 const void *ch1, const void *ch2, size_t length)
839 const char* src[2];
840 char *dest;
841 long input_size;
842 size_t output_size;
844 src[0] = ch1;
845 src[1] = ch2;
847 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
848 length *= 2; /* Length is per channel */
850 while (length)
852 long est_output_size = dsp_output_size(length);
854 while ((dest = pcmbuf_request_voice_buffer(est_output_size,
855 &output_size, playing)) == NULL)
857 if (playing && audio_codec_loaded)
858 swap_codec();
859 else
860 yield();
863 /* Get the real input_size for output_size bytes, guarding
864 * against resampling buffer overflows. */
865 input_size = dsp_input_size(output_size);
867 if (input_size <= 0)
869 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
870 output_size, length, input_size);
871 /* If this happens, there are samples of codec data that don't
872 * become a number of pcm samples, and something is broken */
873 return false;
876 /* Input size has grown, no error, just don't write more than length */
877 if ((size_t)input_size > length)
878 input_size = length;
880 output_size = dsp_process(dest, src, input_size);
882 if (playing)
884 pcmbuf_mix_voice(output_size);
885 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && audio_codec_loaded)
886 swap_codec();
888 else
889 pcmbuf_write_complete(output_size);
891 length -= input_size;
894 return true;
895 } /* voice_pcmbuf_insert_split_callback */
897 static bool voice_pcmbuf_insert_callback(const char *buf, size_t length)
899 /* TODO: The audiobuffer API should probably be updated, and be based on
900 * pcmbuf_insert_split(). */
901 long real_length = length;
903 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
904 length /= 2; /* Length is per channel */
906 /* Second channel is only used for non-interleaved stereo. */
907 return voice_pcmbuf_insert_split_callback(buf, buf + (real_length / 2),
908 length);
911 static void* voice_get_memory_callback(size_t *size)
913 *size = 0;
914 return NULL;
917 static void voice_set_elapsed_callback(unsigned int value)
919 (void)value;
922 static void voice_set_offset_callback(size_t value)
924 (void)value;
927 static size_t voice_filebuf_callback(void *ptr, size_t size)
929 (void)ptr;
930 (void)size;
932 return 0;
935 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
937 struct event ev;
939 if (ci_voice.new_track)
941 *realsize = 0;
942 return NULL;
945 while (1)
947 if (voice_is_playing || playing)
948 queue_wait_w_tmo(&voice_queue, &ev, 0);
949 else
950 queue_wait(&voice_queue, &ev);
951 if (!voice_is_playing)
953 if (ev.id == SYS_TIMEOUT)
954 ev.id = Q_AUDIO_PLAY;
957 switch (ev.id) {
958 case Q_AUDIO_PLAY:
959 LOGFQUEUE("voice < Q_AUDIO_PLAY");
960 if (playing)
962 if (audio_codec_loaded)
963 swap_codec();
964 yield();
966 break;
968 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
969 case Q_ENCODER_RECORD:
970 LOGFQUEUE("voice < Q_ENCODER_RECORD");
971 swap_codec();
972 break;
973 #endif
975 case Q_VOICE_STOP:
976 LOGFQUEUE("voice < Q_VOICE_STOP");
977 if (voice_is_playing)
979 /* Clear the current buffer */
980 voice_is_playing = false;
981 voice_getmore = NULL;
982 voice_remaining = 0;
983 voicebuf = NULL;
984 voice_boost_cpu(false);
986 /* Force the codec to think it's changing tracks */
987 ci_voice.new_track = 1;
988 *realsize = 0;
989 return NULL;
991 else
992 break;
994 case SYS_USB_CONNECTED:
995 LOGFQUEUE("voice < SYS_USB_CONNECTED");
996 usb_acknowledge(SYS_USB_CONNECTED_ACK);
997 if (audio_codec_loaded)
998 swap_codec();
999 usb_wait_for_disconnect(&voice_queue);
1000 break;
1002 case Q_VOICE_PLAY:
1003 LOGFQUEUE("voice < Q_VOICE_PLAY");
1004 if (!voice_is_playing)
1006 /* Slight hack - flush PCM buffer if only being used for voice */
1007 if (!playing && pcm_is_playing())
1008 pcmbuf_play_stop();
1010 /* Set up new voice data */
1011 struct voice_info *voice_data;
1012 voice_is_playing = true;
1013 voice_boost_cpu(true);
1014 voice_data = ev.data;
1015 voice_remaining = voice_data->size;
1016 voicebuf = voice_data->buf;
1017 voice_getmore = voice_data->callback;
1019 goto voice_play_clip;
1021 case SYS_TIMEOUT:
1022 LOGFQUEUE("voice < SYS_TIMEOUT");
1023 goto voice_play_clip;
1025 default:
1026 LOGFQUEUE("voice < default");
1030 voice_play_clip:
1032 if (voice_remaining == 0 || voicebuf == NULL)
1034 if (voice_getmore)
1035 voice_getmore((unsigned char **)&voicebuf, (int *)&voice_remaining);
1037 /* If this clip is done */
1038 if (voice_remaining == 0)
1040 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1041 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1042 /* Force pcm playback. */
1043 if (!pcm_is_playing())
1044 pcmbuf_play_start();
1048 *realsize = MIN(voice_remaining, reqsize);
1050 if (*realsize == 0)
1051 return NULL;
1053 return voicebuf;
1054 } /* voice_request_buffer_callback */
1056 static void voice_advance_buffer_callback(size_t amount)
1058 amount = MIN(amount, voice_remaining);
1059 voicebuf += amount;
1060 voice_remaining -= amount;
1063 static void voice_advance_buffer_loc_callback(void *ptr)
1065 size_t amount = (size_t)ptr - (size_t)voicebuf;
1067 voice_advance_buffer_callback(amount);
1070 static off_t voice_mp3_get_filepos_callback(int newtime)
1072 (void)newtime;
1074 return 0;
1077 static void voice_do_nothing(void)
1079 return;
1082 static bool voice_seek_buffer_callback(size_t newpos)
1084 (void)newpos;
1086 return false;
1089 static bool voice_request_next_track_callback(void)
1091 ci_voice.new_track = 0;
1092 return true;
1095 static void voice_thread(void)
1097 while (1)
1099 logf("Loading voice codec");
1100 voice_codec_loaded = true;
1101 mutex_lock(&mutex_codecthread);
1102 current_codec = CODEC_IDX_VOICE;
1103 dsp_configure(DSP_RESET, 0);
1104 voice_remaining = 0;
1105 voice_getmore = NULL;
1107 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1109 logf("Voice codec finished");
1110 voice_codec_loaded = false;
1111 mutex_unlock(&mutex_codecthread);
1113 } /* voice_thread */
1115 #endif /* PLAYBACK_VOICE */
1117 /* --- Codec thread --- */
1119 static bool codec_pcmbuf_insert_split_callback(
1120 const void *ch1, const void *ch2, size_t length)
1122 const char* src[2];
1123 char *dest;
1124 long input_size;
1125 size_t output_size;
1127 src[0] = ch1;
1128 src[1] = ch2;
1130 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1131 length *= 2; /* Length is per channel */
1133 while (length)
1135 long est_output_size = dsp_output_size(length);
1136 /* Prevent audio from a previous track from playing */
1137 if (ci.new_track || ci.stop_codec)
1138 return true;
1140 while ((dest = pcmbuf_request_buffer(est_output_size,
1141 &output_size)) == NULL)
1143 sleep(1);
1144 if (ci.seek_time || ci.new_track || ci.stop_codec)
1145 return true;
1148 /* Get the real input_size for output_size bytes, guarding
1149 * against resampling buffer overflows. */
1150 input_size = dsp_input_size(output_size);
1152 if (input_size <= 0)
1154 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
1155 output_size, length, input_size);
1156 /* If this happens, there are samples of codec data that don't
1157 * become a number of pcm samples, and something is broken */
1158 return false;
1161 /* Input size has grown, no error, just don't write more than length */
1162 if ((size_t)input_size > length)
1163 input_size = length;
1165 output_size = dsp_process(dest, src, input_size);
1167 pcmbuf_write_complete(output_size);
1169 #ifdef PLAYBACK_VOICE
1170 if ((voice_is_playing || voice_thread_start)
1171 && pcm_is_playing() && voice_codec_loaded &&
1172 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1174 voice_thread_start = false;
1175 swap_codec();
1177 #endif
1179 length -= input_size;
1182 return true;
1183 } /* codec_pcmbuf_insert_split_callback */
1185 static bool codec_pcmbuf_insert_callback(const char *buf, size_t length)
1187 /* TODO: The audiobuffer API should probably be updated, and be based on
1188 * pcmbuf_insert_split(). */
1189 long real_length = length;
1191 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
1192 length /= 2; /* Length is per channel */
1194 /* Second channel is only used for non-interleaved stereo. */
1195 return codec_pcmbuf_insert_split_callback(buf, buf + (real_length / 2),
1196 length);
1199 static void* codec_get_memory_callback(size_t *size)
1201 *size = MALLOC_BUFSIZE;
1202 return &audiobuf[talk_get_bufsize()];
1205 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1206 static void codec_pcmbuf_position_callback(size_t size)
1208 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1209 prev_ti->id3.elapsed;
1211 if (time >= prev_ti->id3.length)
1213 pcmbuf_set_position_callback(NULL);
1214 prev_ti->id3.elapsed = prev_ti->id3.length;
1216 else
1217 prev_ti->id3.elapsed = time;
1220 static void codec_set_elapsed_callback(unsigned int value)
1222 unsigned int latency;
1223 if (ci.seek_time)
1224 return;
1226 #ifdef AB_REPEAT_ENABLE
1227 ab_position_report(value);
1228 #endif
1230 latency = pcmbuf_get_latency();
1231 if (value < latency)
1232 CUR_TI->id3.elapsed = 0;
1233 else if (value - latency > CUR_TI->id3.elapsed ||
1234 value - latency < CUR_TI->id3.elapsed - 2)
1236 CUR_TI->id3.elapsed = value - latency;
1240 static void codec_set_offset_callback(size_t value)
1242 unsigned int latency;
1244 if (ci.seek_time)
1245 return;
1247 latency = pcmbuf_get_latency() * CUR_TI->id3.bitrate / 8;
1248 if (value < latency)
1249 CUR_TI->id3.offset = 0;
1250 else
1251 CUR_TI->id3.offset = value - latency;
1254 static void codec_advance_buffer_counters(size_t amount)
1256 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1258 ci.curpos += amount;
1259 CUR_TI->available -= amount;
1261 /* Start buffer filling as necessary. */
1262 if (!pcmbuf_is_lowdata() && !filling)
1264 if (conf_watermark && FILEBUFUSED <= conf_watermark && playing)
1266 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1267 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1272 /* copy up-to size bytes into ptr and return the actual size copied */
1273 static size_t codec_filebuf_callback(void *ptr, size_t size)
1275 char *buf = (char *)ptr;
1276 size_t copy_n;
1277 size_t part_n;
1279 if (ci.stop_codec || !playing)
1280 return 0;
1282 /* The ammount to copy is the lesser of the requested amount and the
1283 * amount left of the current track (both on disk and already loaded) */
1284 copy_n = MIN(size, CUR_TI->available + CUR_TI->filerem);
1286 /* Nothing requested OR nothing left */
1287 if (copy_n == 0)
1288 return 0;
1290 /* Let the disk buffer catch fill until enough data is available */
1291 while (copy_n > CUR_TI->available)
1293 if (!filling)
1295 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1296 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1299 sleep(1);
1300 if (ci.stop_codec || ci.new_track)
1301 return 0;
1304 /* Copy as much as possible without wrapping */
1305 part_n = MIN(copy_n, filebuflen - buf_ridx);
1306 memcpy(buf, &filebuf[buf_ridx], part_n);
1307 /* Copy the rest in the case of a wrap */
1308 if (part_n < copy_n) {
1309 memcpy(&buf[part_n], &filebuf[0], copy_n - part_n);
1312 /* Update read and other position pointers */
1313 codec_advance_buffer_counters(copy_n);
1315 /* Return the actual amount of data copied to the buffer */
1316 return copy_n;
1317 } /* codec_filebuf_callback */
1319 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1321 size_t short_n, copy_n, buf_rem;
1323 if (!playing)
1325 *realsize = 0;
1326 return NULL;
1329 copy_n = MIN(reqsize, CUR_TI->available + CUR_TI->filerem);
1330 if (copy_n == 0)
1332 *realsize = 0;
1333 return NULL;
1336 while (copy_n > CUR_TI->available)
1338 if (!filling)
1340 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1341 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1344 sleep(1);
1345 if (ci.stop_codec || ci.new_track)
1347 *realsize = 0;
1348 return NULL;
1352 /* How much is left at the end of the file buffer before wrap? */
1353 buf_rem = filebuflen - buf_ridx;
1355 /* If we can't satisfy the request without wrapping */
1356 if (buf_rem < copy_n)
1358 /* How short are we? */
1359 short_n = copy_n - buf_rem;
1361 /* If we can fudge it with the guardbuf */
1362 if (short_n < GUARD_BUFSIZE)
1363 memcpy(&filebuf[filebuflen], &filebuf[0], short_n);
1364 else
1365 copy_n = buf_rem;
1368 *realsize = copy_n;
1370 return (char *)&filebuf[buf_ridx];
1371 } /* codec_request_buffer_callback */
1373 static int get_codec_base_type(int type)
1375 switch (type) {
1376 case AFMT_MPA_L1:
1377 case AFMT_MPA_L2:
1378 case AFMT_MPA_L3:
1379 return AFMT_MPA_L3;
1382 return type;
1385 static void codec_advance_buffer_callback(size_t amount)
1387 if (amount > CUR_TI->available + CUR_TI->filerem)
1388 amount = CUR_TI->available + CUR_TI->filerem;
1390 while (amount > CUR_TI->available && filling)
1391 sleep(1);
1393 if (amount > CUR_TI->available)
1395 struct event ev;
1397 LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK");
1398 queue_post(&audio_queue,
1399 Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount));
1401 queue_wait(&codec_callback_queue, &ev);
1402 switch (ev.id)
1404 case Q_CODEC_REQUEST_FAILED:
1405 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1406 ci.stop_codec = true;
1407 return;
1409 case Q_CODEC_REQUEST_COMPLETE:
1410 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1411 return;
1413 default:
1414 LOGFQUEUE("codec < default");
1415 ci.stop_codec = true;
1416 return;
1420 codec_advance_buffer_counters(amount);
1422 codec_set_offset_callback(ci.curpos);
1425 static void codec_advance_buffer_loc_callback(void *ptr)
1427 size_t amount = (size_t)ptr - (size_t)&filebuf[buf_ridx];
1429 codec_advance_buffer_callback(amount);
1432 /* Copied from mpeg.c. Should be moved somewhere else. */
1433 static int codec_get_file_pos(void)
1435 int pos = -1;
1436 struct mp3entry *id3 = audio_current_track();
1438 if (id3->vbr)
1440 if (id3->has_toc)
1442 /* Use the TOC to find the new position */
1443 unsigned int percent, remainder;
1444 int curtoc, nexttoc, plen;
1446 percent = (id3->elapsed*100)/id3->length;
1447 if (percent > 99)
1448 percent = 99;
1450 curtoc = id3->toc[percent];
1452 if (percent < 99)
1453 nexttoc = id3->toc[percent+1];
1454 else
1455 nexttoc = 256;
1457 pos = (id3->filesize/256)*curtoc;
1459 /* Use the remainder to get a more accurate position */
1460 remainder = (id3->elapsed*100)%id3->length;
1461 remainder = (remainder*100)/id3->length;
1462 plen = (nexttoc - curtoc)*(id3->filesize/256);
1463 pos += (plen/100)*remainder;
1465 else
1467 /* No TOC exists, estimate the new position */
1468 pos = (id3->filesize / (id3->length / 1000)) *
1469 (id3->elapsed / 1000);
1472 else if (id3->bitrate)
1473 pos = id3->elapsed * (id3->bitrate / 8);
1474 else
1475 return -1;
1477 /* Don't seek right to the end of the file so that we can
1478 transition properly to the next song */
1479 if (pos >= (int)(id3->filesize - id3->id3v1len))
1480 pos = id3->filesize - id3->id3v1len - 1;
1481 /* skip past id3v2 tag and other leading garbage */
1482 else if (pos < (int)id3->first_frame_offset)
1483 pos = id3->first_frame_offset;
1485 return pos;
1488 static off_t codec_mp3_get_filepos_callback(int newtime)
1490 off_t newpos;
1492 CUR_TI->id3.elapsed = newtime;
1493 newpos = codec_get_file_pos();
1495 return newpos;
1498 static void codec_seek_complete_callback(void)
1500 logf("seek_complete");
1501 if (pcm_is_paused())
1503 /* If this is not a seamless seek, clear the buffer */
1504 pcmbuf_play_stop();
1506 /* If playback was not 'deliberately' paused, unpause now */
1507 if (!paused)
1508 pcmbuf_pause(false);
1510 ci.seek_time = 0;
1513 static bool codec_seek_buffer_callback(size_t newpos)
1515 int difference;
1517 logf("codec_seek_buffer_callback");
1519 if (newpos >= CUR_TI->filesize)
1520 newpos = CUR_TI->filesize - 1;
1522 difference = newpos - ci.curpos;
1523 if (difference >= 0)
1525 /* Seeking forward */
1526 logf("seek: +%d", difference);
1527 codec_advance_buffer_callback(difference);
1528 return true;
1531 /* Seeking backward */
1532 difference = -difference;
1533 if (ci.curpos - difference < 0)
1534 difference = ci.curpos;
1536 /* We need to reload the song. */
1537 if (newpos < CUR_TI->start_pos)
1539 struct event ev;
1541 LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK");
1542 queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos);
1544 queue_wait(&codec_callback_queue, &ev);
1545 switch (ev.id)
1547 case Q_CODEC_REQUEST_COMPLETE:
1548 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1549 return true;
1551 case Q_CODEC_REQUEST_FAILED:
1552 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1553 ci.stop_codec = true;
1554 return false;
1556 default:
1557 LOGFQUEUE("codec < default");
1558 return false;
1562 /* Seeking inside buffer space. */
1563 logf("seek: -%d", difference);
1564 CUR_TI->available += difference;
1565 buf_ridx = RINGBUF_SUB(buf_ridx, (unsigned)difference);
1566 ci.curpos -= difference;
1568 return true;
1571 static void codec_configure_callback(int setting, void *value)
1573 switch (setting) {
1574 case CODEC_SET_FILEBUF_WATERMARK:
1575 conf_watermark = (unsigned long)value;
1576 set_filebuf_watermark(buffer_margin);
1577 break;
1579 case CODEC_SET_FILEBUF_CHUNKSIZE:
1580 conf_filechunk = (unsigned long)value;
1581 break;
1583 case CODEC_SET_FILEBUF_PRESEEK:
1584 conf_preseek = (unsigned long)value;
1585 break;
1587 default:
1588 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1592 static void codec_track_changed(void)
1594 automatic_skip = false;
1595 track_changed = true;
1596 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1597 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1600 static void codec_pcmbuf_track_changed_callback(void)
1602 pcmbuf_set_position_callback(NULL);
1603 codec_track_changed();
1606 static void codec_discard_codec_callback(void)
1608 if (CUR_TI->has_codec)
1610 CUR_TI->has_codec = false;
1611 buf_ridx = RINGBUF_ADD(buf_ridx, CUR_TI->codecsize);
1614 #if 0
1615 /* Check if a buffer desync has happened, log it and stop playback. */
1616 if (buf_ridx != CUR_TI->buf_idx)
1618 int offset = CUR_TI->buf_idx - buf_ridx;
1619 size_t new_used = FILEBUFUSED - offset;
1621 logf("Buf off :%d=%d-%d", offset, CUR_TI->buf_idx, buf_ridx);
1622 logf("Used off:%d",FILEBUFUSED - new_used);
1624 /* This is a fatal internal error and it's not safe to
1625 * continue playback. */
1626 ci.stop_codec = true;
1627 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1629 #endif
1632 static void codec_track_skip_done(bool was_manual)
1634 /* Manual track change (always crossfade or flush audio). */
1635 if (was_manual)
1637 pcmbuf_crossfade_init(true);
1638 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1639 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1641 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1642 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1643 && global_settings.crossfade != 2)
1645 pcmbuf_crossfade_init(false);
1646 codec_track_changed();
1648 /* Gapless playback. */
1649 else
1651 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1652 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1656 static bool codec_load_next_track(void)
1658 struct event ev;
1660 if (ci.seek_time)
1661 codec_seek_complete_callback();
1663 #ifdef AB_REPEAT_ENABLE
1664 ab_end_of_track_report();
1665 #endif
1667 logf("Request new track");
1669 if (ci.new_track == 0)
1671 ci.new_track++;
1672 automatic_skip = true;
1675 cpu_boost_id(true, CPUBOOSTID_PLAYBACK_CODEC);
1676 LOGFQUEUE("codec > audio Q_AUDIO_CHECK_NEW_TRACK");
1677 queue_post(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1678 while (1)
1680 queue_wait(&codec_callback_queue, &ev);
1681 if (ev.id == Q_CODEC_REQUEST_PENDING)
1683 if (!automatic_skip)
1684 pcmbuf_play_stop();
1686 else
1687 break;
1689 cpu_boost_id(false, CPUBOOSTID_PLAYBACK_CODEC);
1690 switch (ev.id)
1692 case Q_CODEC_REQUEST_COMPLETE:
1693 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1694 codec_track_skip_done(!automatic_skip);
1695 return true;
1697 case Q_CODEC_REQUEST_FAILED:
1698 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1699 ci.new_track = 0;
1700 ci.stop_codec = true;
1701 return false;
1703 default:
1704 LOGFQUEUE("codec < default");
1705 ci.stop_codec = true;
1706 return false;
1710 static bool codec_request_next_track_callback(void)
1712 int prev_codectype;
1714 if (ci.stop_codec || !playing)
1715 return false;
1717 prev_codectype = get_codec_base_type(CUR_TI->id3.codectype);
1719 if (!codec_load_next_track())
1720 return false;
1722 /* Check if the next codec is the same file. */
1723 if (prev_codectype == get_codec_base_type(CUR_TI->id3.codectype))
1725 logf("New track loaded");
1726 codec_discard_codec_callback();
1727 return true;
1729 else
1731 logf("New codec:%d/%d", CUR_TI->id3.codectype, prev_codectype);
1732 return false;
1736 static void codec_thread(void)
1738 struct event ev;
1739 int status;
1740 size_t wrap;
1742 while (1) {
1743 status = 0;
1744 queue_wait(&codec_queue, &ev);
1746 switch (ev.id) {
1747 case Q_CODEC_LOAD_DISK:
1748 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1749 audio_codec_loaded = true;
1750 #ifdef PLAYBACK_VOICE
1751 /* Don't sent messages to voice codec if it's not current */
1752 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1754 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1755 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1757 #endif
1758 mutex_lock(&mutex_codecthread);
1759 current_codec = CODEC_IDX_AUDIO;
1760 ci.stop_codec = false;
1761 status = codec_load_file((const char *)ev.data, &ci);
1762 mutex_unlock(&mutex_codecthread);
1763 break ;
1765 case Q_CODEC_LOAD:
1766 LOGFQUEUE("codec < Q_CODEC_LOAD");
1767 if (!CUR_TI->has_codec) {
1768 logf("Codec slot is empty!");
1769 /* Wait for the pcm buffer to go empty */
1770 while (pcm_is_playing())
1771 yield();
1772 /* This must be set to prevent an infinite loop */
1773 ci.stop_codec = true;
1774 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1775 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1776 break ;
1779 audio_codec_loaded = true;
1780 #ifdef PLAYBACK_VOICE
1781 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1783 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1784 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1786 #endif
1787 mutex_lock(&mutex_codecthread);
1788 current_codec = CODEC_IDX_AUDIO;
1789 ci.stop_codec = false;
1790 wrap = (size_t)&filebuf[filebuflen] - (size_t)CUR_TI->codecbuf;
1791 status = codec_load_ram(CUR_TI->codecbuf, CUR_TI->codecsize,
1792 &filebuf[0], wrap, &ci);
1793 mutex_unlock(&mutex_codecthread);
1794 break ;
1796 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
1797 case Q_ENCODER_LOAD_DISK:
1798 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1799 audio_codec_loaded = false; /* Not audio codec! */
1800 #ifdef PLAYBACK_VOICE
1801 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1803 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1804 queue_post(&voice_queue, Q_ENCODER_RECORD, NULL);
1806 #endif
1807 mutex_lock(&mutex_codecthread);
1808 current_codec = CODEC_IDX_AUDIO;
1809 ci.stop_codec = false;
1810 status = codec_load_file((const char *)ev.data, &ci);
1811 mutex_unlock(&mutex_codecthread);
1812 break;
1813 #endif
1815 #ifndef SIMULATOR
1816 case SYS_USB_CONNECTED:
1817 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1818 queue_clear(&codec_queue);
1819 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1820 usb_wait_for_disconnect(&codec_queue);
1821 break;
1822 #endif
1824 default:
1825 LOGFQUEUE("codec < default");
1828 if (audio_codec_loaded)
1830 if (ci.stop_codec)
1832 status = CODEC_OK;
1833 if (!playing)
1834 pcmbuf_play_stop();
1836 audio_codec_loaded = false;
1839 switch (ev.id) {
1840 case Q_CODEC_LOAD_DISK:
1841 case Q_CODEC_LOAD:
1842 LOGFQUEUE("codec < Q_CODEC_LOAD");
1843 if (playing)
1845 if (ci.new_track || status != CODEC_OK)
1847 if (!ci.new_track)
1849 logf("Codec failure");
1850 gui_syncsplash(HZ*2, true, "Codec failure");
1853 if (!codec_load_next_track())
1855 // queue_post(&codec_queue, Q_AUDIO_STOP, 0);
1856 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1857 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1858 break;
1861 else
1863 logf("Codec finished");
1864 if (ci.stop_codec)
1866 /* Wait for the audio to stop playing before
1867 * triggering the WPS exit */
1868 while(pcm_is_playing())
1869 sleep(1);
1870 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1871 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1872 break;
1876 if (CUR_TI->has_codec)
1878 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
1879 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
1881 else
1883 const char *codec_fn = get_codec_filename(CUR_TI->id3.codectype);
1884 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1885 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
1886 (void *)codec_fn);
1889 break;
1891 default:
1892 LOGFQUEUE("codec < default");
1894 } /* end switch */
1899 /* --- Audio thread --- */
1901 static bool audio_filebuf_is_lowdata(void)
1903 return FILEBUFUSED < AUDIO_FILEBUF_CRITICAL;
1906 static bool audio_have_tracks(void)
1908 return track_ridx != track_widx || CUR_TI->filesize;
1911 static bool audio_have_free_tracks(void)
1913 if (track_widx < track_ridx)
1914 return track_widx + 1 < track_ridx;
1915 else if (track_ridx == 0)
1916 return track_widx < MAX_TRACK - 1;
1918 return true;
1921 int audio_track_count(void)
1923 if (audio_have_tracks())
1925 int relative_track_widx = track_widx;
1927 if (track_ridx > track_widx)
1928 relative_track_widx += MAX_TRACK;
1930 return relative_track_widx - track_ridx + 1;
1933 return 0;
1936 long audio_filebufused(void)
1938 return (long) FILEBUFUSED;
1941 /* Count the data BETWEEN the selected tracks */
1942 static size_t audio_buffer_count_tracks(int from_track, int to_track)
1944 size_t amount = 0;
1945 bool need_wrap = to_track < from_track;
1947 while (1)
1949 if (++from_track >= MAX_TRACK)
1951 from_track -= MAX_TRACK;
1952 need_wrap = false;
1955 if (from_track >= to_track && !need_wrap)
1956 break;
1958 amount += tracks[from_track].codecsize + tracks[from_track].filesize;
1960 return amount;
1963 static bool audio_buffer_wind_forward(int new_track_ridx, int old_track_ridx)
1965 size_t amount;
1967 /* Start with the remainder of the previously playing track */
1968 amount = tracks[old_track_ridx].filesize - ci.curpos;
1969 /* Then collect all data from tracks in between them */
1970 amount += audio_buffer_count_tracks(old_track_ridx, new_track_ridx);
1972 if (amount > FILEBUFUSED)
1973 return false;
1975 logf("bwf:%ldB",amount);
1977 /* Wind the buffer to the beginning of the target track or its codec */
1978 buf_ridx = RINGBUF_ADD(buf_ridx, amount);
1980 return true;
1983 static bool audio_buffer_wind_backward(int new_track_ridx, int old_track_ridx)
1985 /* Available buffer data */
1986 size_t buf_back;
1987 /* Start with the previously playing track's data and our data */
1988 size_t amount;
1990 amount = ci.curpos;
1991 buf_back = RINGBUF_SUB(buf_ridx, buf_widx);
1993 /* If we're not just resetting the current track */
1994 if (new_track_ridx != old_track_ridx)
1996 /* Need to wind to before the old track's codec and our filesize */
1997 amount += tracks[old_track_ridx].codecsize;
1998 amount += tracks[new_track_ridx].filesize;
2000 /* Rewind the old track to its beginning */
2001 tracks[old_track_ridx].available =
2002 tracks[old_track_ridx].filesize - tracks[old_track_ridx].filerem;
2005 /* If the codec was ever buffered */
2006 if (tracks[new_track_ridx].codecsize)
2008 /* Add the codec to the needed size */
2009 amount += tracks[new_track_ridx].codecsize;
2010 tracks[new_track_ridx].has_codec = true;
2013 /* Then collect all data from tracks between new and old */
2014 amount += audio_buffer_count_tracks(new_track_ridx, old_track_ridx);
2016 /* Do we have space to make this skip? */
2017 if (amount > buf_back)
2018 return false;
2020 logf("bwb:%ldB",amount);
2022 /* Rewind the buffer to the beginning of the target track or its codec */
2023 buf_ridx = RINGBUF_SUB(buf_ridx, amount);
2025 /* Reset to the beginning of the new track */
2026 tracks[new_track_ridx].available = tracks[new_track_ridx].filesize;
2028 return true;
2031 static void audio_update_trackinfo(void)
2033 ci.filesize = CUR_TI->filesize;
2034 CUR_TI->id3.elapsed = 0;
2035 CUR_TI->id3.offset = 0;
2036 ci.id3 = &CUR_TI->id3;
2037 ci.curpos = 0;
2038 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2041 /* Yield to codecs for as long as possible if they are in need of data
2042 * return true if the caller should break to let the audio thread process
2043 * new events */
2044 static bool audio_yield_codecs(void)
2046 yield();
2048 if (!queue_empty(&audio_queue))
2049 return true;
2051 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2052 && !ci.stop_codec && playing && !audio_filebuf_is_lowdata())
2054 sleep(1);
2055 if (!queue_empty(&audio_queue))
2056 return true;
2059 return false;
2062 /* Note that this function might yield(). */
2063 static void audio_clear_track_entries(
2064 bool clear_buffered, bool clear_unbuffered,
2065 bool may_yield)
2067 int cur_idx = track_widx;
2068 int last_idx = -1;
2070 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2072 /* Loop over all tracks from write-to-read */
2073 while (1)
2075 cur_idx++;
2076 cur_idx &= MAX_TRACK_MASK;
2078 if (cur_idx == track_ridx)
2079 break;
2081 /* If the track is buffered, conditionally clear/notify,
2082 * otherwise clear the track if that option is selected */
2083 if (tracks[cur_idx].event_sent)
2085 if (clear_buffered)
2087 if (last_idx >= 0)
2089 /* If there is an unbuffer callback, call it, otherwise,
2090 * just clear the track */
2091 if (track_unbuffer_callback)
2093 if (may_yield)
2094 audio_yield_codecs();
2095 track_unbuffer_callback(&tracks[last_idx].id3, false);
2098 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2100 last_idx = cur_idx;
2103 else if (clear_unbuffered)
2104 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
2107 /* We clear the previous instance of a buffered track throughout
2108 * the above loop to facilitate 'last' detection. Clear/notify
2109 * the last track here */
2110 if (last_idx >= 0)
2112 if (track_unbuffer_callback)
2113 track_unbuffer_callback(&tracks[last_idx].id3, true);
2114 memset(&tracks[last_idx], 0, sizeof(struct track_info));
2118 /* FIXME: This code should be made more generic and move to metadata.c */
2119 static void audio_strip_id3v1_tag(void)
2121 int i;
2122 static const unsigned char tag[] = "TAG";
2123 size_t tag_idx;
2124 size_t cur_idx;
2126 tag_idx = RINGBUF_SUB(buf_widx, 128);
2128 if (FILEBUFUSED > 128 && tag_idx > buf_ridx)
2130 cur_idx = tag_idx;
2131 for(i = 0;i < 3;i++)
2133 if(filebuf[cur_idx] != tag[i])
2134 return;
2136 cur_idx = RINGBUF_ADD(cur_idx, 1);
2139 /* Skip id3v1 tag */
2140 logf("Skipping ID3v1 tag");
2141 buf_widx = tag_idx;
2142 tracks[track_widx].available -= 128;
2143 tracks[track_widx].filesize -= 128;
2147 static void audio_read_file(bool quick)
2149 size_t copy_n;
2150 int rc;
2152 /* If we're called and no file is open, this is an error */
2153 if (current_fd < 0)
2155 logf("Bad fd in arf");
2156 /* Stop this buffer cycle immediately */
2157 fill_bytesleft = 0;
2158 /* Give some hope of miraculous recovery by forcing a track reload */
2159 tracks[track_widx].filesize = 0;
2160 return ;
2163 cpu_boost_id(true, CPUBOOSTID_PLAYBACK_AUDIO);
2164 while (tracks[track_widx].filerem > 0)
2166 int overlap;
2168 if (fill_bytesleft == 0)
2169 break ;
2171 /* copy_n is the largest chunk that is safe to read */
2172 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2173 copy_n = MIN(copy_n, fill_bytesleft);
2175 /* rc is the actual amount read */
2176 rc = read(current_fd, &filebuf[buf_widx], copy_n);
2178 if (rc <= 0)
2180 /* Reached the end of the file */
2181 tracks[track_widx].filerem = 0;
2182 break ;
2185 overlap = buf_widx + rc - CUR_TI->buf_idx;
2186 buf_widx = RINGBUF_ADD(buf_widx, rc);
2188 if (overlap > 0 && (unsigned) overlap >= filebuflen)
2189 overlap -= filebuflen;
2191 if (overlap > 0 && overlap <= rc && CUR_TI->available != 0) {
2192 CUR_TI->buf_idx = buf_widx;
2193 CUR_TI->start_pos += overlap;
2196 tracks[track_widx].available += rc;
2197 tracks[track_widx].filerem -= rc;
2199 if (fill_bytesleft > (unsigned)rc)
2200 fill_bytesleft -= rc;
2201 else
2202 fill_bytesleft = 0;
2204 /* Let the codec process until it is out of the danger zone, or there
2205 * is an event to handle. In the latter case, break this fill cycle
2206 * immediately */
2207 if (quick || audio_yield_codecs())
2208 break;
2211 if (tracks[track_widx].filerem == 0)
2213 logf("Finished buf:%dB", tracks[track_widx].filesize);
2214 close(current_fd);
2215 current_fd = -1;
2216 audio_strip_id3v1_tag();
2218 track_widx++;
2219 track_widx &= MAX_TRACK_MASK;
2221 tracks[track_widx].filesize = 0;
2223 else
2225 logf("Partially buf:%dB",
2226 tracks[track_widx].filesize - tracks[track_widx].filerem);
2228 cpu_boost_id(false, CPUBOOSTID_PLAYBACK_AUDIO);
2231 static bool audio_loadcodec(bool start_play)
2233 size_t size;
2234 int fd;
2235 int rc;
2236 size_t copy_n;
2237 int prev_track;
2238 char codec_path[MAX_PATH]; /* Full path to codec */
2240 const char * codec_fn = get_codec_filename(tracks[track_widx].id3.codectype);
2241 if (codec_fn == NULL)
2242 return false;
2244 tracks[track_widx].has_codec = false;
2245 tracks[track_widx].codecsize = 0;
2247 if (start_play)
2249 /* Load the codec directly from disk and save some memory. */
2250 track_ridx = track_widx;
2251 ci.filesize = CUR_TI->filesize;
2252 ci.id3 = &CUR_TI->id3;
2253 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2254 ci.curpos = 0;
2255 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2256 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_fn);
2257 return true;
2259 else
2261 /* If we already have another track than this one buffered */
2262 if (track_widx != track_ridx)
2264 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2266 /* If the previous codec is the same as this one, there is no need
2267 * to put another copy of it on the file buffer */
2268 if (get_codec_base_type(tracks[track_widx].id3.codectype) ==
2269 get_codec_base_type(tracks[prev_track].id3.codectype)
2270 && audio_codec_loaded)
2272 logf("Reusing prev. codec");
2273 return true;
2278 codec_get_full_path(codec_path, codec_fn);
2280 fd = open(codec_path, O_RDONLY);
2281 if (fd < 0)
2283 logf("Codec doesn't exist!");
2284 return false;
2287 size = filesize(fd);
2289 /* Never load a partial codec */
2290 if (fill_bytesleft < size)
2292 logf("Not enough space");
2293 fill_bytesleft = 0;
2294 close(fd);
2295 return false;
2298 while (tracks[track_widx].codecsize < size)
2300 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
2301 rc = read(fd, &filebuf[buf_widx], copy_n);
2302 if (rc < 0)
2304 close(fd);
2305 return false;
2308 if (fill_bytesleft > (unsigned)rc)
2309 fill_bytesleft -= rc;
2310 else
2311 fill_bytesleft = 0;
2313 buf_widx = RINGBUF_ADD(buf_widx, rc);
2315 tracks[track_widx].codecsize += rc;
2318 tracks[track_widx].has_codec = true;
2320 close(fd);
2321 logf("Done: %dB", size);
2323 return true;
2326 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2327 static void audio_set_elapsed(struct mp3entry* id3)
2329 if ( id3->vbr ) {
2330 if ( id3->has_toc ) {
2331 /* calculate elapsed time using TOC */
2332 int i;
2333 unsigned int remainder, plen, relpos, nextpos;
2335 /* find wich percent we're at */
2336 for (i=0; i<100; i++ )
2337 if ( id3->offset < id3->toc[i] * (id3->filesize / 256) )
2338 break;
2340 i--;
2341 if (i < 0)
2342 i = 0;
2344 relpos = id3->toc[i];
2346 if (i < 99)
2347 nextpos = id3->toc[i+1];
2348 else
2349 nextpos = 256;
2351 remainder = id3->offset - (relpos * (id3->filesize / 256));
2353 /* set time for this percent (divide before multiply to prevent
2354 overflow on long files. loss of precision is negligible on
2355 short files) */
2356 id3->elapsed = i * (id3->length / 100);
2358 /* calculate remainder time */
2359 plen = (nextpos - relpos) * (id3->filesize / 256);
2360 id3->elapsed += (((remainder * 100) / plen) *
2361 (id3->length / 10000));
2363 else {
2364 /* no TOC exists. set a rough estimate using average bitrate */
2365 int tpk = id3->length / (id3->filesize / 1024);
2366 id3->elapsed = id3->offset / 1024 * tpk;
2369 else
2371 /* constant bitrate, use exact calculation */
2372 if (id3->bitrate != 0)
2373 id3->elapsed = id3->offset / (id3->bitrate / 8);
2377 static bool audio_load_track(int offset, bool start_play, bool rebuffer)
2379 char *trackname;
2380 off_t size;
2381 char msgbuf[80];
2383 /* Stop buffer filling if there is no free track entries.
2384 Don't fill up the last track entry (we wan't to store next track
2385 metadata there). */
2386 if (!audio_have_free_tracks())
2388 logf("No free tracks");
2389 return false;
2392 if (current_fd >= 0)
2394 logf("Nonzero fd in alt");
2395 close(current_fd);
2396 current_fd = -1;
2399 last_peek_offset++;
2400 peek_again:
2401 logf("Buffering track:%d/%d", track_widx, track_ridx);
2402 /* Get track name from current playlist read position. */
2403 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2405 /* Handle broken playlists. */
2406 current_fd = open(trackname, O_RDONLY);
2407 if (current_fd < 0)
2409 logf("Open failed");
2410 /* Skip invalid entry from playlist. */
2411 playlist_skip_entry(NULL, last_peek_offset);
2413 else
2414 break;
2417 if (!trackname)
2419 logf("End-of-playlist");
2420 playlist_end = true;
2421 return false;
2424 /* Initialize track entry. */
2425 size = filesize(current_fd);
2426 tracks[track_widx].filerem = size;
2427 tracks[track_widx].filesize = size;
2428 tracks[track_widx].available = 0;
2430 /* Set default values */
2431 if (start_play)
2433 int last_codec = current_codec;
2435 current_codec = CODEC_IDX_AUDIO;
2436 conf_watermark = AUDIO_DEFAULT_WATERMARK;
2437 conf_filechunk = AUDIO_DEFAULT_FILECHUNK;
2438 conf_preseek = AUDIO_REBUFFER_GUESS_SIZE;
2439 dsp_configure(DSP_RESET, 0);
2440 current_codec = last_codec;
2443 /* Get track metadata if we don't already have it. */
2444 if (!tracks[track_widx].taginfo_ready)
2446 if (get_metadata(&tracks[track_widx],current_fd,trackname,v1first))
2448 if (start_play)
2450 track_changed = true;
2451 playlist_update_resume_info(audio_current_track());
2454 else
2456 logf("mde:%s!",trackname);
2458 /* Set filesize to zero to indicate no file was loaded. */
2459 tracks[track_widx].filesize = 0;
2460 tracks[track_widx].filerem = 0;
2461 close(current_fd);
2462 current_fd = -1;
2464 /* Skip invalid entry from playlist. */
2465 playlist_skip_entry(NULL, last_peek_offset);
2466 tracks[track_widx].taginfo_ready = false;
2467 goto peek_again;
2472 /* Load the codec. */
2473 tracks[track_widx].codecbuf = &filebuf[buf_widx];
2474 if (!audio_loadcodec(start_play))
2476 if (tracks[track_widx].codecsize)
2478 /* Must undo the buffer write of the partial codec */
2479 logf("Partial codec loaded");
2480 fill_bytesleft += tracks[track_widx].codecsize;
2481 buf_widx = RINGBUF_SUB(buf_widx, tracks[track_widx].codecsize);
2482 tracks[track_widx].codecsize = 0;
2485 /* Set filesize to zero to indicate no file was loaded. */
2486 tracks[track_widx].filesize = 0;
2487 tracks[track_widx].filerem = 0;
2488 close(current_fd);
2489 current_fd = -1;
2491 /* Try skipping to next track if there is space. */
2492 if (fill_bytesleft > 0)
2494 /* This is an error condition unless the fill_bytesleft is 0 */
2495 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2496 /* We should not use gui_syncplash from audio thread! */
2497 gui_syncsplash(HZ*2, true, msgbuf);
2498 /* Skip invalid entry from playlist. */
2499 playlist_skip_entry(NULL, last_peek_offset);
2500 tracks[track_widx].taginfo_ready = false;
2501 goto peek_again;
2504 return false;
2507 tracks[track_widx].start_pos = 0;
2508 set_filebuf_watermark(buffer_margin);
2509 tracks[track_widx].id3.elapsed = 0;
2511 if (offset > 0)
2513 switch (tracks[track_widx].id3.codectype) {
2514 case AFMT_MPA_L1:
2515 case AFMT_MPA_L2:
2516 case AFMT_MPA_L3:
2517 lseek(current_fd, offset, SEEK_SET);
2518 tracks[track_widx].id3.offset = offset;
2519 audio_set_elapsed(&tracks[track_widx].id3);
2520 tracks[track_widx].filerem = size - offset;
2521 ci.curpos = offset;
2522 tracks[track_widx].start_pos = offset;
2523 break;
2525 case AFMT_WAVPACK:
2526 lseek(current_fd, offset, SEEK_SET);
2527 tracks[track_widx].id3.offset = offset;
2528 tracks[track_widx].id3.elapsed =
2529 tracks[track_widx].id3.length / 2;
2530 tracks[track_widx].filerem = size - offset;
2531 ci.curpos = offset;
2532 tracks[track_widx].start_pos = offset;
2533 break;
2535 case AFMT_OGG_VORBIS:
2536 case AFMT_FLAC:
2537 case AFMT_PCM_WAV:
2538 case AFMT_A52:
2539 case AFMT_AAC:
2540 tracks[track_widx].id3.offset = offset;
2541 break;
2546 logf("alt:%s", trackname);
2547 tracks[track_widx].buf_idx = buf_widx;
2549 audio_read_file(rebuffer);
2551 return true;
2554 static bool audio_read_next_metadata(void)
2556 int fd;
2557 char *trackname;
2558 int next_idx;
2559 int status;
2561 next_idx = track_widx;
2562 if (tracks[next_idx].taginfo_ready)
2564 next_idx++;
2565 next_idx &= MAX_TRACK_MASK;
2567 if (tracks[next_idx].taginfo_ready)
2568 return true;
2571 trackname = playlist_peek(last_peek_offset + 1);
2572 if (!trackname)
2573 return false;
2575 fd = open(trackname, O_RDONLY);
2576 if (fd < 0)
2577 return false;
2579 status = get_metadata(&tracks[next_idx],fd,trackname,v1first);
2580 /* Preload the glyphs in the tags */
2581 if (status)
2583 if (tracks[next_idx].id3.title)
2584 lcd_getstringsize(tracks[next_idx].id3.title, NULL, NULL);
2585 if (tracks[next_idx].id3.artist)
2586 lcd_getstringsize(tracks[next_idx].id3.artist, NULL, NULL);
2587 if (tracks[next_idx].id3.album)
2588 lcd_getstringsize(tracks[next_idx].id3.album, NULL, NULL);
2590 close(fd);
2592 return status;
2595 /* Send callback events to notify about new tracks. */
2596 static void audio_generate_postbuffer_events(void)
2598 int cur_idx;
2599 int last_idx = -1;
2601 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2603 if (audio_have_tracks())
2605 cur_idx = track_ridx;
2607 while (1) {
2608 if (!tracks[cur_idx].event_sent)
2610 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2612 /* Mark the event 'sent' even if we don't really send one */
2613 tracks[last_idx].event_sent = true;
2614 if (track_buffer_callback)
2615 track_buffer_callback(&tracks[last_idx].id3, false);
2617 last_idx = cur_idx;
2619 if (cur_idx == track_widx)
2620 break;
2621 cur_idx++;
2622 cur_idx &= MAX_TRACK_MASK;
2625 if (last_idx >= 0 && !tracks[last_idx].event_sent)
2627 tracks[last_idx].event_sent = true;
2628 if (track_buffer_callback)
2629 track_buffer_callback(&tracks[last_idx].id3, true);
2632 /* Force WPS reload. */
2633 track_changed = true;
2637 static bool audio_initialize_buffer_fill(bool clear_tracks)
2639 /* Don't initialize if we're already initialized */
2640 if (filling)
2641 return true;
2643 /* Don't start buffer fill if buffer is already full. */
2644 if (FILEBUFUSED > conf_watermark && !filling)
2645 return false;
2647 logf("Starting buffer fill");
2649 fill_bytesleft = filebuflen - FILEBUFUSED;
2650 /* TODO: This doesn't look right, and might explain some problems with
2651 * seeking in large files (to offsets larger than filebuflen).
2652 * And what about buffer wraps?
2654 * This really doesn't look right, so don't use it.
2656 // if (buf_ridx > CUR_TI->buf_idx)
2657 // CUR_TI->start_pos = buf_ridx - CUR_TI->buf_idx;
2659 /* Set the filling flag true before calling audio_clear_tracks as that
2660 * function can yield and we start looping. */
2661 filling = true;
2663 if (clear_tracks)
2664 audio_clear_track_entries(true, false, true);
2666 /* Save the current resume position once. */
2667 playlist_update_resume_info(audio_current_track());
2669 return true;
2672 static void audio_fill_file_buffer(
2673 bool start_play, bool rebuffer, size_t offset)
2675 bool had_next_track = audio_next_track() != NULL;
2677 if (!audio_initialize_buffer_fill(!start_play))
2678 return ;
2680 /* If we have a partially buffered track, continue loading,
2681 * otherwise load a new track */
2682 if (tracks[track_widx].filesize > 0)
2683 audio_read_file(false);
2684 else if (!audio_load_track(offset, start_play, rebuffer))
2685 fill_bytesleft = 0;
2687 if (!had_next_track && audio_next_track())
2688 track_changed = true;
2690 /* If we're done buffering */
2691 if (fill_bytesleft == 0)
2693 audio_read_next_metadata();
2695 audio_generate_postbuffer_events();
2696 filling = false;
2698 #ifndef SIMULATOR
2699 if (playing)
2700 ata_sleep();
2701 #endif
2705 static void audio_rebuffer(void)
2707 logf("Forcing rebuffer");
2709 /* Notify the codec that this will take a while */
2710 /* Currently this can cause some problems (logf in reverse order):
2711 * Codec load error:-1
2712 * Codec load disk
2713 * Codec: Unsupported
2714 * Codec finished
2715 * New codec:0/3
2716 * Clearing tracks:7/7, 1
2717 * Forcing rebuffer
2718 * Check new track buffer
2719 * Request new track
2720 * Clearing tracks:5/5, 0
2721 * Starting buffer fill
2722 * Clearing tracks:5/5, 1
2723 * Re-buffering song w/seek
2725 //if (!filling)
2726 // queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0);
2728 /* Stop in progress fill, and clear open file descriptor */
2729 if (current_fd >= 0)
2731 close(current_fd);
2732 current_fd = -1;
2734 filling = false;
2736 /* Reset buffer and track pointers */
2737 CUR_TI->buf_idx = buf_ridx = buf_widx = 0;
2738 track_widx = track_ridx;
2739 audio_clear_track_entries(true, true, false);
2740 CUR_TI->available = 0;
2742 /* Fill the buffer */
2743 last_peek_offset = -1;
2744 CUR_TI->filesize = 0;
2745 CUR_TI->start_pos = 0;
2746 ci.curpos = 0;
2748 if (!CUR_TI->taginfo_ready)
2749 memset(&CUR_TI->id3, 0, sizeof(struct mp3entry));
2751 audio_fill_file_buffer(false, true, 0);
2754 static void audio_check_new_track(void)
2756 int track_count = audio_track_count();
2757 int old_track_ridx = track_ridx;
2758 bool forward;
2760 if (dir_skip)
2762 dir_skip = false;
2763 if (playlist_next_dir(ci.new_track))
2765 ci.new_track = 0;
2766 CUR_TI->taginfo_ready = false;
2767 audio_rebuffer();
2768 goto skip_done;
2770 else
2772 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2773 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2774 return;
2778 if (new_playlist)
2779 ci.new_track = 0;
2781 /* If the playlist isn't that big */
2782 if (!playlist_check(ci.new_track))
2784 if (ci.new_track >= 0)
2786 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2787 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2788 return;
2790 /* Find the beginning backward if the user over-skips it */
2791 while (!playlist_check(++ci.new_track))
2792 if (ci.new_track >= 0)
2794 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2795 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2796 return;
2799 /* Update the playlist */
2800 last_peek_offset -= ci.new_track;
2802 if (playlist_next(ci.new_track) < 0)
2804 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2805 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2806 return;
2809 if (new_playlist)
2811 ci.new_track = 1;
2812 new_playlist = false;
2815 /* Save the old track */
2816 prev_ti = CUR_TI;
2818 /* Move to the new track */
2819 track_ridx += ci.new_track;
2820 track_ridx &= MAX_TRACK_MASK;
2822 if (automatic_skip)
2823 playlist_end = false;
2825 track_changed = !automatic_skip;
2827 /* If it is not safe to even skip this many track entries */
2828 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
2830 ci.new_track = 0;
2831 CUR_TI->taginfo_ready = false;
2832 audio_rebuffer();
2833 goto skip_done;
2836 forward = ci.new_track > 0;
2837 ci.new_track = 0;
2839 /* If the target track is clearly not in memory */
2840 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
2842 audio_rebuffer();
2843 goto skip_done;
2846 /* The track may be in memory, see if it really is */
2847 if (forward)
2849 if (!audio_buffer_wind_forward(track_ridx, old_track_ridx))
2850 audio_rebuffer();
2852 else
2854 int cur_idx = track_ridx;
2855 bool taginfo_ready = true;
2856 bool wrap = track_ridx > old_track_ridx;
2858 while (1)
2860 cur_idx++;
2861 cur_idx &= MAX_TRACK_MASK;
2862 if (!(wrap || cur_idx < old_track_ridx))
2863 break;
2865 /* If we hit a track in between without valid tag info, bail */
2866 if (!tracks[cur_idx].taginfo_ready)
2868 taginfo_ready = false;
2869 break;
2872 tracks[cur_idx].available = tracks[cur_idx].filesize;
2873 if (tracks[cur_idx].codecsize)
2874 tracks[cur_idx].has_codec = true;
2876 if (taginfo_ready)
2878 if (!audio_buffer_wind_backward(track_ridx, old_track_ridx))
2879 audio_rebuffer();
2881 else
2883 CUR_TI->taginfo_ready = false;
2884 audio_rebuffer();
2888 skip_done:
2889 audio_update_trackinfo();
2890 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE");
2891 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0);
2894 static void audio_rebuffer_and_seek(size_t newpos)
2896 int fd;
2897 char *trackname;
2899 trackname = playlist_peek(0);
2900 /* (Re-)open current track's file handle. */
2902 fd = open(trackname, O_RDONLY);
2903 if (fd < 0)
2905 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2906 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_FAILED, 0);
2907 return;
2910 if (current_fd >= 0)
2911 close(current_fd);
2912 current_fd = fd;
2914 playlist_end = false;
2916 ci.curpos = newpos;
2918 /* Clear codec buffer. */
2919 track_widx = track_ridx;
2920 tracks[track_widx].buf_idx = buf_widx = buf_ridx = 0;
2922 last_peek_offset = 0;
2923 filling = false;
2924 audio_initialize_buffer_fill(true);
2925 filling = true;
2927 if (newpos > conf_preseek) {
2928 buf_ridx = RINGBUF_ADD(buf_ridx, conf_preseek);
2929 CUR_TI->start_pos = newpos - conf_preseek;
2931 else
2933 buf_ridx = RINGBUF_ADD(buf_ridx, newpos);
2934 CUR_TI->start_pos = 0;
2937 CUR_TI->filerem = CUR_TI->filesize - CUR_TI->start_pos;
2938 CUR_TI->available = 0;
2940 lseek(current_fd, CUR_TI->start_pos, SEEK_SET);
2942 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE");
2943 queue_post(&codec_callback_queue, Q_CODEC_REQUEST_COMPLETE, 0);
2946 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
2947 bool last_track))
2949 track_buffer_callback = handler;
2952 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
2953 bool last_track))
2955 track_unbuffer_callback = handler;
2958 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
2960 track_changed_callback = handler;
2963 static void audio_stop_codec_flush(void)
2965 ci.stop_codec = true;
2966 pcmbuf_pause(true);
2967 while (audio_codec_loaded)
2968 yield();
2969 /* If the audio codec is not loaded any more, and the audio is still
2970 * playing, it is now and _only_ now safe to call this function from the
2971 * audio thread */
2972 if (pcm_is_playing())
2973 pcmbuf_play_stop();
2974 pcmbuf_pause(paused);
2977 static void audio_stop_playback(void)
2979 /* If we were playing, save resume information */
2980 if (playing)
2982 /* Save the current playing spot, or NULL if the playlist has ended */
2983 playlist_update_resume_info(
2984 (playlist_end && ci.stop_codec)?NULL:audio_current_track());
2987 playing = false;
2988 filling = false;
2989 paused = false;
2990 audio_stop_codec_flush();
2992 if (current_fd >= 0)
2994 close(current_fd);
2995 current_fd = -1;
2998 /* Mark all entries null. */
2999 audio_clear_track_entries(true, false, false);
3000 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3003 static void audio_play_start(size_t offset)
3005 #if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
3006 rec_set_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
3007 #endif
3009 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3010 audio_stop_codec_flush();
3012 track_changed = true;
3013 playlist_end = false;
3015 playing = true;
3016 ci.new_track = 0;
3017 ci.seek_time = 0;
3018 wps_offset = 0;
3020 if (current_fd >= 0)
3022 close(current_fd);
3023 current_fd = -1;
3026 sound_set_volume(global_settings.volume);
3027 track_widx = track_ridx = 0;
3028 buf_ridx = buf_widx = 0;
3030 /* Mark all entries null. */
3031 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
3033 last_peek_offset = -1;
3035 audio_fill_file_buffer(true, false, offset);
3039 /* Invalidates all but currently playing track. */
3040 void audio_invalidate_tracks(void)
3042 if (audio_have_tracks()) {
3043 last_peek_offset = 0;
3045 playlist_end = false;
3046 track_widx = track_ridx;
3047 audio_clear_track_entries(true, true, true);
3049 /* If the current track is fully buffered, advance the write pointer */
3050 if (tracks[track_widx].filerem == 0)
3051 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
3053 /* Mark all other entries null (also buffered wrong metadata). */
3054 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3056 audio_read_next_metadata();
3060 static void audio_new_playlist(void)
3062 /* Prepare to start a new fill from the beginning of the playlist */
3063 last_peek_offset = -1;
3064 if (audio_have_tracks()) {
3065 playlist_end = false;
3066 track_widx = track_ridx;
3067 audio_clear_track_entries(true, true, true);
3069 track_widx++;
3070 track_widx &= MAX_TRACK_MASK;
3072 /* Stop reading the current track */
3073 CUR_TI->filerem = 0;
3074 close(current_fd);
3075 current_fd = -1;
3077 /* Mark the current track as invalid to prevent skipping back to it */
3078 CUR_TI->taginfo_ready = false;
3080 /* Invalidate the buffer other than the playing track */
3081 buf_widx = RINGBUF_ADD(buf_ridx, CUR_TI->available);
3084 /* Signal the codec to initiate a track change forward */
3085 new_playlist = true;
3086 ci.new_track = 1;
3087 audio_fill_file_buffer(false, true, 0);
3090 static void audio_initiate_track_change(long direction)
3092 playlist_end = false;
3093 ci.new_track += direction;
3094 wps_offset -= direction;
3097 static void audio_initiate_dir_change(long direction)
3099 playlist_end = false;
3100 dir_skip = true;
3101 ci.new_track = direction;
3104 static void audio_reset_buffer(void)
3106 size_t offset;
3108 /* Set up file buffer as all space available */
3109 filebuf = (char *)&audiobuf[talk_get_bufsize()+MALLOC_BUFSIZE];
3110 filebuflen = audiobufend - (unsigned char *) filebuf - GUARD_BUFSIZE -
3111 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_MIX_CHUNK * 2);
3113 /* Allow for codec(s) at end of file buffer */
3114 if (talk_voice_required())
3116 /* Allow 2 codecs at end of file buffer */
3117 filebuflen -= 2 * (CODEC_IRAM_SIZE + CODEC_SIZE);
3119 iram_buf[0] = &filebuf[filebuflen];
3120 iram_buf[1] = &filebuf[filebuflen+CODEC_IRAM_SIZE];
3121 dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2];
3122 dram_buf[1] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE*2+CODEC_SIZE];
3124 else
3126 /* Allow for 1 codec at end of file buffer */
3127 filebuflen -= CODEC_IRAM_SIZE + CODEC_SIZE;
3129 iram_buf[0] = &filebuf[filebuflen];
3130 iram_buf[1] = NULL;
3131 dram_buf[0] = (unsigned char *)&filebuf[filebuflen+CODEC_IRAM_SIZE];
3132 dram_buf[1] = NULL;
3135 /* Ensure that file buffer is aligned */
3136 offset = (-(size_t)filebuf) & 3;
3137 filebuf += offset;
3138 filebuflen -= offset;
3139 filebuflen &= ~3;
3143 #ifdef ROCKBOX_HAS_LOGF
3144 static void audio_test_track_changed_event(struct mp3entry *id3)
3146 (void)id3;
3148 logf("tce:%s", id3->path);
3150 #endif
3152 static void audio_playback_init(void)
3154 #ifdef PLAYBACK_VOICE
3155 static bool voicetagtrue = true;
3156 static struct mp3entry id3_voice;
3157 #endif
3158 struct event ev;
3160 logf("playback api init");
3161 pcm_init();
3163 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
3164 /* Set the input multiplexer to Line In */
3165 pcm_rec_mux(0);
3166 #endif
3168 #ifdef ROCKBOX_HAS_LOGF
3169 audio_set_track_changed_event(audio_test_track_changed_event);
3170 #endif
3172 /* Initialize codec api. */
3173 ci.read_filebuf = codec_filebuf_callback;
3174 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3175 ci.pcmbuf_insert_split = codec_pcmbuf_insert_split_callback;
3176 ci.get_codec_memory = codec_get_memory_callback;
3177 ci.request_buffer = codec_request_buffer_callback;
3178 ci.advance_buffer = codec_advance_buffer_callback;
3179 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3180 ci.request_next_track = codec_request_next_track_callback;
3181 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3182 ci.seek_buffer = codec_seek_buffer_callback;
3183 ci.seek_complete = codec_seek_complete_callback;
3184 ci.set_elapsed = codec_set_elapsed_callback;
3185 ci.set_offset = codec_set_offset_callback;
3186 ci.configure = codec_configure_callback;
3187 ci.discard_codec = codec_discard_codec_callback;
3189 /* Initialize voice codec api. */
3190 #ifdef PLAYBACK_VOICE
3191 memcpy(&ci_voice, &ci, sizeof(struct codec_api));
3192 memset(&id3_voice, 0, sizeof(struct mp3entry));
3193 ci_voice.read_filebuf = voice_filebuf_callback;
3194 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3195 ci_voice.pcmbuf_insert_split = voice_pcmbuf_insert_split_callback;
3196 ci_voice.get_codec_memory = voice_get_memory_callback;
3197 ci_voice.request_buffer = voice_request_buffer_callback;
3198 ci_voice.advance_buffer = voice_advance_buffer_callback;
3199 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3200 ci_voice.request_next_track = voice_request_next_track_callback;
3201 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3202 ci_voice.seek_buffer = voice_seek_buffer_callback;
3203 ci_voice.seek_complete = voice_do_nothing;
3204 ci_voice.set_elapsed = voice_set_elapsed_callback;
3205 ci_voice.set_offset = voice_set_offset_callback;
3206 ci_voice.discard_codec = voice_do_nothing;
3207 ci_voice.taginfo_ready = &voicetagtrue;
3208 ci_voice.id3 = &id3_voice;
3209 id3_voice.frequency = 11200;
3210 id3_voice.length = 1000000L;
3211 #endif
3213 codec_thread_p = create_thread(codec_thread, codec_stack,
3214 sizeof(codec_stack),
3215 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK));
3217 while (1)
3219 queue_wait(&audio_queue, &ev);
3220 if (ev.id == Q_AUDIO_POSTINIT)
3221 break ;
3223 #ifndef SIMULATOR
3224 if (ev.id == SYS_USB_CONNECTED)
3226 logf("USB: Audio preinit");
3227 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3228 usb_wait_for_disconnect(&audio_queue);
3230 #endif
3233 filebuf = (char *)&audiobuf[MALLOC_BUFSIZE]; /* Will be reset by reset_buffer */
3235 audio_set_crossfade(global_settings.crossfade);
3237 audio_is_initialized = true;
3239 sound_settings_apply();
3242 static void audio_thread(void)
3244 struct event ev;
3246 /* At first initialize audio system in background. */
3247 audio_playback_init();
3249 while (1)
3251 if (filling)
3253 queue_wait_w_tmo(&audio_queue, &ev, 0);
3254 if (ev.id == SYS_TIMEOUT)
3255 ev.id = Q_AUDIO_FILL_BUFFER;
3257 else
3258 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3260 switch (ev.id) {
3261 case Q_AUDIO_FILL_BUFFER:
3262 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3263 if (!filling)
3264 if (!playing || playlist_end || ci.stop_codec)
3265 break;
3266 audio_fill_file_buffer(false, false, 0);
3267 break;
3269 case Q_AUDIO_PLAY:
3270 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3271 audio_clear_track_entries(true, false, true);
3272 audio_play_start((size_t)ev.data);
3273 break ;
3275 case Q_AUDIO_STOP:
3276 LOGFQUEUE("audio < Q_AUDIO_STOP");
3277 audio_stop_playback();
3278 break ;
3280 case Q_AUDIO_PAUSE:
3281 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3282 pcmbuf_pause((bool)ev.data);
3283 paused = (bool)ev.data;
3284 break ;
3286 case Q_AUDIO_SKIP:
3287 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3288 audio_initiate_track_change((long)ev.data);
3289 break;
3291 case Q_AUDIO_PRE_FF_REWIND:
3292 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3293 if (!playing)
3294 break;
3295 pcmbuf_pause(true);
3296 break;
3298 case Q_AUDIO_FF_REWIND:
3299 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3300 if (!playing)
3301 break ;
3302 ci.seek_time = (long)ev.data+1;
3303 break ;
3305 case Q_AUDIO_REBUFFER_SEEK:
3306 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3307 audio_rebuffer_and_seek((size_t)ev.data);
3308 break;
3310 case Q_AUDIO_CHECK_NEW_TRACK:
3311 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3312 audio_check_new_track();
3313 break;
3315 case Q_AUDIO_DIR_SKIP:
3316 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3317 playlist_end = false;
3318 audio_initiate_dir_change((long)ev.data);
3319 break;
3321 case Q_AUDIO_NEW_PLAYLIST:
3322 LOGFQUEUE("audio < Q_AUDIO_NEW_PLAYLIST");
3323 audio_new_playlist();
3324 break;
3326 case Q_AUDIO_FLUSH:
3327 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3328 audio_invalidate_tracks();
3329 break ;
3331 case Q_AUDIO_TRACK_CHANGED:
3332 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3333 if (track_changed_callback)
3334 track_changed_callback(&CUR_TI->id3);
3335 track_changed = true;
3336 playlist_update_resume_info(audio_current_track());
3337 break ;
3339 #ifndef SIMULATOR
3340 case SYS_USB_CONNECTED:
3341 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3342 audio_stop_playback();
3343 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3344 usb_wait_for_disconnect(&audio_queue);
3345 break ;
3346 #endif
3348 case SYS_TIMEOUT:
3349 LOGFQUEUE("audio < SYS_TIMEOUT");
3350 break;
3352 default:
3353 LOGFQUEUE("audio < default");