touchpad interface for the colour selection screens.
[kugel-rb.git] / apps / playback.c
blobd575be9db5740c6aeb3a3b128ded7130fe2d3526
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <ctype.h>
34 #include "system.h"
35 #include "thread.h"
36 #include "file.h"
37 #include "panic.h"
38 #include "memory.h"
39 #include "lcd.h"
40 #include "font.h"
41 #include "button.h"
42 #include "kernel.h"
43 #include "tree.h"
44 #include "debug.h"
45 #include "sprintf.h"
46 #include "settings.h"
47 #include "codecs.h"
48 #include "audio.h"
49 #include "buffering.h"
50 #include "mp3_playback.h"
51 #include "usb.h"
52 #include "status.h"
53 #include "ata.h"
54 #include "screens.h"
55 #include "playlist.h"
56 #include "playback.h"
57 #include "pcmbuf.h"
58 #include "buffer.h"
59 #include "dsp.h"
60 #include "abrepeat.h"
61 #include "cuesheet.h"
62 #ifdef HAVE_TAGCACHE
63 #include "tagcache.h"
64 #endif
65 #ifdef HAVE_LCD_BITMAP
66 #include "icons.h"
67 #include "peakmeter.h"
68 #include "action.h"
69 #endif
70 #include "lang.h"
71 #include "bookmark.h"
72 #include "misc.h"
73 #include "sound.h"
74 #include "metadata.h"
75 #include "splash.h"
76 #include "talk.h"
77 #include "ata_idle_notify.h"
79 #ifdef HAVE_RECORDING
80 #include "recording.h"
81 #include "talk.h"
82 #endif
84 #ifdef HAVE_WM8758
85 #include "menus/eq_menu.h"
86 #endif
88 #define PLAYBACK_VOICE
91 /* default point to start buffer refill */
92 #define AUDIO_DEFAULT_WATERMARK (1024*512)
93 /* amount of data to read in one read() call */
94 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
95 /* amount of guess-space to allow for codecs that must hunt and peck
96 * for their correct seeek target, 32k seems a good size */
97 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
99 /* Define LOGF_ENABLE to enable logf output in this file */
100 /*#define LOGF_ENABLE*/
101 #include "logf.h"
103 /* macros to enable logf for queues
104 logging on SYS_TIMEOUT can be disabled */
105 #ifdef SIMULATOR
106 /* Define this for logf output of all queuing except SYS_TIMEOUT */
107 #define PLAYBACK_LOGQUEUES
108 /* Define this to logf SYS_TIMEOUT messages */
109 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
110 #endif
112 #ifdef PLAYBACK_LOGQUEUES
113 #define LOGFQUEUE logf
114 #else
115 #define LOGFQUEUE(...)
116 #endif
118 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
119 #define LOGFQUEUE_SYS_TIMEOUT logf
120 #else
121 #define LOGFQUEUE_SYS_TIMEOUT(...)
122 #endif
125 /* Define one constant that includes recording related functionality */
126 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
127 #define AUDIO_HAVE_RECORDING
128 #endif
130 enum {
131 Q_AUDIO_PLAY = 1,
132 Q_AUDIO_STOP,
133 Q_AUDIO_PAUSE,
134 Q_AUDIO_SKIP,
135 Q_AUDIO_PRE_FF_REWIND,
136 Q_AUDIO_FF_REWIND,
137 Q_AUDIO_CHECK_NEW_TRACK,
138 Q_AUDIO_FLUSH,
139 Q_AUDIO_TRACK_CHANGED,
140 Q_AUDIO_DIR_SKIP,
141 Q_AUDIO_POSTINIT,
142 Q_AUDIO_FILL_BUFFER,
143 Q_CODEC_REQUEST_COMPLETE,
144 Q_CODEC_REQUEST_FAILED,
146 Q_VOICE_PLAY,
147 Q_VOICE_STOP,
149 Q_CODEC_LOAD,
150 Q_CODEC_LOAD_DISK,
152 #ifdef AUDIO_HAVE_RECORDING
153 Q_ENCODER_LOAD_DISK,
154 Q_ENCODER_RECORD,
155 #endif
158 /* As defined in plugins/lib/xxx2wav.h */
159 #if MEM > 1
160 #define MALLOC_BUFSIZE (512*1024)
161 #define GUARD_BUFSIZE (32*1024)
162 #else
163 #define MALLOC_BUFSIZE (100*1024)
164 #define GUARD_BUFSIZE (8*1024)
165 #endif
167 /* As defined in plugin.lds */
168 #if defined(CPU_PP)
169 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
170 #define CODEC_IRAM_SIZE ((size_t)0xc000)
171 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
172 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
173 #define CODEC_IRAM_SIZE ((size_t)0x10000)
174 #else
175 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
176 #define CODEC_IRAM_SIZE ((size_t)0xc000)
177 #endif
179 #ifndef IBSS_ATTR_VOICE_STACK
180 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
181 #endif
183 bool audio_is_initialized = false;
185 /* Variables are commented with the threads that use them: *
186 * A=audio, C=codec, V=voice. A suffix of - indicates that *
187 * the variable is read but not updated on that thread. */
188 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
190 /* Main state control */
191 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR = false; /* Codec loaded? (C/A-) */
192 static volatile bool playing NOCACHEBSS_ATTR = false; /* Is audio playing? (A) */
193 static volatile bool paused NOCACHEBSS_ATTR = false; /* Is audio paused? (A/C-) */
195 /* Ring buffer where compressed audio and codecs are loaded */
196 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
197 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
198 /* FIXME: make filebuflen static */
199 size_t filebuflen = 0; /* Size of buffer (A/C-) */
200 /* FIXME: make buf_ridx (C/A-) */
202 /* Possible arrangements of the buffer */
203 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
204 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
205 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
206 static int buffer_state = BUFFER_STATE_TRASHED; /* Buffer state */
208 static struct mp3entry prevtrack_id3;
209 static struct mp3entry curtrack_id3;
210 static struct mp3entry nexttrack_id3;
212 /* Track info structure about songs in the file buffer (A/C-) */
213 struct track_info {
214 int audio_hid; /* The ID for the track's buffer handle */
215 int id3_hid; /* The ID for the track's metadata handle */
216 int codec_hid; /* The ID for the track's codec handle */
218 size_t filesize; /* File total length */
220 bool taginfo_ready; /* Is metadata read */
222 bool event_sent; /* Was this track's buffered event sent */
225 static struct track_info tracks[MAX_TRACK];
226 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
227 static int track_widx = 0; /* Track being buffered (A) */
229 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
231 /* Set by the audio thread when the current track information has updated
232 * and the WPS may need to update its cached information */
233 static bool track_changed = false;
235 /* Information used only for filling the buffer */
236 /* Playlist steps from playing track to next track to be buffered (A) */
237 static int last_peek_offset = 0;
239 /* Scrobbler support */
240 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
242 /* Track change controls */
243 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
244 static bool playlist_end = false; /* Has the current playlist ended? (A) */
245 static bool dir_skip = false; /* Is a directory skip pending? (A) */
246 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
247 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
248 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
250 /* Callbacks which applications or plugins may set */
251 /* When the playing track has changed from the user's perspective */
252 void (*track_changed_callback)(struct mp3entry *id3) = NULL;
253 /* When a track has been buffered */
254 void (*track_buffer_callback)(struct mp3entry *id3) = NULL;
255 /* When a track's buffer has been overwritten or cleared */
256 void (*track_unbuffer_callback)(struct mp3entry *id3) = NULL;
258 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
260 /* Multiple threads */
261 static void set_current_codec(int codec_idx);
262 /* Set the watermark to trigger buffer fill (A/C) FIXME */
263 static void set_filebuf_watermark(int seconds, size_t max);
265 /* Audio thread */
266 static struct event_queue audio_queue NOCACHEBSS_ATTR;
267 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR;
268 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
269 static const char audio_thread_name[] = "audio";
271 static void audio_thread(void);
272 static void audio_initiate_track_change(long direction);
273 static bool audio_have_tracks(void);
274 static void audio_reset_buffer(void);
276 /* Codec thread */
277 extern struct codec_api ci;
278 static struct event_queue codec_queue NOCACHEBSS_ATTR;
279 static struct queue_sender_list codec_queue_sender_list;
280 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
281 IBSS_ATTR;
282 static const char codec_thread_name[] = "codec";
283 struct thread_entry *codec_thread_p; /* For modifying thread priority later. */
285 static volatile int current_codec IDATA_ATTR; /* Current codec (normal/voice) */
287 /* Voice thread */
288 #ifdef PLAYBACK_VOICE
290 extern struct codec_api ci_voice;
292 static struct thread_entry *voice_thread_p = NULL;
293 static struct event_queue voice_queue NOCACHEBSS_ATTR;
294 static long voice_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
295 IBSS_ATTR_VOICE_STACK;
296 static const char voice_thread_name[] = "voice codec";
298 /* Voice codec swapping control */
299 extern unsigned char codecbuf[]; /* DRAM codec swap buffer */
301 #ifdef SIMULATOR
302 /* IRAM codec swap buffer for sim*/
303 static unsigned char sim_iram[CODEC_IRAM_SIZE];
304 #undef CODEC_IRAM_ORIGIN
305 #define CODEC_IRAM_ORIGIN sim_iram
306 #endif
308 /* iram_buf and dram_buf are either both NULL or both non-NULL */
309 /* Pointer to IRAM buffer for codec swapping */
310 static unsigned char *iram_buf = NULL;
311 /* Pointer to DRAM buffer for codec swapping */
312 static unsigned char *dram_buf = NULL;
313 /* Parity of swap_codec calls - needed because one codec swapping itself in
314 automatically swaps in the other and the swap when unlocking should not
315 happen if the parity is even.
317 static bool swap_codec_parity NOCACHEBSS_ATTR = false; /* true=odd, false=even */
318 /* Locking to control which codec (normal/voice) is running */
319 static struct semaphore sem_codecthread NOCACHEBSS_ATTR;
320 static struct event event_codecthread NOCACHEBSS_ATTR;
322 /* Voice state */
323 static volatile bool voice_thread_start = false; /* Triggers voice playback (A/V) */
324 static volatile bool voice_is_playing NOCACHEBSS_ATTR = false; /* Is voice currently playing? (V) */
325 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR = false; /* Is voice codec loaded (V/A-) */
326 static unsigned char *voicebuf = NULL;
327 static size_t voice_remaining = 0;
329 #ifdef IRAM_STEAL
330 /* Voice IRAM has been stolen for other use */
331 static bool voice_iram_stolen = false;
332 #endif
334 static void (*voice_getmore)(unsigned char** start, size_t* size) = NULL;
336 struct voice_info {
337 void (*callback)(unsigned char **start, size_t* size);
338 size_t size;
339 unsigned char *buf;
341 static void voice_thread(void);
342 static void voice_stop(void);
344 #endif /* PLAYBACK_VOICE */
347 /* --- Helper functions --- */
349 static struct mp3entry *bufgetid3(int handle_id)
351 if (handle_id < 0)
352 return NULL;
354 struct mp3entry *id3;
355 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
357 if (ret < 0 || ret != sizeof(struct mp3entry))
358 return NULL;
360 return id3;
363 static bool clear_track_info(struct track_info *track)
365 if (!track)
366 return false;
368 if (track->codec_hid > 0) {
369 if (bufclose(track->codec_hid))
370 track->codec_hid = 0;
371 else
372 return false;
375 if (track->id3_hid > 0) {
376 if (bufclose(track->id3_hid))
377 track->id3_hid = 0;
378 else
379 return false;
382 if (track->audio_hid > 0) {
383 if (bufclose(track->audio_hid))
384 track->audio_hid = 0;
385 else
386 return false;
389 memset(track, 0, sizeof(struct track_info));
390 return true;
393 /* --- External interfaces --- */
395 void mp3_play_data(const unsigned char* start, int size,
396 void (*get_more)(unsigned char** start, size_t* size))
398 #ifdef PLAYBACK_VOICE
399 static struct voice_info voice_clip;
400 voice_clip.callback = get_more;
401 voice_clip.buf = (unsigned char*)start;
402 voice_clip.size = size;
403 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
404 queue_post(&voice_queue, Q_VOICE_STOP, 0);
405 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
406 queue_post(&voice_queue, Q_VOICE_PLAY, (intptr_t)&voice_clip);
407 voice_thread_start = true;
408 trigger_cpu_boost();
409 #else
410 (void) start;
411 (void) size;
412 (void) get_more;
413 #endif
416 void mp3_play_stop(void)
418 #ifdef PLAYBACK_VOICE
419 queue_remove_from_head(&voice_queue, Q_VOICE_STOP);
420 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
421 queue_post(&voice_queue, Q_VOICE_STOP, 1);
422 #endif
425 void mp3_play_pause(bool play)
427 /* a dummy */
428 (void)play;
431 bool mp3_is_playing(void)
433 #ifdef PLAYBACK_VOICE
434 return voice_is_playing;
435 #else
436 return false;
437 #endif
440 /* If voice could be swapped out - wait for it to return
441 * Used by buffer claming functions.
443 static void wait_for_voice_swap_in(void)
445 #ifdef PLAYBACK_VOICE
446 if (NULL == iram_buf)
447 return;
449 event_wait(&event_codecthread, STATE_NONSIGNALED);
450 #endif /* PLAYBACK_VOICE */
453 /* This sends a stop message and the audio thread will dump all it's
454 subsequenct messages */
455 static void audio_hard_stop(void)
457 /* Stop playback */
458 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
459 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
462 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
464 unsigned char *buf, *end;
466 if (audio_is_initialized)
468 audio_hard_stop();
469 wait_for_voice_swap_in();
470 #ifdef PLAYBACK_VOICE
471 voice_stop();
472 #endif
474 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
476 if (buffer_size == NULL)
478 /* Special case for talk_init to use since it already knows it's
479 trashed */
480 buffer_state = BUFFER_STATE_TRASHED;
481 return NULL;
484 if (talk_buf || buffer_state == BUFFER_STATE_TRASHED
485 || !talk_voice_required())
487 logf("get buffer: talk, audio");
488 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
489 the talk buffer is not needed because voice isn't being used, or
490 could be BUFFER_STATE_TRASHED already. If state is
491 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
492 without the caller knowing what's going on. Changing certain settings
493 may move it to a worse condition but the memory in use by something
494 else will remain undisturbed.
496 if (buffer_state != BUFFER_STATE_TRASHED)
498 talk_buffer_steal();
499 buffer_state = BUFFER_STATE_TRASHED;
502 buf = audiobuf;
503 end = audiobufend;
505 else
507 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
508 still BUFFER_STATE_INITIALIZED */
509 /* Skip talk buffer and move pcm buffer to end to maximize available
510 contiguous memory - no audio running means voice will not need the
511 swap space */
512 logf("get buffer: audio");
513 buf = audiobuf + talk_get_bufsize();
514 end = audiobufend - pcmbuf_init(audiobufend);
515 buffer_state = BUFFER_STATE_VOICED_ONLY;
518 *buffer_size = end - buf;
520 return buf;
523 #ifdef IRAM_STEAL
524 void audio_iram_steal(void)
526 /* We need to stop audio playback in order to use codec IRAM */
527 audio_hard_stop();
529 #ifdef PLAYBACK_VOICE
530 if (NULL != iram_buf)
532 /* Can't already be stolen */
533 if (voice_iram_stolen)
534 return;
536 /* Must wait for voice to be current again if it is swapped which
537 would cause the caller's buffer to get clobbered when voice locks
538 and runs - we'll wait for it to lock and yield again then make sure
539 the ride has come to a complete stop */
540 wait_for_voice_swap_in();
541 voice_stop();
543 /* Save voice IRAM but just memcpy - safe to do here since voice
544 is current and no audio codec is loaded */
545 memcpy(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
546 voice_iram_stolen = true;
548 else
550 /* Nothing much to do if no voice */
551 voice_iram_stolen = false;
553 #endif
555 #endif /* IRAM_STEAL */
557 #ifdef HAVE_RECORDING
558 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
560 /* Don't allow overwrite of voice swap area or we'll trash the
561 swapped-out voice codec but can use whole thing if none */
562 unsigned char *end;
564 /* Stop audio and voice. Wait for voice to swap in and be clear
565 of pending events to ensure trouble-free operation of encoders */
566 audio_hard_stop();
567 wait_for_voice_swap_in();
568 #ifdef PLAYBACK_VOICE
569 voice_stop();
570 #endif
571 talk_buffer_steal();
573 #ifdef PLAYBACK_VOICE
574 /* If no dram_buf, swap space not used and recording gets more
575 memory. Codec swap areas will remain unaffected by the next init
576 since they're allocated at the end of the buffer and their sizes
577 don't change between calls */
578 end = dram_buf;
579 if (NULL == end)
580 #endif /* PLAYBACK_VOICE */
581 end = audiobufend;
583 buffer_state = BUFFER_STATE_TRASHED;
585 *buffer_size = end - audiobuf;
587 return (unsigned char *)audiobuf;
590 bool audio_load_encoder(int afmt)
592 #ifndef SIMULATOR
593 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
594 if (!enc_fn)
595 return false;
597 audio_remove_encoder();
598 ci.enc_codec_loaded = 0; /* clear any previous error condition */
600 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
601 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
603 while (ci.enc_codec_loaded == 0)
604 yield();
606 logf("codec loaded: %d", ci.enc_codec_loaded);
608 return ci.enc_codec_loaded > 0;
609 #else
610 (void)afmt;
611 return true;
612 #endif
613 } /* audio_load_encoder */
615 void audio_remove_encoder(void)
617 #ifndef SIMULATOR
618 /* force encoder codec unload (if currently loaded) */
619 if (ci.enc_codec_loaded <= 0)
620 return;
622 ci.stop_encoder = true;
623 while (ci.enc_codec_loaded > 0)
624 yield();
625 #endif
626 } /* audio_remove_encoder */
628 #endif /* HAVE_RECORDING */
630 struct mp3entry* audio_current_track(void)
632 const char *filename;
633 const char *p;
634 static struct mp3entry temp_id3;
635 int cur_idx;
636 int offset = ci.new_track + wps_offset;
638 cur_idx = track_ridx + offset;
639 cur_idx &= MAX_TRACK_MASK;
641 if (cur_idx == track_ridx && *curtrack_id3.path)
642 return &curtrack_id3;
643 else if (offset == -1 && *prevtrack_id3.path)
644 return &prevtrack_id3;
645 else if (tracks[cur_idx].id3_hid > 0)
646 return bufgetid3(tracks[cur_idx].id3_hid);
648 memset(&temp_id3, 0, sizeof(struct mp3entry));
650 filename = playlist_peek(0);
651 if (!filename)
652 filename = "No file!";
654 #ifdef HAVE_TC_RAMCACHE
655 if (tagcache_fill_tags(&temp_id3, filename))
656 return &temp_id3;
657 #endif
659 p = strrchr(filename, '/');
660 if (!p)
661 p = filename;
662 else
663 p++;
665 strncpy(temp_id3.path, p, sizeof(temp_id3.path)-1);
666 temp_id3.title = &temp_id3.path[0];
668 return &temp_id3;
671 struct mp3entry* audio_next_track(void)
673 int next_idx = track_ridx;
675 if (!audio_have_tracks())
676 return NULL;
678 if (wps_offset == -1 && *prevtrack_id3.path)
679 return &curtrack_id3;
681 next_idx++;
682 next_idx &= MAX_TRACK_MASK;
684 if (tracks[next_idx].id3_hid <= 0)
685 return NULL;
687 return &nexttrack_id3;
690 bool audio_has_changed_track(void)
692 if (track_changed)
694 track_changed = false;
695 return true;
698 return false;
701 void audio_play(long offset)
703 logf("audio_play");
705 #ifdef PLAYBACK_VOICE
706 /* Truncate any existing voice output so we don't have spelling
707 * etc. over the first part of the played track */
708 talk_force_shutup();
709 #endif
711 /* Start playback */
712 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
713 /* Don't return until playback has actually started */
714 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
717 void audio_stop(void)
719 /* Stop playback */
720 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
721 /* Don't return until playback has actually stopped */
722 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
725 void audio_pause(void)
727 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
728 /* Don't return until playback has actually paused */
729 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
732 void audio_resume(void)
734 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
735 /* Don't return until playback has actually resumed */
736 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
739 void audio_next(void)
741 if (playlist_check(ci.new_track + wps_offset + 1))
743 if (global_settings.beep)
744 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
746 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
747 queue_post(&audio_queue, Q_AUDIO_SKIP, 1);
748 /* Update wps while our message travels inside deep playback queues. */
749 wps_offset++;
750 track_changed = true;
752 else
754 /* No more tracks. */
755 if (global_settings.beep)
756 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
760 void audio_prev(void)
762 if (playlist_check(ci.new_track + wps_offset - 1))
764 if (global_settings.beep)
765 pcmbuf_beep(5000, 100, 2500*global_settings.beep);
767 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
768 queue_post(&audio_queue, Q_AUDIO_SKIP, -1);
769 /* Update wps while our message travels inside deep playback queues. */
770 wps_offset--;
771 track_changed = true;
773 else
775 /* No more tracks. */
776 if (global_settings.beep)
777 pcmbuf_beep(1000, 100, 1000*global_settings.beep);
781 void audio_next_dir(void)
783 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
784 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
787 void audio_prev_dir(void)
789 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
790 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
793 void audio_pre_ff_rewind(void)
795 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
796 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
799 void audio_ff_rewind(long newpos)
801 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
802 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
805 void audio_flush_and_reload_tracks(void)
807 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
808 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
811 void audio_error_clear(void)
813 #ifdef AUDIO_HAVE_RECORDING
814 pcm_rec_error_clear();
815 #endif
818 int audio_status(void)
820 int ret = 0;
822 if (playing)
823 ret |= AUDIO_STATUS_PLAY;
825 if (paused)
826 ret |= AUDIO_STATUS_PAUSE;
828 #ifdef HAVE_RECORDING
829 /* Do this here for constitency with mpeg.c version */
830 ret |= pcm_rec_status();
831 #endif
833 return ret;
836 int audio_get_file_pos(void)
838 return 0;
841 #ifndef HAVE_FLASH_STORAGE
842 void audio_set_buffer_margin(int setting)
844 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
845 buffer_margin = lookup[setting];
846 logf("buffer margin: %ld", buffer_margin);
847 set_filebuf_watermark(buffer_margin, 0);
849 #endif
851 /* Take nescessary steps to enable or disable the crossfade setting */
852 void audio_set_crossfade(int enable)
854 size_t offset;
855 bool was_playing;
856 size_t size;
858 /* Tell it the next setting to use */
859 pcmbuf_crossfade_enable(enable);
861 /* Return if size hasn't changed or this is too early to determine
862 which in the second case there's no way we could be playing
863 anything at all */
864 if (pcmbuf_is_same_size())
866 /* This function is a copout and just syncs some variables -
867 to be removed at a later date */
868 pcmbuf_crossfade_enable_finished();
869 return;
872 offset = 0;
873 was_playing = playing;
875 /* Playback has to be stopped before changing the buffer size */
876 if (was_playing)
878 /* Store the track resume position */
879 offset = curtrack_id3.offset;
880 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK));
883 /* Blast it - audio buffer will have to be setup again next time
884 something plays */
885 audio_get_buffer(true, &size);
887 /* Restart playback if audio was running previously */
888 if (was_playing)
889 audio_play(offset);
892 /* --- Routines called from multiple threads --- */
893 static void set_current_codec(int codec_idx)
895 current_codec = codec_idx;
896 dsp_configure(DSP_SWITCH_CODEC, codec_idx);
899 #ifdef PLAYBACK_VOICE
900 static void swap_codec(void)
902 int my_codec;
904 /* Swap nothing if no swap buffers exist */
905 if (dram_buf == NULL)
907 logf("swap: no swap buffers");
908 return;
911 my_codec = current_codec;
913 logf("swapping out codec: %d", my_codec);
915 /* Invert this when a codec thread enters and leaves */
916 swap_codec_parity = !swap_codec_parity;
918 /* If this is true, an odd number of calls has occurred and there's
919 no codec thread waiting to swap us out when it locks and runs. This
920 occurs when playback is stopped or when just starting playback and
921 the audio thread is loading a codec; parities should always be even
922 on entry when a thread calls this during playback */
923 if (swap_codec_parity)
925 /* Save our current IRAM and DRAM */
926 #ifdef IRAM_STEAL
927 if (voice_iram_stolen)
929 logf("swap: iram restore");
930 voice_iram_stolen = false;
931 /* Don't swap trashed data into buffer as the voice IRAM will
932 already be swapped out - should _always_ be the case if
933 voice_iram_stolen is true since the voice has been swapped
934 in beforehand */
935 if (my_codec == CODEC_IDX_VOICE)
937 logf("voice iram already swapped");
938 goto skip_iram_swap;
941 #endif
943 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
945 #ifdef IRAM_STEAL
946 skip_iram_swap:
947 #endif
949 memswap128(dram_buf, codecbuf, CODEC_SIZE);
950 /* No cache invalidation needed; it will be done in codec_load_ram
951 or we won't be here otherwise */
954 /* Release my semaphore */
955 semaphore_release(&sem_codecthread);
956 logf("unlocked: %d", my_codec);
958 /* Wait for other codec */
959 event_wait(&event_codecthread,
960 (my_codec == CODEC_IDX_AUDIO) ? STATE_NONSIGNALED : STATE_SIGNALED);
962 /* Wait for other codec to unlock */
963 logf("waiting for lock: %d", my_codec);
964 semaphore_wait(&sem_codecthread);
966 /* Take control */
967 set_current_codec(my_codec);
968 event_set_state(&event_codecthread,
969 (my_codec == CODEC_IDX_AUDIO) ? STATE_SIGNALED : STATE_NONSIGNALED);
971 /* Reload our IRAM and DRAM */
972 memswap128(iram_buf, CODEC_IRAM_ORIGIN, CODEC_IRAM_SIZE);
973 memswap128(dram_buf, codecbuf, CODEC_SIZE);
974 invalidate_icache();
976 /* Flip parity again */
977 swap_codec_parity = !swap_codec_parity;
979 logf("resuming codec: %d", my_codec);
982 /* This function is meant to be used by the buffer stealing functions to
983 ensure the codec is no longer active and so voice will be swapped-in
984 before it is called */
985 static void voice_stop(void)
987 /* Must have a voice codec loaded or we'll hang forever here */
988 if (!voice_codec_loaded)
989 return;
991 talk_force_shutup();
993 /* Loop until voice empties it's queue, stops and picks up on the new
994 track; the voice thread must be stopped and waiting for messages
995 outside the codec */
996 while (voice_is_playing || !queue_empty(&voice_queue) ||
997 ci_voice.new_track)
998 yield();
1000 if (!playing)
1001 pcmbuf_play_stop();
1002 } /* voice_stop */
1004 /* Is voice still speaking */
1005 /* Unfortunately only reliable when music is not also playing. */
1006 static bool is_voice_speaking(void)
1008 return is_voice_queued()
1009 || voice_is_playing
1010 || (!playing && pcm_is_playing());
1013 #endif /* PLAYBACK_VOICE */
1015 /* Wait for voice to finish speaking. */
1016 /* Also only reliable when music is not also playing. */
1017 void voice_wait(void)
1019 #ifdef PLAYBACK_VOICE
1020 while (is_voice_speaking())
1021 sleep(HZ/10);
1022 #endif
1025 static void set_filebuf_watermark(int seconds, size_t max)
1027 size_t bytes;
1029 if (!filebuf)
1030 return; /* Audio buffers not yet set up */
1032 bytes = seconds?MAX(curtrack_id3.bitrate * seconds * (1000/8), max):max;
1033 bytes = MIN(bytes, filebuflen / 2);
1034 buf_set_conf(BUFFERING_SET_WATERMARK, bytes);
1037 const char * get_codec_filename(int cod_spec)
1039 const char *fname;
1041 #ifdef HAVE_RECORDING
1042 /* Can choose decoder or encoder if one available */
1043 int type = cod_spec & CODEC_TYPE_MASK;
1044 int afmt = cod_spec & CODEC_AFMT_MASK;
1046 if ((unsigned)afmt >= AFMT_NUM_CODECS)
1047 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
1049 fname = (type == CODEC_TYPE_ENCODER) ?
1050 audio_formats[afmt].codec_enc_root_fn :
1051 audio_formats[afmt].codec_root_fn;
1053 logf("%s: %d - %s",
1054 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
1055 afmt, fname ? fname : "<unknown>");
1056 #else /* !HAVE_RECORDING */
1057 /* Always decoder */
1058 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
1059 cod_spec = AFMT_UNKNOWN;
1060 fname = audio_formats[cod_spec].codec_root_fn;
1061 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
1062 #endif /* HAVE_RECORDING */
1064 return fname;
1065 } /* get_codec_filename */
1068 /* --- Voice thread --- */
1070 #ifdef PLAYBACK_VOICE
1072 static bool voice_pcmbuf_insert_callback(
1073 const void *ch1, const void *ch2, int count)
1075 const char *src[2] = { ch1, ch2 };
1077 while (count > 0)
1079 int out_count = dsp_output_count(count);
1080 int inp_count;
1081 char *dest;
1083 while ((dest = pcmbuf_request_voice_buffer(
1084 &out_count, playing)) == NULL)
1086 if (playing && audio_codec_loaded)
1087 swap_codec();
1088 else
1089 yield();
1092 /* Get the real input_size for output_size bytes, guarding
1093 * against resampling buffer overflows. */
1094 inp_count = dsp_input_count(out_count);
1096 if (inp_count <= 0)
1097 return true;
1099 /* Input size has grown, no error, just don't write more than length */
1100 if (inp_count > count)
1101 inp_count = count;
1103 out_count = dsp_process(dest, src, inp_count);
1105 if (out_count <= 0)
1106 return true;
1108 if (playing)
1110 pcmbuf_mix_voice(out_count);
1111 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1112 audio_codec_loaded)
1113 swap_codec();
1115 else
1116 pcmbuf_write_complete(out_count);
1118 count -= inp_count;
1121 return true;
1122 } /* voice_pcmbuf_insert_callback */
1124 static void* voice_get_memory_callback(size_t *size)
1126 /* Voice should have no use for this. If it did, we'd have to
1127 swap the malloc buffer as well. */
1128 *size = 0;
1129 return NULL;
1132 static void voice_set_elapsed_callback(unsigned int value)
1134 (void)value;
1137 static void voice_set_offset_callback(size_t value)
1139 (void)value;
1142 static void voice_configure_callback(int setting, intptr_t value)
1144 if (!dsp_configure(setting, value))
1146 logf("Illegal key:%d", setting);
1150 static size_t voice_filebuf_callback(void *ptr, size_t size)
1152 (void)ptr;
1153 (void)size;
1155 return 0;
1158 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1159 static bool voice_on_voice_stop(bool aborting, size_t *realsize)
1161 if (aborting && !playing)
1163 /* Aborting: Slight hack - flush PCM buffer if
1164 only being used for voice */
1165 pcmbuf_play_stop();
1168 if (voice_is_playing)
1170 /* Clear the current buffer */
1171 voice_is_playing = false;
1172 voice_getmore = NULL;
1173 voice_remaining = 0;
1174 voicebuf = NULL;
1176 /* Cancel any automatic boost if no more clips requested. */
1177 if (!playing || !voice_thread_start)
1178 sleep(0);
1180 /* Force the codec to think it's changing tracks */
1181 ci_voice.new_track = 1;
1183 *realsize = 0;
1184 return true; /* Yes, change tracks */
1187 return false;
1190 static void* voice_request_buffer_callback(size_t *realsize, size_t reqsize)
1192 struct queue_event ev;
1194 if (ci_voice.new_track)
1196 *realsize = 0;
1197 return NULL;
1200 while (1)
1202 if (voice_is_playing || playing)
1204 queue_wait_w_tmo(&voice_queue, &ev, 0);
1205 if (!voice_is_playing && ev.id == SYS_TIMEOUT)
1206 ev.id = Q_AUDIO_PLAY;
1208 else
1210 queue_wait(&voice_queue, &ev);
1213 switch (ev.id) {
1214 case Q_AUDIO_PLAY:
1215 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1216 if (playing)
1218 if (audio_codec_loaded)
1219 swap_codec();
1220 yield();
1222 break;
1224 #ifdef AUDIO_HAVE_RECORDING
1225 case Q_ENCODER_RECORD:
1226 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1227 swap_codec();
1228 break;
1229 #endif
1231 case Q_VOICE_STOP:
1232 LOGFQUEUE("voice < Q_VOICE_STOP");
1233 if (voice_on_voice_stop(ev.data, realsize))
1234 return NULL;
1235 break;
1237 case Q_VOICE_PLAY:
1238 LOGFQUEUE("voice < Q_VOICE_PLAY");
1239 if (!voice_is_playing)
1241 /* Set up new voice data */
1242 struct voice_info *voice_data;
1243 #ifdef IRAM_STEAL
1244 if (voice_iram_stolen)
1246 /* Voice is the first to run again and is currently
1247 loaded */
1248 logf("voice: iram restore");
1249 memcpy(CODEC_IRAM_ORIGIN, iram_buf, CODEC_IRAM_SIZE);
1250 voice_iram_stolen = false;
1252 #endif
1253 /* Must reset the buffer before any playback begins if
1254 needed */
1255 if (buffer_state == BUFFER_STATE_TRASHED)
1256 audio_reset_buffer();
1258 voice_is_playing = true;
1259 trigger_cpu_boost();
1260 voice_data = (struct voice_info *)ev.data;
1261 voice_remaining = voice_data->size;
1262 voicebuf = voice_data->buf;
1263 voice_getmore = voice_data->callback;
1265 goto voice_play_clip; /* To exit both switch and while */
1267 case SYS_TIMEOUT:
1268 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1269 goto voice_play_clip;
1271 default:
1272 LOGFQUEUE("voice < default");
1276 voice_play_clip:
1278 if (voice_remaining == 0 || voicebuf == NULL)
1280 if (voice_getmore)
1281 voice_getmore((unsigned char **)&voicebuf, &voice_remaining);
1283 /* If this clip is done */
1284 if (voice_remaining == 0)
1286 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1287 queue_post(&voice_queue, Q_VOICE_STOP, 0);
1288 /* Force pcm playback. */
1289 if (!pcm_is_playing())
1290 pcmbuf_play_start();
1294 *realsize = MIN(voice_remaining, reqsize);
1296 if (*realsize == 0)
1297 return NULL;
1299 return voicebuf;
1300 } /* voice_request_buffer_callback */
1302 static void voice_advance_buffer_callback(size_t amount)
1304 amount = MIN(amount, voice_remaining);
1305 voicebuf += amount;
1306 voice_remaining -= amount;
1309 static void voice_advance_buffer_loc_callback(void *ptr)
1311 size_t amount = (size_t)ptr - (size_t)voicebuf;
1313 voice_advance_buffer_callback(amount);
1316 static off_t voice_mp3_get_filepos_callback(int newtime)
1318 (void)newtime;
1320 return 0;
1323 static void voice_do_nothing(void)
1325 return;
1328 static bool voice_seek_buffer_callback(size_t newpos)
1330 (void)newpos;
1332 return false;
1335 static bool voice_request_next_track_callback(void)
1337 ci_voice.new_track = 0;
1338 return true;
1341 static void voice_thread(void)
1343 logf("Loading voice codec");
1344 voice_codec_loaded = true;
1345 semaphore_wait(&sem_codecthread);
1346 event_set_state(&event_codecthread, STATE_NONSIGNALED);
1347 set_current_codec(CODEC_IDX_VOICE);
1348 dsp_configure(DSP_RESET, 0);
1349 voice_remaining = 0;
1350 voice_getmore = NULL;
1352 /* FIXME: If we being starting the voice thread without reboot, the
1353 voice_queue could be full of old stuff and we must flush it. */
1354 codec_load_file(get_codec_filename(AFMT_MPA_L3), &ci_voice);
1356 logf("Voice codec finished");
1357 voice_codec_loaded = false;
1358 voice_thread_p = NULL;
1359 semaphore_release(&sem_codecthread);
1360 } /* voice_thread */
1362 #endif /* PLAYBACK_VOICE */
1364 /* --- Codec thread --- */
1365 static bool codec_pcmbuf_insert_callback(
1366 const void *ch1, const void *ch2, int count)
1368 const char *src[2] = { ch1, ch2 };
1370 while (count > 0)
1372 int out_count = dsp_output_count(count);
1373 int inp_count;
1374 char *dest;
1376 /* Prevent audio from a previous track from playing */
1377 if (ci.new_track || ci.stop_codec)
1378 return true;
1380 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
1382 sleep(1);
1383 if (ci.seek_time || ci.new_track || ci.stop_codec)
1384 return true;
1387 /* Get the real input_size for output_size bytes, guarding
1388 * against resampling buffer overflows. */
1389 inp_count = dsp_input_count(out_count);
1391 if (inp_count <= 0)
1392 return true;
1394 /* Input size has grown, no error, just don't write more than length */
1395 if (inp_count > count)
1396 inp_count = count;
1398 out_count = dsp_process(dest, src, inp_count);
1400 if (out_count <= 0)
1401 return true;
1403 pcmbuf_write_complete(out_count);
1405 #ifdef PLAYBACK_VOICE
1406 if ((voice_is_playing || voice_thread_start)
1407 && pcm_is_playing() && voice_codec_loaded &&
1408 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1410 voice_thread_start = false;
1411 swap_codec();
1413 #endif
1415 count -= inp_count;
1418 return true;
1419 } /* codec_pcmbuf_insert_callback */
1421 static void* codec_get_memory_callback(size_t *size)
1423 *size = MALLOC_BUFSIZE;
1424 return malloc_buf;
1427 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
1428 static void codec_pcmbuf_position_callback(size_t size)
1430 /* This is called from an ISR, so be quick */
1431 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
1432 prevtrack_id3.elapsed;
1434 if (time >= prevtrack_id3.length)
1436 pcmbuf_set_position_callback(NULL);
1437 prevtrack_id3.elapsed = prevtrack_id3.length;
1439 else
1440 prevtrack_id3.elapsed = time;
1443 static void codec_set_elapsed_callback(unsigned int value)
1445 unsigned int latency;
1446 if (ci.seek_time)
1447 return;
1449 #ifdef AB_REPEAT_ENABLE
1450 ab_position_report(value);
1451 #endif
1453 latency = pcmbuf_get_latency();
1454 if (value < latency)
1455 curtrack_id3.elapsed = 0;
1456 else if (value - latency > curtrack_id3.elapsed ||
1457 value - latency < curtrack_id3.elapsed - 2)
1459 curtrack_id3.elapsed = value - latency;
1463 static void codec_set_offset_callback(size_t value)
1465 unsigned int latency;
1467 if (ci.seek_time)
1468 return;
1470 latency = pcmbuf_get_latency() * curtrack_id3.bitrate / 8;
1471 if (value < latency)
1472 curtrack_id3.offset = 0;
1473 else
1474 curtrack_id3.offset = value - latency;
1477 static void codec_advance_buffer_counters(size_t amount)
1479 bufadvance(CUR_TI->audio_hid, amount);
1480 ci.curpos += amount;
1483 /* copy up-to size bytes into ptr and return the actual size copied */
1484 static size_t codec_filebuf_callback(void *ptr, size_t size)
1486 ssize_t copy_n;
1488 if (ci.stop_codec || !playing)
1489 return 0;
1491 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1493 /* Nothing requested OR nothing left */
1494 if (copy_n == 0)
1495 return 0;
1497 /* Update read and other position pointers */
1498 codec_advance_buffer_counters(copy_n);
1500 /* Return the actual amount of data copied to the buffer */
1501 return copy_n;
1502 } /* codec_filebuf_callback */
1504 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1506 size_t copy_n = reqsize;
1507 ssize_t ret;
1508 void *ptr;
1510 if (!playing)
1512 *realsize = 0;
1513 return NULL;
1516 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1517 if (ret >= 0)
1518 copy_n = MIN((size_t)ret, reqsize);
1520 if (copy_n == 0)
1522 *realsize = 0;
1523 return NULL;
1526 *realsize = copy_n;
1528 return ptr;
1529 } /* codec_request_buffer_callback */
1531 static int get_codec_base_type(int type)
1533 switch (type) {
1534 case AFMT_MPA_L1:
1535 case AFMT_MPA_L2:
1536 case AFMT_MPA_L3:
1537 return AFMT_MPA_L3;
1540 return type;
1543 static void codec_advance_buffer_callback(size_t amount)
1545 codec_advance_buffer_counters(amount);
1546 codec_set_offset_callback(ci.curpos);
1549 static void codec_advance_buffer_loc_callback(void *ptr)
1551 size_t amount = buf_get_offset(CUR_TI->audio_hid, ptr);
1552 codec_advance_buffer_callback(amount);
1555 /* Copied from mpeg.c. Should be moved somewhere else. */
1556 static int codec_get_file_pos(void)
1558 int pos = -1;
1559 struct mp3entry *id3 = audio_current_track();
1561 if (id3->vbr)
1563 if (id3->has_toc)
1565 /* Use the TOC to find the new position */
1566 unsigned int percent, remainder;
1567 int curtoc, nexttoc, plen;
1569 percent = (id3->elapsed*100)/id3->length;
1570 if (percent > 99)
1571 percent = 99;
1573 curtoc = id3->toc[percent];
1575 if (percent < 99)
1576 nexttoc = id3->toc[percent+1];
1577 else
1578 nexttoc = 256;
1580 pos = (id3->filesize/256)*curtoc;
1582 /* Use the remainder to get a more accurate position */
1583 remainder = (id3->elapsed*100)%id3->length;
1584 remainder = (remainder*100)/id3->length;
1585 plen = (nexttoc - curtoc)*(id3->filesize/256);
1586 pos += (plen/100)*remainder;
1588 else
1590 /* No TOC exists, estimate the new position */
1591 pos = (id3->filesize / (id3->length / 1000)) *
1592 (id3->elapsed / 1000);
1595 else if (id3->bitrate)
1596 pos = id3->elapsed * (id3->bitrate / 8);
1597 else
1598 return -1;
1600 pos += id3->first_frame_offset;
1602 /* Don't seek right to the end of the file so that we can
1603 transition properly to the next song */
1604 if (pos >= (int)(id3->filesize - id3->id3v1len))
1605 pos = id3->filesize - id3->id3v1len - 1;
1607 return pos;
1610 static off_t codec_mp3_get_filepos_callback(int newtime)
1612 off_t newpos;
1614 curtrack_id3.elapsed = newtime;
1615 newpos = codec_get_file_pos();
1617 return newpos;
1620 static void codec_seek_complete_callback(void)
1622 logf("seek_complete");
1623 if (pcm_is_paused())
1625 /* If this is not a seamless seek, clear the buffer */
1626 pcmbuf_play_stop();
1627 dsp_configure(DSP_FLUSH, 0);
1629 /* If playback was not 'deliberately' paused, unpause now */
1630 if (!paused)
1631 pcmbuf_pause(false);
1633 ci.seek_time = 0;
1636 static bool codec_seek_buffer_callback(size_t newpos)
1638 logf("codec_seek_buffer_callback");
1640 int ret = bufseek(CUR_TI->audio_hid, newpos);
1641 if (ret == 0) {
1642 ci.curpos = newpos;
1643 return true;
1645 else {
1646 return false;
1650 static void codec_configure_callback(int setting, intptr_t value)
1652 switch (setting) {
1653 case CODEC_SET_FILEBUF_WATERMARK:
1654 set_filebuf_watermark(buffer_margin, value);
1655 break;
1657 case CODEC_SET_FILEBUF_CHUNKSIZE:
1658 buf_set_conf(BUFFERING_SET_CHUNKSIZE, value);
1659 break;
1661 case CODEC_SET_FILEBUF_PRESEEK:
1662 buf_set_conf(BUFFERING_SET_PRESEEK, value);
1663 break;
1665 default:
1666 if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); }
1670 static void codec_track_changed(void)
1672 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1673 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1676 static void codec_pcmbuf_track_changed_callback(void)
1678 pcmbuf_set_position_callback(NULL);
1679 codec_track_changed();
1682 static void codec_discard_codec_callback(void)
1684 if (CUR_TI->codec_hid > 0)
1686 bufclose(CUR_TI->codec_hid);
1687 CUR_TI->codec_hid = 0;
1691 static inline void codec_gapless_track_change(void)
1693 /* callback keeps the progress bar moving while the pcmbuf empties */
1694 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1695 /* set the pcmbuf callback for when the track really changes */
1696 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1699 static inline void codec_crossfade_track_change(void)
1701 /* Initiate automatic crossfade mode */
1702 pcmbuf_crossfade_init(false);
1703 /* Notify the wps that the track change starts now */
1704 codec_track_changed();
1707 static void codec_track_skip_done(bool was_manual)
1709 /* Manual track change (always crossfade or flush audio). */
1710 if (was_manual)
1712 pcmbuf_crossfade_init(true);
1713 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1714 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1716 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1717 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1718 && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP)
1720 if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1722 if (global_settings.playlist_shuffle)
1723 /* shuffle mode is on, so crossfade: */
1724 codec_crossfade_track_change();
1725 else
1726 /* shuffle mode is off, so do a gapless track change */
1727 codec_gapless_track_change();
1729 else
1730 /* normal crossfade: */
1731 codec_crossfade_track_change();
1733 else
1734 /* normal gapless playback. */
1735 codec_gapless_track_change();
1738 static bool codec_load_next_track(void)
1740 intptr_t result = Q_CODEC_REQUEST_FAILED;
1742 prev_track_elapsed = curtrack_id3.elapsed;
1744 if (ci.seek_time)
1745 codec_seek_complete_callback();
1747 #ifdef AB_REPEAT_ENABLE
1748 ab_end_of_track_report();
1749 #endif
1751 logf("Request new track");
1753 if (ci.new_track == 0)
1755 ci.new_track++;
1756 automatic_skip = true;
1759 if (!ci.stop_codec)
1761 trigger_cpu_boost();
1762 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1763 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1766 switch (result)
1768 case Q_CODEC_REQUEST_COMPLETE:
1769 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1770 codec_track_skip_done(!automatic_skip);
1771 return true;
1773 case Q_CODEC_REQUEST_FAILED:
1774 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1775 ci.new_track = 0;
1776 ci.stop_codec = true;
1777 return false;
1779 default:
1780 LOGFQUEUE("codec |< default");
1781 ci.stop_codec = true;
1782 return false;
1786 static bool codec_request_next_track_callback(void)
1788 int prev_codectype;
1790 if (ci.stop_codec || !playing)
1791 return false;
1793 prev_codectype = get_codec_base_type(curtrack_id3.codectype);
1795 if (!codec_load_next_track())
1796 return false;
1798 /* Seek to the beginning of the new track because if the struct mp3entry was
1799 buffered, "elapsed" might not be zero (if the track has been played
1800 already but not unbuffered) */
1801 codec_seek_buffer_callback(0);
1803 /* Check if the next codec is the same file. */
1804 if (prev_codectype == get_codec_base_type(curtrack_id3.codectype))
1806 logf("New track loaded");
1807 codec_discard_codec_callback();
1808 return true;
1810 else
1812 logf("New codec:%d/%d", curtrack_id3.codectype, prev_codectype);
1813 return false;
1817 static void codec_thread(void)
1819 struct queue_event ev;
1820 int status;
1822 while (1) {
1823 status = 0;
1824 queue_wait(&codec_queue, &ev);
1826 switch (ev.id) {
1827 case Q_CODEC_LOAD_DISK:
1828 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1829 queue_reply(&codec_queue, 1);
1830 audio_codec_loaded = true;
1831 #ifdef PLAYBACK_VOICE
1832 /* Don't sent messages to voice codec if it's already swapped
1833 out or it will never get this */
1834 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1836 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1837 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1839 semaphore_wait(&sem_codecthread);
1840 event_set_state(&event_codecthread, STATE_SIGNALED);
1841 #endif
1842 set_current_codec(CODEC_IDX_AUDIO);
1843 ci.stop_codec = false;
1844 status = codec_load_file((const char *)ev.data, &ci);
1845 #ifdef PLAYBACK_VOICE
1846 semaphore_release(&sem_codecthread);
1847 #endif
1848 break;
1850 case Q_CODEC_LOAD:
1851 LOGFQUEUE("codec < Q_CODEC_LOAD");
1852 if (CUR_TI->codec_hid <= 0) {
1853 logf("Codec slot is empty!");
1854 /* Wait for the pcm buffer to go empty */
1855 while (pcm_is_playing())
1856 yield();
1857 /* This must be set to prevent an infinite loop */
1858 ci.stop_codec = true;
1859 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1860 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1861 break;
1864 audio_codec_loaded = true;
1865 #ifdef PLAYBACK_VOICE
1866 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1868 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1869 queue_post(&voice_queue, Q_AUDIO_PLAY, 0);
1871 semaphore_wait(&sem_codecthread);
1872 event_set_state(&event_codecthread, STATE_SIGNALED);
1873 #endif
1874 set_current_codec(CODEC_IDX_AUDIO);
1875 ci.stop_codec = false;
1876 status = codec_load_buf(CUR_TI->codec_hid, &ci);
1877 #ifdef PLAYBACK_VOICE
1878 semaphore_release(&sem_codecthread);
1879 #endif
1880 break;
1882 #ifdef AUDIO_HAVE_RECORDING
1883 case Q_ENCODER_LOAD_DISK:
1884 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1885 audio_codec_loaded = false; /* Not audio codec! */
1886 #ifdef PLAYBACK_VOICE
1887 if (voice_codec_loaded && current_codec == CODEC_IDX_VOICE)
1889 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1890 queue_post(&voice_queue, Q_ENCODER_RECORD, 0);
1892 semaphore_wait(&sem_codecthread);
1893 event_set_state(&event_codecthread, STATE_SIGNALED);
1894 #endif
1895 logf("loading encoder");
1896 set_current_codec(CODEC_IDX_AUDIO);
1897 ci.stop_encoder = false;
1898 status = codec_load_file((const char *)ev.data, &ci);
1899 #ifdef PLAYBACK_VOICE
1900 semaphore_release(&sem_codecthread);
1901 #endif
1902 logf("encoder stopped");
1903 break;
1904 #endif /* AUDIO_HAVE_RECORDING */
1906 default:
1907 LOGFQUEUE("codec < default");
1910 if (audio_codec_loaded)
1912 if (ci.stop_codec)
1914 status = CODEC_OK;
1915 if (!playing)
1916 pcmbuf_play_stop();
1919 audio_codec_loaded = false;
1922 switch (ev.id) {
1923 case Q_CODEC_LOAD_DISK:
1924 case Q_CODEC_LOAD:
1925 LOGFQUEUE("codec < Q_CODEC_LOAD");
1926 if (playing)
1928 if (ci.new_track || status != CODEC_OK)
1930 if (!ci.new_track)
1932 logf("Codec failure");
1933 gui_syncsplash(HZ*2, "Codec failure");
1936 if (!codec_load_next_track())
1938 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1939 /* End of playlist */
1940 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1941 break;
1944 else
1946 logf("Codec finished");
1947 if (ci.stop_codec)
1949 /* Wait for the audio to stop playing before
1950 * triggering the WPS exit */
1951 while(pcm_is_playing())
1953 curtrack_id3.elapsed =
1954 curtrack_id3.length - pcmbuf_get_latency();
1955 sleep(1);
1957 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1958 /* End of playlist */
1959 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1960 break;
1964 if (CUR_TI->codec_hid > 0)
1966 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
1967 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
1969 else
1971 const char *codec_fn =
1972 get_codec_filename(curtrack_id3.codectype);
1973 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1974 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
1975 (intptr_t)codec_fn);
1978 break;
1980 #ifdef AUDIO_HAVE_RECORDING
1981 case Q_ENCODER_LOAD_DISK:
1982 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1984 if (status == CODEC_OK)
1985 break;
1987 logf("Encoder failure");
1988 gui_syncsplash(HZ*2, "Encoder failure");
1990 if (ci.enc_codec_loaded < 0)
1991 break;
1993 logf("Encoder failed to load");
1994 ci.enc_codec_loaded = -1;
1995 break;
1996 #endif /* AUDIO_HAVE_RECORDING */
1998 default:
1999 LOGFQUEUE("codec < default");
2001 } /* end switch */
2006 /* --- Audio thread --- */
2008 static bool audio_have_tracks(void)
2010 return track_ridx != track_widx || CUR_TI->filesize;
2013 static bool audio_have_free_tracks(void)
2015 if (track_widx < track_ridx)
2016 return track_widx + 1 < track_ridx;
2017 else if (track_ridx == 0)
2018 return track_widx < MAX_TRACK - 1;
2020 return true;
2023 int audio_track_count(void)
2025 if (audio_have_tracks())
2027 int relative_track_widx = track_widx;
2029 if (track_ridx > track_widx)
2030 relative_track_widx += MAX_TRACK;
2032 return relative_track_widx - track_ridx + 1;
2035 return 0;
2038 long audio_filebufused(void)
2040 return (long) buf_used();
2043 static void audio_update_trackinfo(void)
2045 if (CUR_TI->id3_hid > 0)
2046 copy_mp3entry(&curtrack_id3, bufgetid3(CUR_TI->id3_hid));
2048 CUR_TI->taginfo_ready = (CUR_TI->id3_hid > 0);
2050 int next_idx = track_ridx + 1;
2051 next_idx &= MAX_TRACK_MASK;
2053 if (tracks[next_idx].id3_hid > 0)
2054 copy_mp3entry(&nexttrack_id3, bufgetid3(tracks[next_idx].id3_hid));
2056 tracks[next_idx].taginfo_ready = (tracks[next_idx].id3_hid > 0);
2058 ci.filesize = CUR_TI->filesize;
2059 curtrack_id3.elapsed = 0;
2060 curtrack_id3.offset = 0;
2061 ci.id3 = &curtrack_id3;
2062 ci.curpos = 0;
2063 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2066 static void low_buffer_callback(void)
2068 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
2069 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
2072 static void audio_clear_track_entries(bool clear_unbuffered)
2074 int cur_idx = track_widx;
2076 logf("Clearing tracks:%d/%d, %d", track_ridx, track_widx, clear_unbuffered);
2078 /* This function is always called in association with a stop or a rebuffer,
2079 * we will reregister the callback at the end of a rebuffer if needed */
2080 unregister_buffer_low_callback(low_buffer_callback);
2082 /* Loop over all tracks from write-to-read */
2083 while (1)
2085 cur_idx++;
2086 cur_idx &= MAX_TRACK_MASK;
2088 if (cur_idx == track_ridx)
2089 break;
2091 /* If the track is buffered, conditionally clear/notify,
2092 * otherwise clear the track if that option is selected */
2093 if (tracks[cur_idx].event_sent)
2095 /* If there is an unbuffer callback, call it, otherwise,
2096 * just clear the track */
2097 if (track_unbuffer_callback && tracks[cur_idx].id3_hid > 0)
2098 track_unbuffer_callback(bufgetid3(tracks[cur_idx].id3_hid));
2100 clear_track_info(&tracks[cur_idx]);
2102 else if (clear_unbuffered)
2103 clear_track_info(&tracks[cur_idx]);
2107 static bool audio_release_tracks(void)
2109 int i, cur_idx;
2111 logf("releasing all tracks");
2113 for(i = 0; i < MAX_TRACKS; i++)
2115 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
2116 if (!clear_track_info(&tracks[cur_idx]))
2117 return false;
2120 return true;
2123 static bool audio_loadcodec(bool start_play)
2125 int prev_track;
2126 char codec_path[MAX_PATH]; /* Full path to codec */
2128 if (tracks[track_widx].id3_hid <= 0) {
2129 return false;
2132 const char * codec_fn =
2133 get_codec_filename(bufgetid3(tracks[track_widx].id3_hid)->codectype);
2134 if (codec_fn == NULL)
2135 return false;
2137 tracks[track_widx].codec_hid = false;
2139 if (start_play)
2141 /* Load the codec directly from disk and save some memory. */
2142 track_ridx = track_widx;
2143 ci.filesize = CUR_TI->filesize;
2144 ci.id3 = &curtrack_id3;
2145 ci.taginfo_ready = &CUR_TI->taginfo_ready;
2146 ci.curpos = 0;
2147 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2148 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
2149 return true;
2151 else
2153 /* If we already have another track than this one buffered */
2154 if (track_widx != track_ridx)
2156 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
2158 /* If the previous codec is the same as this one, there is no need
2159 * to put another copy of it on the file buffer */
2160 if (get_codec_base_type(
2161 bufgetid3(tracks[track_widx].id3_hid)->codectype) ==
2162 get_codec_base_type(
2163 bufgetid3(tracks[prev_track].id3_hid)->codectype)
2164 && audio_codec_loaded)
2166 logf("Reusing prev. codec");
2167 return true;
2172 codec_get_full_path(codec_path, codec_fn);
2174 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
2175 if (tracks[track_widx].codec_hid < 0)
2176 return false;
2178 logf("Loaded codec");
2180 return true;
2183 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2184 static void audio_set_elapsed(struct mp3entry* id3)
2186 unsigned long offset = id3->offset > id3->first_frame_offset ?
2187 id3->offset - id3->first_frame_offset : 0;
2189 if ( id3->vbr ) {
2190 if ( id3->has_toc ) {
2191 /* calculate elapsed time using TOC */
2192 int i;
2193 unsigned int remainder, plen, relpos, nextpos;
2195 /* find wich percent we're at */
2196 for (i=0; i<100; i++ )
2197 if ( offset < id3->toc[i] * (id3->filesize / 256) )
2198 break;
2200 i--;
2201 if (i < 0)
2202 i = 0;
2204 relpos = id3->toc[i];
2206 if (i < 99)
2207 nextpos = id3->toc[i+1];
2208 else
2209 nextpos = 256;
2211 remainder = offset - (relpos * (id3->filesize / 256));
2213 /* set time for this percent (divide before multiply to prevent
2214 overflow on long files. loss of precision is negligible on
2215 short files) */
2216 id3->elapsed = i * (id3->length / 100);
2218 /* calculate remainder time */
2219 plen = (nextpos - relpos) * (id3->filesize / 256);
2220 id3->elapsed += (((remainder * 100) / plen) *
2221 (id3->length / 10000));
2223 else {
2224 /* no TOC exists. set a rough estimate using average bitrate */
2225 int tpk = id3->length /
2226 ((id3->filesize - id3->first_frame_offset - id3->id3v1len) /
2227 1024);
2228 id3->elapsed = offset / 1024 * tpk;
2231 else
2233 /* constant bitrate, use exact calculation */
2234 if (id3->bitrate != 0)
2235 id3->elapsed = offset / (id3->bitrate / 8);
2239 /* Load one track by making the appropriate bufopen calls. Return true if
2240 everything required was loaded correctly, false if not. */
2241 static bool audio_load_track(int offset, bool start_play)
2243 char *trackname;
2244 char msgbuf[80];
2245 int fd = -1;
2246 int file_offset = 0;
2247 struct mp3entry id3;
2249 /* Stop buffer filling if there is no free track entries.
2250 Don't fill up the last track entry (we wan't to store next track
2251 metadata there). */
2252 if (!audio_have_free_tracks())
2254 logf("No free tracks");
2255 return false;
2258 last_peek_offset++;
2259 peek_again:
2260 logf("Buffering track:%d/%d", track_widx, track_ridx);
2261 /* Get track name from current playlist read position. */
2262 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
2264 /* Handle broken playlists. */
2265 fd = open(trackname, O_RDONLY);
2266 if (fd < 0)
2268 logf("Open failed");
2269 /* Skip invalid entry from playlist. */
2270 playlist_skip_entry(NULL, last_peek_offset);
2272 else
2273 break;
2276 if (!trackname)
2278 logf("End-of-playlist");
2279 playlist_end = true;
2280 return false;
2283 tracks[track_widx].filesize = filesize(fd);
2285 /* Set default values */
2286 if (start_play)
2288 int last_codec = current_codec;
2290 set_current_codec(CODEC_IDX_AUDIO);
2291 buf_set_conf(BUFFERING_SET_WATERMARK, AUDIO_DEFAULT_WATERMARK);
2292 buf_set_conf(BUFFERING_SET_CHUNKSIZE, AUDIO_DEFAULT_FILECHUNK);
2293 buf_set_conf(BUFFERING_SET_PRESEEK, AUDIO_REBUFFER_GUESS_SIZE);
2294 dsp_configure(DSP_RESET, 0);
2295 set_current_codec(last_codec);
2297 track_changed = true;
2298 playlist_update_resume_info(audio_current_track());
2301 /* Get track metadata if we don't already have it. */
2302 if (tracks[track_widx].id3_hid <= 0)
2304 if (get_metadata(&id3, fd, trackname))
2306 tracks[track_widx].id3_hid = bufalloc(&id3, sizeof(struct mp3entry),
2307 TYPE_ID3);
2308 tracks[track_widx].taginfo_ready = (tracks[track_widx].id3_hid > 0);
2310 if (tracks[track_widx].id3_hid <= 0)
2312 last_peek_offset--;
2313 close(fd);
2314 return false;
2317 if (track_widx == track_ridx)
2318 copy_mp3entry(&curtrack_id3, &id3);
2319 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2320 copy_mp3entry(&nexttrack_id3, &id3);
2322 if (start_play)
2324 track_changed = true;
2325 playlist_update_resume_info(audio_current_track());
2328 else
2330 logf("mde:%s!",trackname);
2332 /* Skip invalid entry from playlist. */
2333 playlist_skip_entry(NULL, last_peek_offset);
2334 tracks[track_widx].taginfo_ready = false;
2335 close(fd);
2336 goto peek_again;
2341 close(fd);
2343 #if 0
2344 if (cuesheet_is_enabled() && tracks[track_widx].id3.cuesheet_type == 1)
2346 char cuepath[MAX_PATH];
2348 struct cuesheet *cue = start_play ? curr_cue : temp_cue;
2350 if (look_for_cuesheet_file(trackname, cuepath) &&
2351 parse_cuesheet(cuepath, cue))
2353 strcpy((cue)->audio_filename, trackname);
2354 if (start_play)
2355 cue_spoof_id3(curr_cue, &tracks[track_widx].id3);
2358 #endif
2360 /* Load the codec. */
2361 if (!audio_loadcodec(start_play))
2363 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
2365 /* No space for codec on buffer, not an error */
2366 return false;
2369 /* This is an error condition, either no codec was found, or reading
2370 * the codec file failed part way through, either way, skip the track */
2371 snprintf(msgbuf, sizeof(msgbuf)-1, "No codec for: %s", trackname);
2372 /* We should not use gui_syncplash from audio thread! */
2373 gui_syncsplash(HZ*2, msgbuf);
2374 /* Skip invalid entry from playlist. */
2375 playlist_skip_entry(NULL, last_peek_offset);
2376 tracks[track_widx].taginfo_ready = false;
2377 goto peek_again;
2380 struct mp3entry *track_id3;
2382 if (track_widx == track_ridx)
2383 track_id3 = &curtrack_id3;
2384 else if (track_widx == ((track_ridx + 1) & MAX_TRACK_MASK))
2385 track_id3 = &nexttrack_id3;
2386 else
2387 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
2389 #ifndef HAVE_FLASH_STORAGE
2390 set_filebuf_watermark(buffer_margin, 0);
2391 #endif
2392 track_id3->elapsed = 0;
2394 enum data_type type = TYPE_PACKET_AUDIO;
2396 switch (track_id3->codectype) {
2397 case AFMT_MPA_L1:
2398 case AFMT_MPA_L2:
2399 case AFMT_MPA_L3:
2400 if (offset > 0) {
2401 file_offset = offset;
2402 track_id3->offset = offset;
2403 audio_set_elapsed(track_id3);
2404 ci.curpos = offset;
2406 break;
2408 case AFMT_WAVPACK:
2409 if (offset > 0) {
2410 file_offset = offset;
2411 track_id3->offset = offset;
2412 track_id3->elapsed = track_id3->length / 2;
2413 ci.curpos = offset;
2415 break;
2417 case AFMT_OGG_VORBIS:
2418 case AFMT_SPEEX:
2419 case AFMT_FLAC:
2420 case AFMT_PCM_WAV:
2421 case AFMT_A52:
2422 case AFMT_AAC:
2423 case AFMT_MPC:
2424 case AFMT_APE:
2425 if (offset > 0)
2426 track_id3->offset = offset;
2427 break;
2429 case AFMT_NSF:
2430 case AFMT_SPC:
2431 case AFMT_SID:
2432 logf("Loading atomic %d",track_id3->codectype);
2433 type = TYPE_ATOMIC_AUDIO;
2434 break;
2437 logf("alt:%s", trackname);
2439 tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type);
2441 if (tracks[track_widx].audio_hid <= 0)
2442 return false;
2444 if (start_play)
2446 buf_request_buffer_handle(tracks[track_widx].audio_hid);
2449 track_widx++;
2450 track_widx &= MAX_TRACK_MASK;
2452 return true;
2455 /* Send callback events to notify about new tracks. */
2456 static void audio_generate_postbuffer_events(void)
2458 int cur_idx;
2460 logf("Postbuffer:%d/%d",track_ridx,track_widx);
2462 if (audio_have_tracks())
2464 cur_idx = track_ridx;
2466 while (1) {
2467 if (!tracks[cur_idx].event_sent)
2469 /* Mark the event 'sent' even if we don't really send one */
2470 tracks[cur_idx].event_sent = true;
2471 if (track_buffer_callback && tracks[cur_idx].id3_hid > 0)
2472 track_buffer_callback(bufgetid3(tracks[cur_idx].id3_hid));
2474 if (cur_idx == track_widx)
2475 break;
2476 cur_idx++;
2477 cur_idx &= MAX_TRACK_MASK;
2482 static void audio_fill_file_buffer(bool start_play, size_t offset)
2484 struct queue_event ev;
2485 bool had_next_track = audio_next_track() != NULL;
2486 bool continue_buffering;
2488 /* Must reset the buffer before use if trashed or voice only - voice
2489 file size shouldn't have changed so we can go straight from
2490 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2491 if (buffer_state != BUFFER_STATE_INITIALIZED)
2492 audio_reset_buffer();
2494 logf("Starting buffer fill");
2496 if (!start_play)
2497 audio_clear_track_entries(false);
2499 /* Save the current resume position once. */
2500 playlist_update_resume_info(audio_current_track());
2502 do {
2503 continue_buffering = audio_load_track(offset, start_play);
2504 start_play = false;
2505 offset = 0;
2506 sleep(1);
2507 if (queue_peek(&audio_queue, &ev)) {
2508 if (ev.id != Q_AUDIO_FILL_BUFFER)
2510 /* There's a message in the queue. break the loop to treat it,
2511 and go back to filling after that. */
2512 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
2513 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
2515 break;
2517 } while (continue_buffering);
2519 if (!had_next_track && audio_next_track())
2520 track_changed = true;
2522 audio_generate_postbuffer_events();
2524 if (!continue_buffering)
2525 register_buffer_low_callback(low_buffer_callback);
2528 static void audio_rebuffer(void)
2530 logf("Forcing rebuffer");
2532 clear_track_info(CUR_TI);
2534 /* Reset track pointers */
2535 track_widx = track_ridx;
2536 audio_clear_track_entries(true);
2538 /* Fill the buffer */
2539 last_peek_offset = -1;
2540 ci.curpos = 0;
2542 if (!CUR_TI->taginfo_ready)
2543 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2545 audio_fill_file_buffer(false, 0);
2548 static int audio_check_new_track(void)
2550 int track_count = audio_track_count();
2551 int old_track_ridx = track_ridx;
2552 bool forward;
2554 if (dir_skip)
2556 dir_skip = false;
2557 if (playlist_next_dir(ci.new_track))
2559 ci.new_track = 0;
2560 audio_rebuffer();
2561 goto skip_done;
2563 else
2565 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2566 return Q_CODEC_REQUEST_FAILED;
2570 if (new_playlist)
2571 ci.new_track = 0;
2573 /* If the playlist isn't that big */
2574 if (!playlist_check(ci.new_track))
2576 if (ci.new_track >= 0)
2578 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2579 return Q_CODEC_REQUEST_FAILED;
2581 /* Find the beginning backward if the user over-skips it */
2582 while (!playlist_check(++ci.new_track))
2583 if (ci.new_track >= 0)
2585 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2586 return Q_CODEC_REQUEST_FAILED;
2589 /* Update the playlist */
2590 last_peek_offset -= ci.new_track;
2592 if (playlist_next(ci.new_track) < 0)
2594 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2595 return Q_CODEC_REQUEST_FAILED;
2598 if (new_playlist)
2600 ci.new_track = 1;
2601 new_playlist = false;
2604 /* Save the old track */
2605 copy_mp3entry(&prevtrack_id3, &curtrack_id3);
2607 int i, idx;
2608 for (i = 0; i < ci.new_track; i++)
2610 idx = (track_ridx + i) & MAX_TRACK_MASK;
2611 if (buf_handle_offset(tracks[idx].audio_hid) > 0)
2612 clear_track_info(&tracks[idx]);
2615 /* Move to the new track */
2616 track_ridx += ci.new_track;
2617 track_ridx &= MAX_TRACK_MASK;
2619 buf_set_base_handle(CUR_TI->audio_hid);
2621 if (automatic_skip)
2623 playlist_end = false;
2624 wps_offset = -ci.new_track;
2627 track_changed = true;
2629 /* If it is not safe to even skip this many track entries */
2630 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
2632 ci.new_track = 0;
2633 audio_rebuffer();
2634 goto skip_done;
2637 forward = ci.new_track > 0;
2638 ci.new_track = 0;
2640 /* If the target track is clearly not in memory */
2641 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
2643 audio_rebuffer();
2644 goto skip_done;
2647 /* When skipping backwards, it is possible that we've found a track that's
2648 * buffered, but which is around the track-wrap and therefor not the track
2649 * we are looking for */
2650 if (!forward)
2652 int cur_idx = track_ridx;
2653 bool taginfo_ready = true;
2654 /* We've wrapped the buffer backwards if new > old */
2655 bool wrap = track_ridx > old_track_ridx;
2657 while (1)
2659 cur_idx++;
2660 cur_idx &= MAX_TRACK_MASK;
2662 /* if we've advanced past the wrap when cur_idx is zeroed */
2663 if (!cur_idx)
2664 wrap = false;
2666 /* if we aren't still on the wrap and we've caught the old track */
2667 if (!(wrap || cur_idx < old_track_ridx))
2668 break;
2670 /* If we hit a track in between without valid tag info, bail */
2671 if (!tracks[cur_idx].taginfo_ready)
2673 taginfo_ready = false;
2674 break;
2677 if (!taginfo_ready)
2679 audio_rebuffer();
2683 skip_done:
2684 audio_update_trackinfo();
2685 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
2686 return Q_CODEC_REQUEST_COMPLETE;
2689 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3))
2691 track_buffer_callback = handler;
2694 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3))
2696 track_unbuffer_callback = handler;
2699 void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
2701 track_changed_callback = handler;
2704 unsigned long audio_prev_elapsed(void)
2706 return prev_track_elapsed;
2709 static void audio_stop_codec_flush(void)
2711 ci.stop_codec = true;
2712 pcmbuf_pause(true);
2714 while (audio_codec_loaded)
2715 yield();
2717 /* If the audio codec is not loaded any more, and the audio is still
2718 * playing, it is now and _only_ now safe to call this function from the
2719 * audio thread */
2720 if (pcm_is_playing())
2721 pcmbuf_play_stop();
2722 pcmbuf_pause(paused);
2725 static void audio_stop_playback(void)
2727 /* If we were playing, save resume information */
2728 if (playing)
2730 struct mp3entry *id3 = NULL;
2732 if (!playlist_end || !ci.stop_codec)
2734 /* Set this early, the outside code yields and may allow the codec
2735 to try to wait for a reply on a buffer wait */
2736 ci.stop_codec = true;
2737 id3 = audio_current_track();
2740 /* Save the current playing spot, or NULL if the playlist has ended */
2741 playlist_update_resume_info(id3);
2743 prev_track_elapsed = curtrack_id3.elapsed;
2745 /* Increment index so runtime info is saved in audio_clear_track_entries().
2746 * Done here, as audio_stop_playback() may be called more than once.
2747 * Don't update runtime unless playback is stopped because of end of playlist.
2748 * Updating runtime when manually stopping a tracks, can destroy autoscores
2749 * and playcounts.
2751 if (playlist_end)
2753 track_ridx++;
2754 track_ridx &= MAX_TRACK_MASK;
2758 paused = false;
2759 audio_stop_codec_flush();
2760 playing = false;
2762 /* Mark all entries null. */
2763 audio_clear_track_entries(false);
2765 /* Close all tracks */
2766 audio_release_tracks();
2768 memset(&curtrack_id3, 0, sizeof(struct mp3entry));
2769 memset(&nexttrack_id3, 0, sizeof(struct mp3entry));
2772 static void audio_play_start(size_t offset)
2774 #if INPUT_SRC_CAPS != 0
2775 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2776 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2777 #endif
2779 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2780 paused = false;
2781 audio_stop_codec_flush();
2783 track_changed = true;
2784 playlist_end = false;
2786 playing = true;
2788 ci.new_track = 0;
2789 ci.seek_time = 0;
2790 wps_offset = 0;
2792 sound_set_volume(global_settings.volume);
2793 track_widx = track_ridx = 0;
2795 /* Mark all entries null. */
2796 memset(tracks, 0, sizeof(struct track_info) * MAX_TRACK);
2798 last_peek_offset = -1;
2800 /* Officially playing */
2801 queue_reply(&audio_queue, 1);
2803 audio_fill_file_buffer(true, offset);
2805 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
2806 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
2810 /* Invalidates all but currently playing track. */
2811 static void audio_invalidate_tracks(void)
2813 if (audio_have_tracks())
2815 last_peek_offset = 0;
2816 playlist_end = false;
2817 track_widx = track_ridx;
2819 /* Mark all other entries null (also buffered wrong metadata). */
2820 audio_clear_track_entries(true);
2822 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
2824 audio_fill_file_buffer(false, 0);
2828 static void audio_new_playlist(void)
2830 /* Prepare to start a new fill from the beginning of the playlist */
2831 last_peek_offset = -1;
2832 if (audio_have_tracks())
2834 if (paused)
2835 skipped_during_pause = true;
2836 playlist_end = false;
2837 track_widx = track_ridx;
2838 audio_clear_track_entries(true);
2840 track_widx++;
2841 track_widx &= MAX_TRACK_MASK;
2843 /* Mark the current track as invalid to prevent skipping back to it */
2844 CUR_TI->taginfo_ready = false;
2847 /* Signal the codec to initiate a track change forward */
2848 new_playlist = true;
2849 ci.new_track = 1;
2851 /* Officially playing */
2852 queue_reply(&audio_queue, 1);
2854 audio_fill_file_buffer(false, 0);
2857 static void audio_initiate_track_change(long direction)
2859 playlist_end = false;
2860 ci.new_track += direction;
2861 wps_offset -= direction;
2862 if (paused)
2863 skipped_during_pause = true;
2866 static void audio_initiate_dir_change(long direction)
2868 playlist_end = false;
2869 dir_skip = true;
2870 ci.new_track = direction;
2871 if (paused)
2872 skipped_during_pause = true;
2876 * Layout audio buffer as follows - iram buffer depends on target:
2877 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
2879 static void audio_reset_buffer(void)
2881 /* see audio_get_recording_buffer if this is modified */
2882 logf("audio_reset_buffer");
2884 /* If the setup of anything allocated before the file buffer is
2885 changed, do check the adjustments after the buffer_alloc call
2886 as it will likely be affected and need sliding over */
2888 /* Initially set up file buffer as all space available */
2889 malloc_buf = audiobuf + talk_get_bufsize();
2890 /* Align the malloc buf to line size. Especially important to cf
2891 targets that do line reads/writes. */
2892 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
2893 filebuf = malloc_buf + MALLOC_BUFSIZE; /* filebuf line align implied */
2894 filebuflen = audiobufend - filebuf;
2896 /* Allow for codec swap space at end of audio buffer */
2897 if (talk_voice_required())
2899 /* Layout of swap buffer:
2900 * #ifdef IRAM_STEAL (dedicated iram_buf):
2901 * |iram_buf|...audiobuf...|dram_buf|audiobufend
2902 * #else:
2903 * audiobuf...|dram_buf|iram_buf|audiobufend
2905 #ifdef PLAYBACK_VOICE
2906 /* Check for an absolutely nasty situation which should never,
2907 ever happen - frankly should just panic */
2908 if (voice_codec_loaded && current_codec != CODEC_IDX_VOICE)
2910 logf("buffer reset with voice swapped");
2912 /* line align length which line aligns the calculations below since
2913 all sizes are also at least line aligned - needed for memswap128 */
2914 filebuflen &= ~15;
2915 #ifdef IRAM_STEAL
2916 filebuflen -= CODEC_SIZE;
2917 #else
2918 filebuflen -= CODEC_SIZE + CODEC_IRAM_SIZE;
2919 #endif
2920 /* Allocate buffers for swapping voice <=> audio */
2921 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
2922 and out of the way of buffer usage or else a call to audio_get_buffer
2923 and subsequent buffer use might trash the swap space. A plugin
2924 initializing IRAM after getting the full buffer would present similar
2925 problem. Options include: failing the request if the other buffer
2926 has been obtained already or never allowing use of the voice IRAM
2927 buffer within the audio buffer. Using buffer_alloc basically
2928 implements the second in a more convenient way. */
2929 dram_buf = filebuf + filebuflen;
2931 #ifdef IRAM_STEAL
2932 /* Allocate voice IRAM swap buffer once */
2933 if (iram_buf == NULL)
2935 iram_buf = buffer_alloc(CODEC_IRAM_SIZE);
2936 /* buffer_alloc moves audiobuf; this is safe because only the end
2937 * has been touched so far in this function and the address of
2938 * filebuf + filebuflen is not changed */
2939 malloc_buf += CODEC_IRAM_SIZE;
2940 filebuf += CODEC_IRAM_SIZE;
2941 filebuflen -= CODEC_IRAM_SIZE;
2943 #else
2944 /* Allocate iram_buf after dram_buf */
2945 iram_buf = dram_buf + CODEC_SIZE;
2946 #endif /* IRAM_STEAL */
2947 #endif /* PLAYBACK_VOICE */
2949 else
2951 #ifdef PLAYBACK_VOICE
2952 /* No swap buffers needed */
2953 iram_buf = NULL;
2954 dram_buf = NULL;
2955 #endif
2958 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
2959 filebuflen -= pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
2961 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
2962 will already be line aligned */
2963 filebuflen &= ~3;
2965 buffering_reset(filebuf, filebuflen);
2967 /* Clear any references to the file buffer */
2968 buffer_state = BUFFER_STATE_INITIALIZED;
2970 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
2971 /* Make sure everything adds up - yes, some info is a bit redundant but
2972 aids viewing and the sumation of certain variables should add up to
2973 the location of others. */
2975 size_t pcmbufsize;
2976 unsigned char * pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
2977 logf("mabuf: %08X", (unsigned)malloc_buf);
2978 logf("mabufe: %08X", (unsigned)(malloc_buf + MALLOC_BUFSIZE));
2979 logf("fbuf: %08X", (unsigned)filebuf);
2980 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
2981 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
2982 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
2983 logf("pcmb: %08X", (unsigned)pcmbuf);
2984 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
2985 if (dram_buf)
2987 logf("dramb: %08X", (unsigned)dram_buf);
2988 logf("drambe: %08X", (unsigned)(dram_buf + CODEC_SIZE));
2990 if (iram_buf)
2992 logf("iramb: %08X", (unsigned)iram_buf);
2993 logf("irambe: %08X", (unsigned)(iram_buf + CODEC_IRAM_SIZE));
2996 #endif
2999 static void audio_thread(void)
3001 struct queue_event ev;
3003 pcm_postinit();
3005 #ifdef PLAYBACK_VOICE
3006 /* Unlock semaphore that init stage locks before creating this thread */
3007 semaphore_release(&sem_codecthread);
3009 /* Buffers must be set up by now - should panic - really */
3010 if (buffer_state != BUFFER_STATE_INITIALIZED)
3012 logf("audio_thread start: no buffer");
3015 /* Have to wait for voice to load up or else the codec swap will be
3016 invalid when an audio codec is loaded */
3017 wait_for_voice_swap_in();
3018 #endif
3020 while (1)
3022 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
3024 switch (ev.id) {
3025 case Q_AUDIO_FILL_BUFFER:
3026 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3027 if (!playing || playlist_end || ci.stop_codec)
3028 break;
3029 audio_fill_file_buffer(false, 0);
3030 break;
3032 case Q_AUDIO_PLAY:
3033 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3034 if (playing && ev.data <= 0)
3035 audio_new_playlist();
3036 else
3038 audio_stop_playback();
3039 audio_play_start((size_t)ev.data);
3041 break;
3043 case Q_AUDIO_STOP:
3044 LOGFQUEUE("audio < Q_AUDIO_STOP");
3045 if (playing)
3046 audio_stop_playback();
3047 if (ev.data != 0)
3048 queue_clear(&audio_queue);
3049 break;
3051 case Q_AUDIO_PAUSE:
3052 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3053 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
3054 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3055 skipped_during_pause = false;
3056 if (!playing)
3057 break;
3058 pcmbuf_pause((bool)ev.data);
3059 paused = (bool)ev.data;
3060 break;
3062 case Q_AUDIO_SKIP:
3063 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3064 audio_initiate_track_change((long)ev.data);
3065 break;
3067 case Q_AUDIO_PRE_FF_REWIND:
3068 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3069 if (!playing)
3070 break;
3071 pcmbuf_pause(true);
3072 break;
3074 case Q_AUDIO_FF_REWIND:
3075 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3076 if (!playing)
3077 break;
3078 ci.seek_time = (long)ev.data+1;
3079 break;
3081 case Q_AUDIO_CHECK_NEW_TRACK:
3082 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3083 queue_reply(&audio_queue, audio_check_new_track());
3084 break;
3086 case Q_AUDIO_DIR_SKIP:
3087 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3088 playlist_end = false;
3089 audio_initiate_dir_change(ev.data);
3090 break;
3092 case Q_AUDIO_FLUSH:
3093 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3094 audio_invalidate_tracks();
3095 break;
3097 case Q_AUDIO_TRACK_CHANGED:
3098 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3099 if (automatic_skip)
3101 wps_offset = 0;
3102 automatic_skip = false;
3104 prevtrack_id3.path[0] = 0;
3105 if (track_changed_callback)
3106 track_changed_callback(&curtrack_id3);
3107 track_changed = true;
3108 playlist_update_resume_info(audio_current_track());
3109 break;
3111 #ifndef SIMULATOR
3112 case SYS_USB_CONNECTED:
3113 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3114 if (playing)
3115 audio_stop_playback();
3116 #ifdef PLAYBACK_VOICE
3117 wait_for_voice_swap_in();
3118 voice_stop();
3119 #endif
3120 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3121 usb_wait_for_disconnect(&audio_queue);
3123 /* Mark all entries null. */
3124 audio_clear_track_entries(false);
3126 /* release tracks to make sure all handles are closed */
3127 audio_release_tracks();
3128 break;
3129 #endif
3131 case SYS_TIMEOUT:
3132 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3133 break;
3135 default:
3136 LOGFQUEUE("audio < default");
3137 break;
3138 } /* end switch */
3139 } /* end while */
3142 #ifdef ROCKBOX_HAS_LOGF
3143 static void audio_test_track_changed_event(struct mp3entry *id3)
3145 (void)id3;
3147 logf("tce:%s", id3->path);
3149 #endif
3151 /* Initialize the audio system - called from init() in main.c.
3152 * Last function because of all the references to internal symbols
3154 void audio_init(void)
3156 #ifdef PLAYBACK_VOICE
3157 static bool voicetagtrue = true;
3158 static struct mp3entry id3_voice;
3159 struct thread_entry *voice_thread_p = NULL;
3160 #endif
3161 struct thread_entry *audio_thread_p;
3163 /* Can never do this twice */
3164 if (audio_is_initialized)
3166 logf("audio: already initialized");
3167 return;
3170 logf("audio: initializing");
3172 /* Initialize queues before giving control elsewhere in case it likes
3173 to send messages. Thread creation will be delayed however so nothing
3174 starts running until ready if something yields such as talk_init. */
3175 #ifdef PLAYBACK_VOICE
3176 /* Take ownership of lock to prevent playback of anything before audio
3177 hardware is initialized - audio thread unlocks it after final init
3178 stage */
3179 semaphore_init(&sem_codecthread, 1, 0);
3180 event_init(&event_codecthread, EVENT_MANUAL | STATE_SIGNALED);
3181 #endif
3182 queue_init(&audio_queue, true);
3183 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list);
3184 queue_init(&codec_queue, false);
3185 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list);
3187 pcm_init();
3189 #ifdef ROCKBOX_HAS_LOGF
3190 audio_set_track_changed_event(audio_test_track_changed_event);
3191 #endif
3193 /* Initialize codec api. */
3194 ci.read_filebuf = codec_filebuf_callback;
3195 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
3196 ci.get_codec_memory = codec_get_memory_callback;
3197 ci.request_buffer = codec_request_buffer_callback;
3198 ci.advance_buffer = codec_advance_buffer_callback;
3199 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
3200 ci.request_next_track = codec_request_next_track_callback;
3201 ci.mp3_get_filepos = codec_mp3_get_filepos_callback;
3202 ci.seek_buffer = codec_seek_buffer_callback;
3203 ci.seek_complete = codec_seek_complete_callback;
3204 ci.set_elapsed = codec_set_elapsed_callback;
3205 ci.set_offset = codec_set_offset_callback;
3206 ci.configure = codec_configure_callback;
3207 ci.discard_codec = codec_discard_codec_callback;
3209 /* Initialize voice codec api. */
3210 #ifdef PLAYBACK_VOICE
3211 memcpy(&ci_voice, &ci, sizeof(ci_voice));
3212 memset(&id3_voice, 0, sizeof(id3_voice));
3213 ci_voice.read_filebuf = voice_filebuf_callback;
3214 ci_voice.pcmbuf_insert = voice_pcmbuf_insert_callback;
3215 ci_voice.get_codec_memory = voice_get_memory_callback;
3216 ci_voice.request_buffer = voice_request_buffer_callback;
3217 ci_voice.advance_buffer = voice_advance_buffer_callback;
3218 ci_voice.advance_buffer_loc = voice_advance_buffer_loc_callback;
3219 ci_voice.request_next_track = voice_request_next_track_callback;
3220 ci_voice.mp3_get_filepos = voice_mp3_get_filepos_callback;
3221 ci_voice.seek_buffer = voice_seek_buffer_callback;
3222 ci_voice.seek_complete = voice_do_nothing;
3223 ci_voice.set_elapsed = voice_set_elapsed_callback;
3224 ci_voice.set_offset = voice_set_offset_callback;
3225 ci_voice.configure = voice_configure_callback;
3226 ci_voice.discard_codec = voice_do_nothing;
3227 ci_voice.taginfo_ready = &voicetagtrue;
3228 ci_voice.id3 = &id3_voice;
3229 id3_voice.frequency = 11200;
3230 id3_voice.length = 1000000L;
3231 #endif
3233 /* initialize the buffer */
3234 filebuf = audiobuf;
3236 /* audio_reset_buffer must to know the size of voice buffer so init
3237 talk first */
3238 talk_init();
3240 codec_thread_p = create_thread(
3241 codec_thread, codec_stack, sizeof(codec_stack),
3242 CREATE_THREAD_FROZEN,
3243 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
3244 IF_COP(, CPU));
3246 audio_thread_p = create_thread(audio_thread, audio_stack,
3247 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3248 audio_thread_name IF_PRIO(, PRIORITY_BACKGROUND)
3249 IF_COP(, CPU));
3251 #ifdef PLAYBACK_VOICE
3252 /* TODO: Change this around when various speech codecs can be used */
3253 if (talk_voice_required())
3255 logf("Starting voice codec");
3256 queue_init(&voice_queue, false);
3257 voice_thread_p = create_thread(voice_thread, voice_stack,
3258 sizeof(voice_stack), CREATE_THREAD_FROZEN,
3259 voice_thread_name
3260 IF_PRIO(, PRIORITY_PLAYBACK) IF_COP(, CPU));
3262 #endif
3264 /* Set crossfade setting for next buffer init which should be about... */
3265 pcmbuf_crossfade_enable(global_settings.crossfade);
3267 /* initialize the buffering system */
3269 buffering_init();
3270 /* ...now! Set up the buffers */
3271 audio_reset_buffer();
3273 /* Probably safe to say */
3274 audio_is_initialized = true;
3276 sound_settings_apply();
3277 #ifdef HAVE_WM8758
3278 eq_hw_enable(global_settings.eq_hw_enabled);
3279 #endif
3280 #ifndef HAVE_FLASH_STORAGE
3281 audio_set_buffer_margin(global_settings.buffer_margin);
3282 #endif
3284 /* it's safe to let the threads run now */
3285 thread_thaw(codec_thread_p);
3286 #ifdef PLAYBACK_VOICE
3287 if (voice_thread_p)
3288 thread_thaw(voice_thread_p);
3289 #endif
3290 thread_thaw(audio_thread_p);
3291 } /* audio_init */