Crossfade: added a new option, rewrote decision logic, updated manual and menus....
[kugel-rb.git] / apps / playback.c
blob57aca136a1a081cefef4a97b9e09b10ae029aa95
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005-2007 Miika Pekkarinen
11 * Copyright (C) 2007-2008 Nicolas Pennequin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
24 * play whilst audio is paused */
26 #include <string.h>
27 #include "playback.h"
28 #include "codec_thread.h"
29 #include "kernel.h"
30 #include "codecs.h"
31 #include "buffering.h"
32 #include "voice_thread.h"
33 #include "usb.h"
34 #include "ata.h"
35 #include "playlist.h"
36 #include "pcmbuf.h"
37 #include "buffer.h"
38 #include "cuesheet.h"
39 #ifdef HAVE_TAGCACHE
40 #include "tagcache.h"
41 #endif
42 #ifdef HAVE_LCD_BITMAP
43 #ifdef HAVE_ALBUMART
44 #include "albumart.h"
45 #endif
46 #endif
47 #include "sound.h"
48 #include "metadata.h"
49 #include "splash.h"
50 #include "talk.h"
52 #ifdef HAVE_RECORDING
53 #include "pcm_record.h"
54 #endif
56 #define PLAYBACK_VOICE
58 /* amount of guess-space to allow for codecs that must hunt and peck
59 * for their correct seeek target, 32k seems a good size */
60 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
62 /* Define LOGF_ENABLE to enable logf output in this file */
63 /*#define LOGF_ENABLE*/
64 #include "logf.h"
66 /* macros to enable logf for queues
67 logging on SYS_TIMEOUT can be disabled */
68 #ifdef SIMULATOR
69 /* Define this for logf output of all queuing except SYS_TIMEOUT */
70 #define PLAYBACK_LOGQUEUES
71 /* Define this to logf SYS_TIMEOUT messages */
72 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
73 #endif
75 #ifdef PLAYBACK_LOGQUEUES
76 #define LOGFQUEUE logf
77 #else
78 #define LOGFQUEUE(...)
79 #endif
81 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
82 #define LOGFQUEUE_SYS_TIMEOUT logf
83 #else
84 #define LOGFQUEUE_SYS_TIMEOUT(...)
85 #endif
88 static enum filling_state {
89 STATE_IDLE, /* audio is stopped: nothing to do */
90 STATE_FILLING, /* adding tracks to the buffer */
91 STATE_FULL, /* can't add any more tracks */
92 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
93 STATE_FINISHED, /* all remaining tracks are fully buffered */
94 } filling;
96 /* As defined in plugins/lib/xxx2wav.h */
97 #define GUARD_BUFSIZE (32*1024)
99 bool audio_is_initialized = false;
100 static bool audio_thread_ready SHAREDBSS_ATTR = false;
102 /* Variables are commented with the threads that use them: *
103 * A=audio, C=codec, V=voice. A suffix of - indicates that *
104 * the variable is read but not updated on that thread. */
105 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
107 /* Main state control */
108 static volatile bool playing SHAREDBSS_ATTR = false;/* Is audio playing? (A) */
109 static volatile bool paused SHAREDBSS_ATTR = false; /* Is audio paused? (A/C-) */
110 extern volatile bool audio_codec_loaded; /* Codec loaded? (C/A-) */
112 /* Ring buffer where compressed audio and codecs are loaded */
113 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
114 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
115 static size_t filebuflen = 0; /* Size of buffer (A/C-) */
116 /* FIXME: make buf_ridx (C/A-) */
118 /* Possible arrangements of the buffer */
119 static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
121 /* These are used to store the current and next (or prev if the current is the last)
122 * mp3entry's in a round-robin system. This guarentees that the pointer returned
123 * by audio_current/next_track will be valid for the full duration of the
124 * currently playing track */
125 static struct mp3entry mp3entry_buf[2];
126 struct mp3entry *thistrack_id3, /* the currently playing track */
127 *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
128 * next track otherwise */
129 static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
131 /* for cuesheet support */
132 static struct cuesheet *curr_cue = NULL;
135 #define MAX_MULTIPLE_AA 2
137 #ifdef HAVE_ALBUMART
138 static struct albumart_slot {
139 struct dim dim; /* holds width, height of the albumart */
140 int used; /* counter, increments if something uses it */
141 } albumart_slots[MAX_MULTIPLE_AA];
143 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
144 #endif
147 #define MAX_TRACK 128
148 #define MAX_TRACK_MASK (MAX_TRACK-1)
150 /* Track info structure about songs in the file buffer (A/C-) */
151 static struct track_info {
152 int audio_hid; /* The ID for the track's buffer handle */
153 int id3_hid; /* The ID for the track's metadata handle */
154 int codec_hid; /* The ID for the track's codec handle */
155 #ifdef HAVE_ALBUMART
156 int aa_hid[MAX_MULTIPLE_AA];/* The ID for the track's album art handle */
157 #endif
158 int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */
160 size_t filesize; /* File total length */
162 bool taginfo_ready; /* Is metadata read */
164 } tracks[MAX_TRACK];
166 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
167 static int track_widx = 0; /* Track being buffered (A) */
168 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
170 static struct track_info *prev_ti = NULL; /* Pointer to the previously played
171 track */
173 /* Information used only for filling the buffer */
174 /* Playlist steps from playing track to next track to be buffered (A) */
175 static int last_peek_offset = 0;
177 /* Scrobbler support */
178 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
180 /* Track change controls */
181 bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
182 extern bool track_transition; /* Are we in a track transition? */
183 static bool dir_skip = false; /* Is a directory skip pending? (A) */
184 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
185 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
186 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
188 static bool start_play_g = false; /* Used by audio_load_track to notify
189 audio_finish_load_track about start_play */
191 /* True when a track load is in progress, i.e. audio_load_track() has returned
192 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
193 * audio_load_track() to get called twice in a row, which would cause problems.
195 static bool track_load_started = false;
197 #ifdef HAVE_DISK_STORAGE
198 static size_t buffer_margin = 5; /* Buffer margin aka anti-skip buffer (A/C-) */
199 #endif
201 /* Event queues */
202 struct event_queue audio_queue SHAREDBSS_ATTR;
203 struct event_queue codec_queue SHAREDBSS_ATTR;
204 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR;
206 extern struct codec_api ci;
207 extern unsigned int codec_thread_id;
209 /* Multiple threads */
210 /* Set the watermark to trigger buffer fill (A/C) */
211 static void set_filebuf_watermark(void);
213 /* Audio thread */
214 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
215 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
216 static const char audio_thread_name[] = "audio";
218 static void audio_thread(void);
219 static void audio_initiate_track_change(long direction);
220 static bool audio_have_tracks(void);
221 static void audio_reset_buffer(void);
222 static void audio_stop_playback(void);
225 /**************************************/
227 /* Between the codec and PCM track change, we need to keep updating the
228 "elapsed" value of the previous (to the codec, but current to the
229 user/PCM/WPS) track, so that the progressbar reaches the end.
230 During that transition, the WPS will display othertrack_id3. */
231 void audio_pcmbuf_position_callback(size_t size)
233 /* This is called from an ISR, so be quick */
234 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
235 othertrack_id3->elapsed;
237 if (time >= othertrack_id3->length)
239 /* we just played the end of the track, so stop this callback */
240 track_transition = false;
241 othertrack_id3->elapsed = othertrack_id3->length;
243 else
244 othertrack_id3->elapsed = time;
247 /* Post message from pcmbuf that the end of the previous track
248 * has just been played. */
249 void audio_post_track_change(bool pcmbuf)
251 if (pcmbuf)
253 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
254 queue_post(&pcmbuf_queue, Q_AUDIO_TRACK_CHANGED, 0);
256 else
258 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
259 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
263 /* Scan the pcmbuf queue and return true if a message pulled.
264 * Permissible Context(s): Thread
266 static bool pcmbuf_queue_scan(struct queue_event *ev)
268 if (!queue_empty(&pcmbuf_queue))
270 /* Transfer message to audio queue */
271 pcm_play_lock();
272 /* Pull message - never, ever any blocking call! */
273 queue_wait_w_tmo(&pcmbuf_queue, ev, 0);
274 pcm_play_unlock();
275 return true;
278 return false;
281 /* --- Helper functions --- */
283 static struct mp3entry *bufgetid3(int handle_id)
285 if (handle_id < 0)
286 return NULL;
288 struct mp3entry *id3;
289 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
291 if (ret < 0 || ret != sizeof(struct mp3entry))
292 return NULL;
294 return id3;
297 static bool clear_track_info(struct track_info *track)
299 /* bufclose returns true if the handle is not found, or if it is closed
300 * successfully, so these checks are safe on non-existant handles */
301 if (!track)
302 return false;
304 if (track->codec_hid >= 0) {
305 if (bufclose(track->codec_hid))
306 track->codec_hid = -1;
307 else
308 return false;
311 if (track->id3_hid >= 0) {
312 if (bufclose(track->id3_hid))
313 track->id3_hid = -1;
314 else
315 return false;
318 if (track->audio_hid >= 0) {
319 if (bufclose(track->audio_hid))
320 track->audio_hid = -1;
321 else
322 return false;
325 #ifdef HAVE_ALBUMART
327 int i;
328 FOREACH_ALBUMART(i)
330 if (track->aa_hid[i] >= 0) {
331 if (bufclose(track->aa_hid[i]))
332 track->aa_hid[i] = -1;
333 else
334 return false;
338 #endif
340 if (track->cuesheet_hid >= 0) {
341 if (bufclose(track->cuesheet_hid))
342 track->cuesheet_hid = -1;
343 else
344 return false;
347 track->filesize = 0;
348 track->taginfo_ready = false;
350 return true;
353 /* --- External interfaces --- */
355 /* This sends a stop message and the audio thread will dump all it's
356 subsequenct messages */
357 void audio_hard_stop(void)
359 /* Stop playback */
360 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
361 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
362 #ifdef PLAYBACK_VOICE
363 voice_stop();
364 #endif
367 bool audio_restore_playback(int type)
369 switch (type)
371 case AUDIO_WANT_PLAYBACK:
372 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
373 audio_reset_buffer();
374 return true;
375 case AUDIO_WANT_VOICE:
376 if (buffer_state == AUDIOBUF_STATE_TRASHED)
377 audio_reset_buffer();
378 return true;
379 default:
380 return false;
384 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
386 unsigned char *buf, *end;
388 if (audio_is_initialized)
390 audio_hard_stop();
392 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
394 /* Reset the buffering thread so that it doesn't try to use the data */
395 buffering_reset(filebuf, filebuflen);
397 if (buffer_size == NULL)
399 /* Special case for talk_init to use since it already knows it's
400 trashed */
401 buffer_state = AUDIOBUF_STATE_TRASHED;
402 return NULL;
405 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
406 || !talk_voice_required())
408 logf("get buffer: talk, audio");
409 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
410 the talk buffer is not needed because voice isn't being used, or
411 could be AUDIOBUF_STATE_TRASHED already. If state is
412 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
413 without the caller knowing what's going on. Changing certain settings
414 may move it to a worse condition but the memory in use by something
415 else will remain undisturbed.
417 if (buffer_state != AUDIOBUF_STATE_TRASHED)
419 talk_buffer_steal();
420 buffer_state = AUDIOBUF_STATE_TRASHED;
423 buf = audiobuf;
424 end = audiobufend;
426 else
428 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
429 still AUDIOBUF_STATE_INITIALIZED */
430 /* Skip talk buffer and move pcm buffer to end to maximize available
431 contiguous memory - no audio running means voice will not need the
432 swap space */
433 logf("get buffer: audio");
434 buf = audiobuf + talk_get_bufsize();
435 end = audiobufend - pcmbuf_init(audiobufend);
436 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
439 *buffer_size = end - buf;
441 return buf;
444 int audio_buffer_state(void)
446 return buffer_state;
449 #ifdef HAVE_RECORDING
450 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
452 /* Stop audio, voice and obtain all available buffer space */
453 audio_hard_stop();
454 talk_buffer_steal();
456 unsigned char *end = audiobufend;
457 buffer_state = AUDIOBUF_STATE_TRASHED;
458 *buffer_size = end - audiobuf;
460 return (unsigned char *)audiobuf;
463 bool audio_load_encoder(int afmt)
465 #ifndef SIMULATOR
466 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
467 if (!enc_fn)
468 return false;
470 audio_remove_encoder();
471 ci.enc_codec_loaded = 0; /* clear any previous error condition */
473 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
474 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
476 while (ci.enc_codec_loaded == 0)
477 yield();
479 logf("codec loaded: %d", ci.enc_codec_loaded);
481 return ci.enc_codec_loaded > 0;
482 #else
483 (void)afmt;
484 return true;
485 #endif
486 } /* audio_load_encoder */
488 void audio_remove_encoder(void)
490 #ifndef SIMULATOR
491 /* force encoder codec unload (if currently loaded) */
492 if (ci.enc_codec_loaded <= 0)
493 return;
495 ci.stop_encoder = true;
496 while (ci.enc_codec_loaded > 0)
497 yield();
498 #endif
499 } /* audio_remove_encoder */
501 #endif /* HAVE_RECORDING */
504 struct mp3entry* audio_current_track(void)
506 const char *filename;
507 struct playlist_track_info trackinfo;
508 int cur_idx;
509 int offset = ci.new_track + wps_offset;
510 struct mp3entry *write_id3;
512 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
514 if (cur_idx == track_ridx && *thistrack_id3->path)
516 /* The usual case */
517 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
519 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
520 thistrack_id3->cuesheet = curr_cue;
521 cue_spoof_id3(thistrack_id3->cuesheet, thistrack_id3);
523 return thistrack_id3;
525 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
527 /* We're in a track transition. The codec has moved on to the next track,
528 but the audio being played is still the same (now previous) track.
529 othertrack_id3.elapsed is being updated in an ISR by
530 codec_pcmbuf_position_callback */
531 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
533 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
534 othertrack_id3->cuesheet = curr_cue;
535 cue_spoof_id3(othertrack_id3->cuesheet, othertrack_id3);
537 return othertrack_id3;
540 if (offset != 0)
542 /* Codec may be using thistrack_id3, so it must not be overwritten.
543 If this is a manual skip, othertrack_id3 will become
544 thistrack_id3 in audio_check_new_track().
545 FIXME: If this is an automatic skip, it probably means multiple
546 short tracks fit in the PCM buffer. Overwriting othertrack_id3
547 can lead to an incorrect value later.
548 Note that othertrack_id3 may also be used for next track.
550 write_id3 = othertrack_id3;
552 else
554 write_id3 = thistrack_id3;
557 if (tracks[cur_idx].id3_hid >= 0)
559 /* The current track's info has been buffered but not read yet, so get it */
560 if (bufread(tracks[cur_idx].id3_hid, sizeof(struct mp3entry), write_id3)
561 == sizeof(struct mp3entry))
562 return write_id3;
565 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
566 we have and return that. */
568 memset(write_id3, 0, sizeof(struct mp3entry));
570 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo);
571 filename = trackinfo.filename;
572 if (!filename)
573 filename = "No file!";
575 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
576 if (tagcache_fill_tags(write_id3, filename))
577 return write_id3;
578 #endif
580 strlcpy(write_id3->path, filename, sizeof(write_id3->path));
581 write_id3->title = strrchr(write_id3->path, '/');
582 if (!write_id3->title)
583 write_id3->title = &write_id3->path[0];
584 else
585 write_id3->title++;
587 return write_id3;
590 struct mp3entry* audio_next_track(void)
592 int next_idx;
593 int offset = ci.new_track + wps_offset;
595 if (!audio_have_tracks())
596 return NULL;
598 if (wps_offset == -1 && *thistrack_id3->path)
600 /* We're in a track transition. The next track for the WPS is the one
601 currently being decoded. */
602 return thistrack_id3;
605 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
607 if (tracks[next_idx].id3_hid >= 0)
609 if (bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), othertrack_id3)
610 == sizeof(struct mp3entry))
611 return othertrack_id3;
612 else
613 return NULL;
616 if (next_idx == track_widx)
618 /* The next track hasn't been buffered yet, so we return the static
619 version of its metadata. */
620 return &unbuffered_id3;
623 return NULL;
626 #ifdef HAVE_ALBUMART
627 int playback_current_aa_hid(int slot)
629 if (slot < 0)
630 return -1;
631 int cur_idx;
632 int offset = ci.new_track + wps_offset;
634 cur_idx = track_ridx + offset;
635 cur_idx &= MAX_TRACK_MASK;
637 return tracks[cur_idx].aa_hid[slot];
640 int playback_claim_aa_slot(struct dim *dim)
642 int i;
643 /* first try to find a slot already having the size to reuse it
644 * since we don't want albumart of the same size buffered multiple times */
645 FOREACH_ALBUMART(i)
647 struct albumart_slot *slot = &albumart_slots[i];
648 if (slot->dim.width == dim->width
649 && slot->dim.height == dim->height)
651 slot->used++;
652 return i;
655 /* size is new, find a free slot */
656 FOREACH_ALBUMART(i)
658 if (!albumart_slots[i].used)
660 albumart_slots[i].used++;
661 albumart_slots[i].dim = *dim;
662 return i;
665 /* sorry, no free slot */
666 return -1;
669 void playback_release_aa_slot(int slot)
671 /* invalidate the albumart_slot */
672 struct albumart_slot *aa_slot = &albumart_slots[slot];
673 if (aa_slot->used > 0)
674 aa_slot->used--;
677 #endif
678 void audio_play(long offset)
680 logf("audio_play");
682 #ifdef PLAYBACK_VOICE
683 /* Truncate any existing voice output so we don't have spelling
684 * etc. over the first part of the played track */
685 talk_force_shutup();
686 #endif
688 /* Start playback */
689 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
690 /* Don't return until playback has actually started */
691 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
694 void audio_stop(void)
696 /* Stop playback */
697 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
698 /* Don't return until playback has actually stopped */
699 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
702 void audio_pause(void)
704 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
705 /* Don't return until playback has actually paused */
706 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
709 void audio_resume(void)
711 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
712 /* Don't return until playback has actually resumed */
713 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
716 void audio_skip(int direction)
718 if (playlist_check(ci.new_track + wps_offset + direction))
720 if (global_settings.beep)
721 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
723 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction);
724 queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
725 /* Update wps while our message travels inside deep playback queues. */
726 wps_offset += direction;
728 else
730 /* No more tracks. */
731 if (global_settings.beep)
732 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
736 void audio_next(void)
738 audio_skip(1);
741 void audio_prev(void)
743 audio_skip(-1);
746 void audio_next_dir(void)
748 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
749 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
752 void audio_prev_dir(void)
754 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
755 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
758 void audio_pre_ff_rewind(void)
760 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
761 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
764 void audio_ff_rewind(long newpos)
766 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
767 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
770 void audio_flush_and_reload_tracks(void)
772 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
773 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
776 void audio_error_clear(void)
778 #ifdef AUDIO_HAVE_RECORDING
779 pcm_rec_error_clear();
780 #endif
783 int audio_status(void)
785 int ret = 0;
787 if (playing)
788 ret |= AUDIO_STATUS_PLAY;
790 if (paused)
791 ret |= AUDIO_STATUS_PAUSE;
793 #ifdef HAVE_RECORDING
794 /* Do this here for constitency with mpeg.c version */
795 /* FIXME: pcm_rec_status() is deprecated */
796 ret |= pcm_rec_status();
797 #endif
799 return ret;
802 int audio_get_file_pos(void)
804 return 0;
807 #ifdef HAVE_DISK_STORAGE
808 void audio_set_buffer_margin(int setting)
810 static const unsigned short lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
811 buffer_margin = lookup[setting];
812 logf("buffer margin: %ld", (long)buffer_margin);
813 set_filebuf_watermark();
815 #endif
817 #ifdef HAVE_CROSSFADE
818 /* Take necessary steps to enable or disable the crossfade setting */
819 void audio_set_crossfade(int enable)
821 size_t offset;
822 bool was_playing;
823 size_t size;
825 /* Tell it the next setting to use */
826 pcmbuf_request_crossfade_enable(enable);
828 /* Return if size hasn't changed or this is too early to determine
829 which in the second case there's no way we could be playing
830 anything at all */
831 if (pcmbuf_is_same_size()) return;
833 offset = 0;
834 was_playing = playing;
836 /* Playback has to be stopped before changing the buffer size */
837 if (was_playing)
839 /* Store the track resume position */
840 offset = thistrack_id3->offset;
843 /* Blast it - audio buffer will have to be setup again next time
844 something plays */
845 audio_get_buffer(true, &size);
847 /* Restart playback if audio was running previously */
848 if (was_playing)
849 audio_play(offset);
851 #endif
853 /* --- Routines called from multiple threads --- */
855 static void set_filebuf_watermark(void)
857 if (!filebuf)
858 return; /* Audio buffers not yet set up */
860 #ifdef HAVE_DISK_STORAGE
861 int seconds;
862 int spinup = ata_spinup_time();
863 if (spinup)
864 seconds = (spinup / HZ) + 1;
865 else
866 seconds = 5;
868 seconds += buffer_margin;
869 #else
870 /* flash storage */
871 int seconds = 1;
872 #endif
874 /* bitrate of last track in buffer dictates watermark */
875 struct mp3entry* id3 = NULL;
876 if (tracks[track_widx].taginfo_ready)
877 id3 = bufgetid3(tracks[track_widx].id3_hid);
878 else
879 id3 = bufgetid3(tracks[track_widx-1].id3_hid);
880 if (!id3) {
881 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
882 return;
884 size_t bytes = id3->bitrate * (1000/8) * seconds;
885 buf_set_watermark(bytes);
886 logf("fwmark: %d", bytes);
889 /* --- Buffering callbacks --- */
891 static void buffering_low_buffer_callback(void *data)
893 (void)data;
894 logf("low buffer callback");
896 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) {
897 /* force a refill */
898 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
899 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
903 static void buffering_handle_rebuffer_callback(void *data)
905 (void)data;
906 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
907 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
910 static void buffering_handle_finished_callback(void *data)
912 logf("handle %d finished buffering", *(int*)data);
913 int hid = (*(int*)data);
915 if (hid == tracks[track_widx].id3_hid)
917 int offset = ci.new_track + wps_offset;
918 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
919 /* The metadata handle for the last loaded track has been buffered.
920 We can ask the audio thread to load the rest of the track's data. */
921 LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
922 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
923 if (tracks[next_idx].id3_hid == hid)
924 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
926 else
928 /* This is most likely an audio handle, so we strip the useless
929 trailing tags that are left. */
930 strip_tags(hid);
932 if (hid == tracks[track_widx-1].audio_hid
933 && filling == STATE_END_OF_PLAYLIST)
935 /* This was the last track in the playlist.
936 We now have all the data we need. */
937 logf("last track finished buffering");
938 filling = STATE_FINISHED;
944 /* --- Audio thread --- */
946 static bool audio_have_tracks(void)
948 return (audio_track_count() != 0);
951 static int audio_free_track_count(void)
953 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
954 return MAX_TRACK - 1 - audio_track_count();
957 int audio_track_count(void)
959 /* Calculate difference from track_ridx to track_widx
960 * taking into account a possible wrap-around. */
961 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK;
964 long audio_filebufused(void)
966 return (long) buf_used();
969 /* Update track info after successful a codec track change */
970 static void audio_update_trackinfo(void)
972 /* Load the curent track's metadata into curtrack_id3 */
973 if (CUR_TI->id3_hid >= 0)
974 copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid));
976 /* Reset current position */
977 thistrack_id3->elapsed = 0;
978 thistrack_id3->offset = 0;
980 /* Update the codec API */
981 ci.filesize = CUR_TI->filesize;
982 ci.id3 = thistrack_id3;
983 ci.curpos = 0;
984 ci.taginfo_ready = &CUR_TI->taginfo_ready;
987 /* Clear tracks between write and read, non inclusive */
988 static void audio_clear_track_entries(void)
990 int cur_idx = track_widx;
992 logf("Clearing tracks: r%d/w%d", track_ridx, track_widx);
994 /* Loop over all tracks from write-to-read */
995 while (1)
997 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
999 if (cur_idx == track_ridx)
1000 break;
1002 clear_track_info(&tracks[cur_idx]);
1006 /* Clear all tracks */
1007 static bool audio_release_tracks(void)
1009 int i, cur_idx;
1011 logf("releasing all tracks");
1013 for(i = 0; i < MAX_TRACK; i++)
1015 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
1016 if (!clear_track_info(&tracks[cur_idx]))
1017 return false;
1020 return true;
1023 static bool audio_loadcodec(bool start_play)
1025 int prev_track;
1026 char codec_path[MAX_PATH]; /* Full path to codec */
1027 const struct mp3entry *id3, *prev_id3;
1029 if (tracks[track_widx].id3_hid < 0) {
1030 return false;
1033 id3 = bufgetid3(tracks[track_widx].id3_hid);
1034 if (!id3)
1035 return false;
1037 const char *codec_fn = get_codec_filename(id3->codectype);
1038 if (codec_fn == NULL)
1039 return false;
1041 tracks[track_widx].codec_hid = -1;
1043 if (start_play)
1045 /* Load the codec directly from disk and save some memory. */
1046 track_ridx = track_widx;
1047 ci.filesize = CUR_TI->filesize;
1048 ci.id3 = thistrack_id3;
1049 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1050 ci.curpos = 0;
1051 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1052 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
1053 return true;
1055 else
1057 /* If we already have another track than this one buffered */
1058 if (track_widx != track_ridx)
1060 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1062 id3 = bufgetid3(tracks[track_widx].id3_hid);
1063 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1065 /* If the previous codec is the same as this one, there is no need
1066 * to put another copy of it on the file buffer */
1067 if (id3 && prev_id3 &&
1068 get_codec_base_type(id3->codectype) ==
1069 get_codec_base_type(prev_id3->codectype)
1070 && audio_codec_loaded)
1072 logf("Reusing prev. codec");
1073 return true;
1078 codec_get_full_path(codec_path, codec_fn);
1080 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1081 if (tracks[track_widx].codec_hid < 0)
1082 return false;
1084 logf("Loaded codec");
1086 return true;
1089 /* Load metadata for the next track (with bufopen). The rest of the track
1090 loading will be handled by audio_finish_load_track once the metadata has been
1091 actually loaded by the buffering thread. */
1092 static bool audio_load_track(size_t offset, bool start_play)
1094 const char *trackname;
1095 int fd = -1;
1097 if (track_load_started) {
1098 /* There is already a track load in progress, so track_widx hasn't been
1099 incremented yet. Loading another track would overwrite the one that
1100 hasn't finished loading. */
1101 logf("audio_load_track(): a track load is already in progress");
1102 return false;
1105 start_play_g = start_play; /* will be read by audio_finish_load_track */
1107 /* Stop buffer filling if there is no free track entries.
1108 Don't fill up the last track entry (we wan't to store next track
1109 metadata there). */
1110 if (!audio_free_track_count())
1112 logf("No free tracks");
1113 return false;
1116 last_peek_offset++;
1117 tracks[track_widx].taginfo_ready = false;
1119 logf("Buffering track: r%d/w%d", track_ridx, track_widx);
1120 /* Get track name from current playlist read position. */
1121 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
1123 /* Handle broken playlists. */
1124 fd = open(trackname, O_RDONLY);
1125 if (fd < 0)
1127 logf("Open failed");
1128 /* Skip invalid entry from playlist. */
1129 playlist_skip_entry(NULL, last_peek_offset);
1131 else
1132 break;
1135 if (!trackname)
1137 logf("End-of-playlist");
1138 memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
1139 filling = STATE_END_OF_PLAYLIST;
1141 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
1143 /* Stop playback if no valid track was found. */
1144 audio_stop_playback();
1147 return false;
1150 tracks[track_widx].filesize = filesize(fd);
1152 if (offset > tracks[track_widx].filesize)
1153 offset = 0;
1155 /* Set default values */
1156 if (start_play)
1158 buf_set_watermark(filebuflen/2);
1159 dsp_configure(ci.dsp, DSP_RESET, 0);
1160 playlist_update_resume_info(audio_current_track());
1163 /* Get track metadata if we don't already have it. */
1164 if (tracks[track_widx].id3_hid < 0)
1166 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL);
1168 if (tracks[track_widx].id3_hid < 0)
1170 /* Buffer is full. */
1171 get_metadata(&unbuffered_id3, fd, trackname);
1172 last_peek_offset--;
1173 close(fd);
1174 logf("buffer is full for now (get metadata)");
1175 filling = STATE_FULL;
1176 return false;
1179 if (track_widx == track_ridx)
1181 /* TODO: Superfluos buffering call? */
1182 buf_request_buffer_handle(tracks[track_widx].id3_hid);
1183 struct mp3entry *id3 = bufgetid3(tracks[track_widx].id3_hid);
1184 if (id3)
1186 copy_mp3entry(thistrack_id3, id3);
1187 thistrack_id3->offset = offset;
1189 else
1190 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1193 if (start_play)
1195 playlist_update_resume_info(audio_current_track());
1199 close(fd);
1200 track_load_started = true; /* Remember that we've started loading a track */
1201 return true;
1204 /* Second part of the track loading: We now have the metadata available, so we
1205 can load the codec, the album art and finally the audio data.
1206 This is called on the audio thread after the buffering thread calls the
1207 buffering_handle_finished_callback callback. */
1208 static void audio_finish_load_track(void)
1210 size_t file_offset = 0;
1211 size_t offset = 0;
1212 bool start_play = start_play_g;
1214 track_load_started = false;
1216 if (tracks[track_widx].id3_hid < 0) {
1217 logf("No metadata");
1218 return;
1221 struct mp3entry *track_id3;
1223 if (track_widx == track_ridx)
1224 track_id3 = thistrack_id3;
1225 else
1226 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
1228 if (track_id3->length == 0 && track_id3->filesize == 0)
1230 logf("audio_finish_load_track: invalid metadata");
1232 /* Invalid metadata */
1233 bufclose(tracks[track_widx].id3_hid);
1234 tracks[track_widx].id3_hid = -1;
1236 /* Skip invalid entry from playlist. */
1237 playlist_skip_entry(NULL, last_peek_offset--);
1239 /* load next track */
1240 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play);
1241 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1243 return;
1245 /* Try to load a cuesheet for the track */
1246 if (curr_cue)
1248 char cuepath[MAX_PATH];
1249 if (look_for_cuesheet_file(track_id3->path, cuepath))
1251 void *temp;
1252 tracks[track_widx].cuesheet_hid =
1253 bufalloc(NULL, sizeof(struct cuesheet), TYPE_CUESHEET);
1254 if (tracks[track_widx].cuesheet_hid >= 0)
1256 bufgetdata(tracks[track_widx].cuesheet_hid,
1257 sizeof(struct cuesheet), &temp);
1258 struct cuesheet *cuesheet = (struct cuesheet*)temp;
1259 if (!parse_cuesheet(cuepath, cuesheet))
1261 bufclose(tracks[track_widx].cuesheet_hid);
1262 track_id3->cuesheet = NULL;
1267 #ifdef HAVE_ALBUMART
1269 int i;
1270 char aa_path[MAX_PATH];
1271 FOREACH_ALBUMART(i)
1273 /* albumart_slots may change during a yield of bufopen,
1274 * but that's no problem */
1275 if (tracks[track_widx].aa_hid[i] >= 0 || !albumart_slots[i].used)
1276 continue;
1277 /* find_albumart will error out if the wps doesn't have AA */
1278 if (find_albumart(track_id3, aa_path, sizeof(aa_path),
1279 &(albumart_slots[i].dim)))
1281 int aa_hid = bufopen(aa_path, 0, TYPE_BITMAP,
1282 &(albumart_slots[i].dim));
1284 if(aa_hid == ERR_BUFFER_FULL)
1286 filling = STATE_FULL;
1287 logf("buffer is full for now (get album art)");
1288 return; /* No space for track's album art, not an error */
1290 else if (aa_hid < 0)
1292 /* another error, ignore AlbumArt */
1293 logf("Album art loading failed");
1295 tracks[track_widx].aa_hid[i] = aa_hid;
1300 #endif
1302 /* Load the codec. */
1303 if (!audio_loadcodec(start_play))
1305 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1307 /* No space for codec on buffer, not an error */
1308 filling = STATE_FULL;
1309 return;
1312 /* This is an error condition, either no codec was found, or reading
1313 * the codec file failed part way through, either way, skip the track */
1314 /* FIXME: We should not use splashf from audio thread! */
1315 splashf(HZ*2, "No codec for: %s", track_id3->path);
1316 /* Skip invalid entry from playlist. */
1317 playlist_skip_entry(NULL, last_peek_offset);
1318 return;
1321 track_id3->elapsed = 0;
1322 offset = track_id3->offset;
1324 enum data_type type = TYPE_PACKET_AUDIO;
1326 switch (track_id3->codectype) {
1327 case AFMT_MPA_L1:
1328 case AFMT_MPA_L2:
1329 case AFMT_MPA_L3:
1330 if (offset > 0) {
1331 file_offset = offset;
1332 track_id3->offset = offset;
1334 break;
1336 case AFMT_WAVPACK:
1337 if (offset > 0) {
1338 file_offset = offset;
1339 track_id3->offset = offset;
1340 track_id3->elapsed = track_id3->length / 2;
1342 break;
1344 case AFMT_OGG_VORBIS:
1345 case AFMT_SPEEX:
1346 case AFMT_FLAC:
1347 case AFMT_PCM_WAV:
1348 case AFMT_A52:
1349 case AFMT_MP4_AAC:
1350 case AFMT_MPC:
1351 case AFMT_APE:
1352 case AFMT_WMA:
1353 if (offset > 0)
1354 track_id3->offset = offset;
1355 break;
1357 case AFMT_NSF:
1358 case AFMT_SPC:
1359 case AFMT_SID:
1360 logf("Loading atomic %d",track_id3->codectype);
1361 type = TYPE_ATOMIC_AUDIO;
1362 break;
1365 logf("load track: %s", track_id3->path);
1367 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1368 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1369 else if (track_id3->first_frame_offset)
1370 file_offset = track_id3->first_frame_offset;
1371 else
1372 file_offset = 0;
1374 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type,
1375 NULL);
1377 /* No space left, not an error */
1378 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1380 filling = STATE_FULL;
1381 logf("buffer is full for now (load audio)");
1382 return;
1384 else if (tracks[track_widx].audio_hid < 0)
1386 /* another error, do not continue either */
1387 logf("Could not add audio data handle");
1388 return;
1391 /* All required data is now available for the codec. */
1392 tracks[track_widx].taginfo_ready = true;
1394 if (start_play)
1396 ci.curpos=file_offset;
1397 buf_request_buffer_handle(tracks[track_widx].audio_hid);
1400 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1402 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
1404 /* load next track */
1405 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1406 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1408 return;
1411 static void audio_fill_file_buffer(bool start_play, size_t offset)
1413 trigger_cpu_boost();
1415 /* No need to rebuffer if there are track skips pending,
1416 * however don't cancel buffering on skipping while filling. */
1417 if (ci.new_track != 0 && filling != STATE_FILLING)
1418 return;
1419 filling = STATE_FILLING;
1421 /* Must reset the buffer before use if trashed or voice only - voice
1422 file size shouldn't have changed so we can go straight from
1423 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1424 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1425 audio_reset_buffer();
1427 logf("Starting buffer fill");
1429 if (!start_play)
1430 audio_clear_track_entries();
1432 /* Save the current resume position once. */
1433 playlist_update_resume_info(audio_current_track());
1435 audio_load_track(offset, start_play);
1438 static void audio_rebuffer(void)
1440 logf("Forcing rebuffer");
1442 clear_track_info(CUR_TI);
1444 /* Reset track pointers */
1445 track_widx = track_ridx;
1446 audio_clear_track_entries();
1448 /* Reset a possibly interrupted track load */
1449 track_load_started = false;
1451 /* Fill the buffer */
1452 last_peek_offset = -1;
1453 ci.curpos = 0;
1455 if (!CUR_TI->taginfo_ready)
1456 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1458 audio_fill_file_buffer(false, 0);
1461 /* Called on request from the codec to get a new track. This is the codec part
1462 of the track transition. */
1463 static int audio_check_new_track(void)
1465 int track_count = audio_track_count();
1466 int old_track_ridx = track_ridx;
1467 int i, idx;
1468 bool forward;
1469 struct mp3entry *temp = thistrack_id3;
1471 /* Now it's good time to send track finish events. */
1472 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1473 /* swap the mp3entry pointers */
1474 thistrack_id3 = othertrack_id3;
1475 othertrack_id3 = temp;
1476 ci.id3 = thistrack_id3;
1477 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1479 if (dir_skip)
1481 dir_skip = false;
1482 /* regardless of the return value we need to rebuffer.
1483 if it fails the old playlist will resume, else the
1484 next dir will start playing */
1485 playlist_next_dir(ci.new_track);
1486 ci.new_track = 0;
1487 audio_rebuffer();
1488 goto skip_done;
1491 if (new_playlist)
1492 ci.new_track = 0;
1494 /* If the playlist isn't that big */
1495 if (automatic_skip)
1497 while (!playlist_check(ci.new_track))
1499 if (ci.new_track >= 0)
1501 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1502 return Q_CODEC_REQUEST_FAILED;
1504 ci.new_track++;
1508 /* Update the playlist */
1509 last_peek_offset -= ci.new_track;
1511 if (playlist_next(ci.new_track) < 0)
1513 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1514 return Q_CODEC_REQUEST_FAILED;
1517 if (new_playlist)
1519 ci.new_track = 1;
1520 new_playlist = false;
1523 /* Save a pointer to the old track to allow later clearing */
1524 prev_ti = CUR_TI;
1526 for (i = 0; i < ci.new_track; i++)
1528 idx = (track_ridx + i) & MAX_TRACK_MASK;
1529 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid);
1530 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid);
1531 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset)
1533 /* We don't have all the audio data for that track, so clear it,
1534 but keep the metadata. */
1535 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
1537 tracks[idx].audio_hid = -1;
1538 tracks[idx].filesize = 0;
1543 /* Move to the new track */
1544 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
1546 buf_set_base_handle(CUR_TI->audio_hid);
1548 if (automatic_skip)
1550 wps_offset = -ci.new_track;
1553 /* If it is not safe to even skip this many track entries */
1554 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
1556 ci.new_track = 0;
1557 audio_rebuffer();
1558 goto skip_done;
1561 forward = ci.new_track > 0;
1562 ci.new_track = 0;
1564 /* If the target track is clearly not in memory */
1565 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
1567 audio_rebuffer();
1568 goto skip_done;
1571 /* When skipping backwards, it is possible that we've found a track that's
1572 * buffered, but which is around the track-wrap and therefore not the track
1573 * we are looking for */
1574 if (!forward)
1576 int cur_idx = track_ridx;
1577 bool taginfo_ready = true;
1578 /* We've wrapped the buffer backwards if new > old */
1579 bool wrap = track_ridx > old_track_ridx;
1581 while (1)
1583 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1585 /* if we've advanced past the wrap when cur_idx is zeroed */
1586 if (!cur_idx)
1587 wrap = false;
1589 /* if we aren't still on the wrap and we've caught the old track */
1590 if (!(wrap || cur_idx < old_track_ridx))
1591 break;
1593 /* If we hit a track in between without valid tag info, bail */
1594 if (!tracks[cur_idx].taginfo_ready)
1596 taginfo_ready = false;
1597 break;
1600 if (!taginfo_ready)
1602 audio_rebuffer();
1606 skip_done:
1607 audio_update_trackinfo();
1608 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
1609 return Q_CODEC_REQUEST_COMPLETE;
1612 unsigned long audio_prev_elapsed(void)
1614 return prev_track_elapsed;
1617 void audio_set_prev_elapsed(unsigned long setting)
1619 prev_track_elapsed = setting;
1622 static void audio_stop_codec_flush(void)
1624 ci.stop_codec = true;
1625 pcmbuf_pause(true);
1627 while (audio_codec_loaded)
1628 yield();
1630 /* If the audio codec is not loaded any more, and the audio is still
1631 * playing, it is now and _only_ now safe to call this function from the
1632 * audio thread */
1633 if (pcm_is_playing())
1635 pcmbuf_play_stop();
1636 pcm_play_lock();
1637 queue_clear(&pcmbuf_queue);
1638 pcm_play_unlock();
1640 pcmbuf_pause(paused);
1643 static void audio_stop_playback(void)
1645 if (playing)
1647 /* If we were playing, save resume information */
1648 struct mp3entry *id3 = NULL;
1650 if (!ci.stop_codec)
1652 /* Set this early, the outside code yields and may allow the codec
1653 to try to wait for a reply on a buffer wait */
1654 ci.stop_codec = true;
1655 id3 = audio_current_track();
1658 /* Save the current playing spot, or NULL if the playlist has ended */
1659 playlist_update_resume_info(id3);
1661 /* TODO: Create auto bookmark too? */
1663 prev_track_elapsed = othertrack_id3->elapsed;
1665 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
1668 audio_stop_codec_flush();
1669 paused = false;
1670 playing = false;
1671 track_load_started = false;
1673 filling = STATE_IDLE;
1675 /* Mark all entries null. */
1676 audio_clear_track_entries();
1678 /* Close all tracks */
1679 audio_release_tracks();
1682 static void audio_play_start(size_t offset)
1684 int i;
1686 #if INPUT_SRC_CAPS != 0
1687 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1688 audio_set_output_source(AUDIO_SRC_PLAYBACK);
1689 #endif
1691 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
1692 paused = false;
1693 audio_stop_codec_flush();
1695 playing = true;
1696 track_load_started = false;
1698 ci.new_track = 0;
1699 ci.seek_time = 0;
1700 wps_offset = 0;
1702 sound_set_volume(global_settings.volume);
1703 track_widx = track_ridx = 0;
1705 /* Clear all track entries. */
1706 for (i = 0; i < MAX_TRACK; i++) {
1707 clear_track_info(&tracks[i]);
1710 last_peek_offset = -1;
1712 /* Officially playing */
1713 queue_reply(&audio_queue, 1);
1715 audio_fill_file_buffer(true, offset);
1717 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
1719 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1720 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1724 /* Invalidates all but currently playing track. */
1725 static void audio_invalidate_tracks(void)
1727 if (audio_have_tracks())
1729 last_peek_offset = 0;
1730 track_widx = track_ridx;
1732 /* Mark all other entries null (also buffered wrong metadata). */
1733 audio_clear_track_entries();
1735 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1737 audio_fill_file_buffer(false, 0);
1741 static void audio_new_playlist(void)
1743 /* Prepare to start a new fill from the beginning of the playlist */
1744 last_peek_offset = -1;
1745 if (audio_have_tracks())
1747 if (paused)
1748 skipped_during_pause = true;
1749 track_widx = track_ridx;
1750 audio_clear_track_entries();
1752 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1754 /* Mark the current track as invalid to prevent skipping back to it */
1755 CUR_TI->taginfo_ready = false;
1758 /* Signal the codec to initiate a track change forward */
1759 new_playlist = true;
1760 ci.new_track = 1;
1762 /* Officially playing */
1763 queue_reply(&audio_queue, 1);
1765 audio_fill_file_buffer(false, 0);
1768 /* Called on manual track skip */
1769 static void audio_initiate_track_change(long direction)
1771 logf("audio_initiate_track_change(%ld)", direction);
1773 ci.new_track += direction;
1774 wps_offset -= direction;
1775 if (paused)
1776 skipped_during_pause = true;
1779 /* Called on manual dir skip */
1780 static void audio_initiate_dir_change(long direction)
1782 dir_skip = true;
1783 ci.new_track = direction;
1784 if (paused)
1785 skipped_during_pause = true;
1788 /* Called when PCM track change is complete */
1789 static void audio_finalise_track_change(void)
1791 logf("audio_finalise_track_change");
1793 if (automatic_skip)
1795 wps_offset = 0;
1796 automatic_skip = false;
1798 /* Invalidate prevtrack_id3 */
1799 memset(othertrack_id3, 0, sizeof(struct mp3entry));
1801 if (prev_ti && prev_ti->audio_hid < 0)
1803 /* No audio left so we clear all the track info. */
1804 clear_track_info(prev_ti);
1807 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1808 playlist_update_resume_info(audio_current_track());
1812 * Layout audio buffer as follows - iram buffer depends on target:
1813 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
1815 static void audio_reset_buffer(void)
1817 /* see audio_get_recording_buffer if this is modified */
1818 logf("audio_reset_buffer");
1820 /* If the setup of anything allocated before the file buffer is
1821 changed, do check the adjustments after the buffer_alloc call
1822 as it will likely be affected and need sliding over */
1824 /* Initially set up file buffer as all space available */
1825 malloc_buf = audiobuf + talk_get_bufsize();
1826 /* Align the malloc buf to line size. Especially important to cf
1827 targets that do line reads/writes. */
1828 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
1829 filebuf = malloc_buf; /* filebuf line align implied */
1830 filebuflen = audiobufend - filebuf;
1832 filebuflen &= ~15;
1834 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
1835 const size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) +GUARD_BUFSIZE;
1837 #ifdef DEBUG
1838 if(pcmbuf_size > filebuflen)
1839 panicf("Not enough memory for pcmbuf_init() : %d > %d",
1840 (int)pcmbuf_size, (int)filebuflen);
1841 #endif
1843 filebuflen -= pcmbuf_size;
1845 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
1846 will already be line aligned */
1847 filebuflen &= ~3;
1849 buffering_reset(filebuf, filebuflen);
1851 /* Clear any references to the file buffer */
1852 buffer_state = AUDIOBUF_STATE_INITIALIZED;
1854 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1855 /* Make sure everything adds up - yes, some info is a bit redundant but
1856 aids viewing and the sumation of certain variables should add up to
1857 the location of others. */
1859 size_t pcmbufsize;
1860 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
1861 logf("mabuf: %08X", (unsigned)malloc_buf);
1862 logf("fbuf: %08X", (unsigned)filebuf);
1863 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
1864 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
1865 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
1866 logf("pcmb: %08X", (unsigned)pcmbuf);
1867 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
1869 #endif
1872 static void audio_thread(void)
1874 struct queue_event ev;
1876 pcm_postinit();
1878 audio_thread_ready = true;
1880 while (1)
1882 if (filling != STATE_FILLING && filling != STATE_IDLE) {
1883 /* End of buffering, let's calculate the watermark and unboost */
1884 set_filebuf_watermark();
1885 cancel_cpu_boost();
1888 if (!pcmbuf_queue_scan(&ev))
1889 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
1891 switch (ev.id) {
1893 case Q_AUDIO_FILL_BUFFER:
1894 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
1895 audio_fill_file_buffer((bool)ev.data, 0);
1896 break;
1898 case Q_AUDIO_FINISH_LOAD:
1899 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
1900 audio_finish_load_track();
1901 break;
1903 case Q_AUDIO_PLAY:
1904 LOGFQUEUE("audio < Q_AUDIO_PLAY");
1905 if (playing && ev.data <= 0)
1906 audio_new_playlist();
1907 else
1909 audio_stop_playback();
1910 audio_play_start((size_t)ev.data);
1912 break;
1914 case Q_AUDIO_STOP:
1915 LOGFQUEUE("audio < Q_AUDIO_STOP");
1916 if (playing)
1917 audio_stop_playback();
1918 if (ev.data != 0)
1919 queue_clear(&audio_queue);
1920 break;
1922 case Q_AUDIO_PAUSE:
1923 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
1924 if (!(bool) ev.data && skipped_during_pause
1925 #ifdef HAVE_CROSSFADE
1926 && !pcmbuf_is_crossfade_active()
1927 #endif
1929 pcmbuf_play_stop(); /* Flush old track on resume after skip */
1930 skipped_during_pause = false;
1931 if (!playing)
1932 break;
1933 pcmbuf_pause((bool)ev.data);
1934 paused = (bool)ev.data;
1935 break;
1937 case Q_AUDIO_SKIP:
1938 LOGFQUEUE("audio < Q_AUDIO_SKIP");
1939 audio_initiate_track_change((long)ev.data);
1940 break;
1942 case Q_AUDIO_PRE_FF_REWIND:
1943 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
1944 if (!playing)
1945 break;
1946 pcmbuf_pause(true);
1947 break;
1949 case Q_AUDIO_FF_REWIND:
1950 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
1951 if (!playing)
1952 break;
1953 if (automatic_skip)
1955 /* An automatic track skip is in progress. Finalize it,
1956 then go back to the previous track */
1957 audio_finalise_track_change();
1958 ci.new_track = -1;
1960 ci.seek_time = (long)ev.data+1;
1961 break;
1963 case Q_AUDIO_CHECK_NEW_TRACK:
1964 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
1965 queue_reply(&audio_queue, audio_check_new_track());
1966 break;
1968 case Q_AUDIO_DIR_SKIP:
1969 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
1970 audio_initiate_dir_change(ev.data);
1971 break;
1973 case Q_AUDIO_FLUSH:
1974 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
1975 audio_invalidate_tracks();
1976 break;
1978 case Q_AUDIO_TRACK_CHANGED:
1979 /* PCM track change done */
1980 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
1981 audio_finalise_track_change();
1982 break;
1983 #ifndef SIMULATOR
1984 case SYS_USB_CONNECTED:
1985 LOGFQUEUE("audio < SYS_USB_CONNECTED");
1986 if (playing)
1987 audio_stop_playback();
1988 #ifdef PLAYBACK_VOICE
1989 voice_stop();
1990 #endif
1991 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1992 usb_wait_for_disconnect(&audio_queue);
1994 /* Mark all entries null. */
1995 audio_clear_track_entries();
1997 /* release tracks to make sure all handles are closed */
1998 audio_release_tracks();
1999 break;
2000 #endif
2002 case SYS_TIMEOUT:
2003 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2004 break;
2006 default:
2007 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2008 break;
2009 } /* end switch */
2010 } /* end while */
2013 /* Initialize the audio system - called from init() in main.c.
2014 * Last function because of all the references to internal symbols
2016 void audio_init(void)
2018 unsigned int audio_thread_id;
2020 /* Can never do this twice */
2021 if (audio_is_initialized)
2023 logf("audio: already initialized");
2024 return;
2027 logf("audio: initializing");
2029 /* Initialize queues before giving control elsewhere in case it likes
2030 to send messages. Thread creation will be delayed however so nothing
2031 starts running until ready if something yields such as talk_init. */
2032 queue_init(&audio_queue, true);
2033 queue_init(&codec_queue, false);
2034 queue_init(&pcmbuf_queue, false);
2036 pcm_init();
2038 codec_init_codec_api();
2040 thistrack_id3 = &mp3entry_buf[0];
2041 othertrack_id3 = &mp3entry_buf[1];
2043 /* cuesheet support */
2044 if (global_settings.cuesheet)
2045 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2047 /* initialize the buffer */
2048 filebuf = audiobuf;
2050 /* audio_reset_buffer must to know the size of voice buffer so init
2051 talk first */
2052 talk_init();
2054 make_codec_thread();
2056 audio_thread_id = create_thread(audio_thread, audio_stack,
2057 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2058 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
2059 IF_COP(, CPU));
2061 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
2062 audio_thread_id);
2064 #ifdef PLAYBACK_VOICE
2065 voice_thread_init();
2066 #endif
2068 #ifdef HAVE_CROSSFADE
2069 /* Set crossfade setting for next buffer init which should be about... */
2070 pcmbuf_request_crossfade_enable(global_settings.crossfade);
2071 #endif
2073 /* initialize the buffering system */
2075 buffering_init();
2076 /* ...now! Set up the buffers */
2077 audio_reset_buffer();
2079 int i;
2080 for(i = 0; i < MAX_TRACK; i++)
2082 tracks[i].audio_hid = -1;
2083 tracks[i].id3_hid = -1;
2084 tracks[i].codec_hid = -1;
2085 tracks[i].cuesheet_hid = -1;
2087 #ifdef HAVE_ALBUMART
2088 FOREACH_ALBUMART(i)
2090 int j;
2091 for (j = 0; j < MAX_TRACK; j++)
2093 tracks[j].aa_hid[i] = -1;
2096 #endif
2098 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2099 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2101 /* Probably safe to say */
2102 audio_is_initialized = true;
2104 sound_settings_apply();
2105 #ifdef HAVE_DISK_STORAGE
2106 audio_set_buffer_margin(global_settings.buffer_margin);
2107 #endif
2109 /* it's safe to let the threads run now */
2110 #ifdef PLAYBACK_VOICE
2111 voice_thread_resume();
2112 #endif
2113 thread_thaw(codec_thread_id);
2114 thread_thaw(audio_thread_id);
2116 } /* audio_init */
2118 bool audio_is_thread_ready(void)
2120 return audio_thread_ready;
2123 size_t audio_get_filebuflen(void)
2125 return filebuflen;
2128 int get_audio_hid()
2130 return CUR_TI->audio_hid;
2133 int *get_codec_hid()
2135 return &tracks[track_ridx].codec_hid;