initial commit for a rework to put the fade on pause feature into the playback engine
[kugel-rb.git] / apps / playback.c
blob58e1b499f91045893aa25a5904a48eff502660cb
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 DEBUGF("\n"); DEBUGF
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 /* Define one constant that includes recording related functionality */
89 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
90 #define AUDIO_HAVE_RECORDING
91 #endif
93 enum {
94 Q_NULL = 0,
95 Q_AUDIO_PLAY = 1,
96 Q_AUDIO_STOP,
97 Q_AUDIO_PAUSE,
98 Q_AUDIO_PAUSE_W_FADE,
99 Q_AUDIO_SKIP,
100 Q_AUDIO_PRE_FF_REWIND,
101 Q_AUDIO_FF_REWIND,
102 Q_AUDIO_CHECK_NEW_TRACK,
103 Q_AUDIO_FLUSH,
104 Q_AUDIO_TRACK_CHANGED,
105 Q_AUDIO_DIR_SKIP,
106 Q_AUDIO_POSTINIT,
107 Q_AUDIO_FILL_BUFFER,
108 Q_AUDIO_FINISH_LOAD,
109 Q_CODEC_REQUEST_COMPLETE,
110 Q_CODEC_REQUEST_FAILED,
112 Q_CODEC_LOAD,
113 Q_CODEC_LOAD_DISK,
115 #ifdef AUDIO_HAVE_RECORDING
116 Q_ENCODER_LOAD_DISK,
117 Q_ENCODER_RECORD,
118 #endif
120 Q_CODEC_DO_CALLBACK,
123 static enum filling_state {
124 STATE_IDLE, /* audio is stopped: nothing to do */
125 STATE_FILLING, /* adding tracks to the buffer */
126 STATE_FULL, /* can't add any more tracks */
127 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
128 STATE_FINISHED, /* all remaining tracks are fully buffered */
129 } filling;
131 /* As defined in plugins/lib/xxx2wav.h */
132 #define GUARD_BUFSIZE (32*1024)
134 bool audio_is_initialized = false;
135 static bool audio_thread_ready SHAREDBSS_ATTR = false;
137 /* Variables are commented with the threads that use them: *
138 * A=audio, C=codec, V=voice. A suffix of - indicates that *
139 * the variable is read but not updated on that thread. */
140 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
142 /* Main state control */
143 static volatile bool playing SHAREDBSS_ATTR = false;/* Is audio playing? (A) */
144 static volatile bool paused SHAREDBSS_ATTR = false; /* Is audio paused? (A/C-) */
145 extern volatile bool audio_codec_loaded; /* Codec loaded? (C/A-) */
146 static volatile bool fading SHAREDBSS_ATTR = false; /* Is audio fading in/out? (A) */
148 /* Ring buffer where compressed audio and codecs are loaded */
149 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
150 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
151 static size_t filebuflen = 0; /* Size of buffer (A/C-) */
152 /* FIXME: make buf_ridx (C/A-) */
154 /* Possible arrangements of the buffer */
155 enum audio_buffer_state
157 AUDIOBUF_STATE_TRASHED = -1, /* trashed; must be reset */
158 AUDIOBUF_STATE_INITIALIZED = 0, /* voice+audio OR audio-only */
159 AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
161 static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
163 /* These are used to store the current and next (or prev if the current is the last)
164 * mp3entry's in a round-robin system. This guarentees that the pointer returned
165 * by audio_current/next_track will be valid for the full duration of the
166 * currently playing track */
167 static struct mp3entry mp3entry_buf[2];
168 struct mp3entry *thistrack_id3, /* the currently playing track */
169 *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
170 * next track otherwise */
171 static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
173 /* for cuesheet support */
174 static struct cuesheet *curr_cue = NULL;
177 #define MAX_MULTIPLE_AA 2
179 #ifdef HAVE_ALBUMART
180 static struct albumart_slot {
181 struct dim dim; /* holds width, height of the albumart */
182 int used; /* counter, increments if something uses it */
183 } albumart_slots[MAX_MULTIPLE_AA];
185 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
186 #endif
189 #define MAX_TRACK 128
190 #define MAX_TRACK_MASK (MAX_TRACK-1)
192 /* Track info structure about songs in the file buffer (A/C-) */
193 static struct track_info {
194 int audio_hid; /* The ID for the track's buffer handle */
195 int id3_hid; /* The ID for the track's metadata handle */
196 int codec_hid; /* The ID for the track's codec handle */
197 #ifdef HAVE_ALBUMART
198 int aa_hid[MAX_MULTIPLE_AA];/* The ID for the track's album art handle */
199 #endif
200 int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */
202 size_t filesize; /* File total length */
204 bool taginfo_ready; /* Is metadata read */
206 } tracks[MAX_TRACK];
208 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
209 static int track_widx = 0; /* Track being buffered (A) */
210 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
212 static struct track_info *prev_ti = NULL; /* Pointer to the previously played
213 track */
215 /* Information used only for filling the buffer */
216 /* Playlist steps from playing track to next track to be buffered (A) */
217 static int last_peek_offset = 0;
219 /* Scrobbler support */
220 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
222 /* Track change controls */
223 bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
224 extern bool track_transition; /* Are we in a track transition? */
225 static bool dir_skip = false; /* Is a directory skip pending? (A) */
226 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
227 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
228 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
230 static bool start_play_g = false; /* Used by audio_load_track to notify
231 audio_finish_load_track about start_play */
233 /* True when a track load is in progress, i.e. audio_load_track() has returned
234 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
235 * audio_load_track() to get called twice in a row, which would cause problems.
237 static bool track_load_started = false;
239 #ifdef HAVE_DISK_STORAGE
240 static size_t buffer_margin = 5; /* Buffer margin aka anti-skip buffer (A/C-) */
241 #endif
243 /* Event queues */
244 struct event_queue audio_queue SHAREDBSS_ATTR;
245 struct event_queue codec_queue SHAREDBSS_ATTR;
246 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR;
248 extern struct codec_api ci;
249 extern unsigned int codec_thread_id;
251 /* Multiple threads */
252 /* Set the watermark to trigger buffer fill (A/C) */
253 static void set_filebuf_watermark(void);
255 /* Audio thread */
256 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
257 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
258 static const char audio_thread_name[] = "audio";
260 static void audio_thread(void);
261 static void audio_initiate_track_change(long direction);
262 static bool audio_have_tracks(void);
263 static void audio_reset_buffer(void);
264 static void audio_stop_playback(void);
267 /**************************************/
270 /** Pcmbuf callbacks */
272 /* Between the codec and PCM track change, we need to keep updating the
273 * "elapsed" value of the previous (to the codec, but current to the
274 * user/PCM/WPS) track, so that the progressbar reaches the end.
275 * During that transition, the WPS will display othertrack_id3. */
276 void audio_pcmbuf_position_callback(unsigned int time)
278 time += othertrack_id3->elapsed;
280 if (time >= othertrack_id3->length)
282 /* we just played the end of the track, so stop this callback */
283 track_transition = false;
284 othertrack_id3->elapsed = othertrack_id3->length;
286 else
287 othertrack_id3->elapsed = time;
290 /* Post message from pcmbuf that the end of the previous track
291 * has just been played. */
292 void audio_post_track_change(bool pcmbuf)
294 if (pcmbuf)
296 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
297 queue_post(&pcmbuf_queue, Q_AUDIO_TRACK_CHANGED, 0);
299 else
301 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
302 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
306 /* Scan the pcmbuf queue and return true if a message pulled */
307 static bool pcmbuf_queue_scan(struct queue_event *ev)
309 if (!queue_empty(&pcmbuf_queue))
311 /* Transfer message to audio queue */
312 pcm_play_lock();
313 /* Pull message - never, ever any blocking call! */
314 queue_wait_w_tmo(&pcmbuf_queue, ev, 0);
315 pcm_play_unlock();
316 return true;
319 return false;
323 /** Helper functions */
325 static struct mp3entry *bufgetid3(int handle_id)
327 if (handle_id < 0)
328 return NULL;
330 struct mp3entry *id3;
331 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
333 if (ret < 0 || ret != sizeof(struct mp3entry))
334 return NULL;
336 return id3;
339 static bool clear_track_info(struct track_info *track)
341 /* bufclose returns true if the handle is not found, or if it is closed
342 * successfully, so these checks are safe on non-existant handles */
343 if (!track)
344 return false;
346 if (track->codec_hid >= 0) {
347 if (bufclose(track->codec_hid))
348 track->codec_hid = -1;
349 else
350 return false;
353 if (track->id3_hid >= 0) {
354 if (bufclose(track->id3_hid))
355 track->id3_hid = -1;
356 else
357 return false;
360 if (track->audio_hid >= 0) {
361 if (bufclose(track->audio_hid))
362 track->audio_hid = -1;
363 else
364 return false;
367 #ifdef HAVE_ALBUMART
369 int i;
370 FOREACH_ALBUMART(i)
372 if (track->aa_hid[i] >= 0) {
373 if (bufclose(track->aa_hid[i]))
374 track->aa_hid[i] = -1;
375 else
376 return false;
380 #endif
382 if (track->cuesheet_hid >= 0) {
383 if (bufclose(track->cuesheet_hid))
384 track->cuesheet_hid = -1;
385 else
386 return false;
389 track->filesize = 0;
390 track->taginfo_ready = false;
392 return true;
395 /* --- External interfaces --- */
397 /* This sends a stop message and the audio thread will dump all it's
398 subsequenct messages */
399 void audio_hard_stop(void)
401 /* Stop playback */
402 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
403 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
404 #ifdef PLAYBACK_VOICE
405 voice_stop();
406 #endif
409 bool audio_restore_playback(int type)
411 switch (type)
413 case AUDIO_WANT_PLAYBACK:
414 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
415 audio_reset_buffer();
416 return true;
417 case AUDIO_WANT_VOICE:
418 if (buffer_state == AUDIOBUF_STATE_TRASHED)
419 audio_reset_buffer();
420 return true;
421 default:
422 return false;
426 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
428 unsigned char *buf, *end;
430 if (audio_is_initialized)
432 audio_hard_stop();
434 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
436 /* Reset the buffering thread so that it doesn't try to use the data */
437 buffering_reset(filebuf, filebuflen);
439 if (buffer_size == NULL)
441 /* Special case for talk_init to use since it already knows it's
442 trashed */
443 buffer_state = AUDIOBUF_STATE_TRASHED;
444 return NULL;
447 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
448 || !talk_voice_required())
450 logf("get buffer: talk, audio");
451 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
452 the talk buffer is not needed because voice isn't being used, or
453 could be AUDIOBUF_STATE_TRASHED already. If state is
454 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
455 without the caller knowing what's going on. Changing certain settings
456 may move it to a worse condition but the memory in use by something
457 else will remain undisturbed.
459 if (buffer_state != AUDIOBUF_STATE_TRASHED)
461 talk_buffer_steal();
462 buffer_state = AUDIOBUF_STATE_TRASHED;
465 buf = audiobuf;
466 end = audiobufend;
468 else
470 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
471 still AUDIOBUF_STATE_INITIALIZED */
472 /* Skip talk buffer and move pcm buffer to end to maximize available
473 contiguous memory - no audio running means voice will not need the
474 swap space */
475 logf("get buffer: audio");
476 buf = audiobuf + talk_get_bufsize();
477 end = audiobufend - pcmbuf_init(audiobufend);
478 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
481 *buffer_size = end - buf;
483 return buf;
486 bool audio_buffer_state_trashed(void)
488 return buffer_state == AUDIOBUF_STATE_TRASHED;
491 #ifdef HAVE_RECORDING
492 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
494 /* Stop audio, voice and obtain all available buffer space */
495 audio_hard_stop();
496 talk_buffer_steal();
498 unsigned char *end = audiobufend;
499 buffer_state = AUDIOBUF_STATE_TRASHED;
500 *buffer_size = end - audiobuf;
502 return (unsigned char *)audiobuf;
505 bool audio_load_encoder(int afmt)
507 #ifndef SIMULATOR
508 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
509 if (!enc_fn)
510 return false;
512 audio_remove_encoder();
513 ci.enc_codec_loaded = 0; /* clear any previous error condition */
515 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
516 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
518 while (ci.enc_codec_loaded == 0)
519 yield();
521 logf("codec loaded: %d", ci.enc_codec_loaded);
523 return ci.enc_codec_loaded > 0;
524 #else
525 (void)afmt;
526 return true;
527 #endif
528 } /* audio_load_encoder */
530 void audio_remove_encoder(void)
532 #ifndef SIMULATOR
533 /* force encoder codec unload (if currently loaded) */
534 if (ci.enc_codec_loaded <= 0)
535 return;
537 ci.stop_encoder = true;
538 while (ci.enc_codec_loaded > 0)
539 yield();
540 #endif
541 } /* audio_remove_encoder */
543 #endif /* HAVE_RECORDING */
546 struct mp3entry* audio_current_track(void)
548 const char *filename;
549 struct playlist_track_info trackinfo;
550 int cur_idx;
551 int offset = ci.new_track + wps_offset;
552 struct mp3entry *write_id3;
554 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
556 if (cur_idx == track_ridx && *thistrack_id3->path)
558 /* The usual case */
559 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
561 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
562 thistrack_id3->cuesheet = curr_cue;
563 cue_spoof_id3(thistrack_id3->cuesheet, thistrack_id3);
565 return thistrack_id3;
567 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
569 /* We're in a track transition. The codec has moved on to the next track,
570 but the audio being played is still the same (now previous) track.
571 othertrack_id3.elapsed is being updated in an ISR by
572 codec_pcmbuf_position_callback */
573 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
575 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
576 othertrack_id3->cuesheet = curr_cue;
577 cue_spoof_id3(othertrack_id3->cuesheet, othertrack_id3);
579 return othertrack_id3;
582 if (offset != 0)
584 /* Codec may be using thistrack_id3, so it must not be overwritten.
585 If this is a manual skip, othertrack_id3 will become
586 thistrack_id3 in audio_check_new_track().
587 FIXME: If this is an automatic skip, it probably means multiple
588 short tracks fit in the PCM buffer. Overwriting othertrack_id3
589 can lead to an incorrect value later.
590 Note that othertrack_id3 may also be used for next track.
592 write_id3 = othertrack_id3;
594 else
596 write_id3 = thistrack_id3;
599 if (tracks[cur_idx].id3_hid >= 0)
601 /* The current track's info has been buffered but not read yet, so get it */
602 if (bufread(tracks[cur_idx].id3_hid, sizeof(struct mp3entry), write_id3)
603 == sizeof(struct mp3entry))
604 return write_id3;
607 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
608 we have and return that. */
610 memset(write_id3, 0, sizeof(struct mp3entry));
612 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo);
613 filename = trackinfo.filename;
614 if (!filename)
615 filename = "No file!";
617 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
618 if (tagcache_fill_tags(write_id3, filename))
619 return write_id3;
620 #endif
622 strlcpy(write_id3->path, filename, sizeof(write_id3->path));
623 write_id3->title = strrchr(write_id3->path, '/');
624 if (!write_id3->title)
625 write_id3->title = &write_id3->path[0];
626 else
627 write_id3->title++;
629 return write_id3;
632 struct mp3entry* audio_next_track(void)
634 int next_idx;
635 int offset = ci.new_track + wps_offset;
637 if (!audio_have_tracks())
638 return NULL;
640 if (wps_offset == -1 && *thistrack_id3->path)
642 /* We're in a track transition. The next track for the WPS is the one
643 currently being decoded. */
644 return thistrack_id3;
647 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
649 if (tracks[next_idx].id3_hid >= 0)
651 if (bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), othertrack_id3)
652 == sizeof(struct mp3entry))
653 return othertrack_id3;
654 else
655 return NULL;
658 if (next_idx == track_widx)
660 /* The next track hasn't been buffered yet, so we return the static
661 version of its metadata. */
662 return &unbuffered_id3;
665 return NULL;
668 /* gets a pointer to the id3 data, Not thread safe!, DON'T yield()/sleep() */
669 bool audio_peek_track(struct mp3entry** id3, int offset)
671 int next_idx;
672 int new_offset = ci.new_track + wps_offset + offset;
674 if (!audio_have_tracks())
675 return false;
676 next_idx = (track_ridx + new_offset) & MAX_TRACK_MASK;
678 if (tracks[next_idx].id3_hid >= 0)
680 return bufgetdata(tracks[next_idx].id3_hid, 0, (void**)id3)
681 == sizeof(struct mp3entry);
683 return false;
686 #ifdef HAVE_ALBUMART
687 int playback_current_aa_hid(int slot)
689 if (slot < 0)
690 return -1;
691 int cur_idx;
692 int offset = ci.new_track + wps_offset;
694 cur_idx = track_ridx + offset;
695 cur_idx &= MAX_TRACK_MASK;
697 return tracks[cur_idx].aa_hid[slot];
700 int playback_claim_aa_slot(struct dim *dim)
702 int i;
703 /* first try to find a slot already having the size to reuse it
704 * since we don't want albumart of the same size buffered multiple times */
705 FOREACH_ALBUMART(i)
707 struct albumart_slot *slot = &albumart_slots[i];
708 if (slot->dim.width == dim->width
709 && slot->dim.height == dim->height)
711 slot->used++;
712 return i;
715 /* size is new, find a free slot */
716 FOREACH_ALBUMART(i)
718 if (!albumart_slots[i].used)
720 albumart_slots[i].used++;
721 albumart_slots[i].dim = *dim;
722 return i;
725 /* sorry, no free slot */
726 return -1;
729 void playback_release_aa_slot(int slot)
731 /* invalidate the albumart_slot */
732 struct albumart_slot *aa_slot = &albumart_slots[slot];
733 if (aa_slot->used > 0)
734 aa_slot->used--;
737 #endif
738 void audio_play(long offset)
740 logf("audio_play");
742 #ifdef PLAYBACK_VOICE
743 /* Truncate any existing voice output so we don't have spelling
744 * etc. over the first part of the played track */
745 talk_force_shutup();
746 #endif
748 /* Start playback */
749 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
750 /* Don't return until playback has actually started */
751 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
754 void audio_stop(void)
756 /* Stop playback */
757 while(fading)
758 sleep(1);
759 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
760 /* Don't return until playback has actually stopped */
761 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
764 void playback_fade_on_pause(bool fade_in, void (*update_func)(void))
767 (void)update_func;
769 /* Stop playback */
770 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE_W_FADE");
771 /* Don't return until playback has actually stopped */
772 queue_post(&audio_queue, Q_AUDIO_PAUSE_W_FADE, (intptr_t)fade_in);
773 sleep(HZ/10);
776 static void handle_fade(bool fade_out)
778 int fp_global_vol = global_settings.volume << 8;
779 int fp_min_vol = sound_min(SOUND_VOLUME) << 8;
780 int fp_step = (fp_global_vol - fp_min_vol) / 30;
781 if (!fade_out) {
782 /* fade in */
783 int fp_volume = fp_min_vol;
785 /* zero out the sound */
786 sound_set_volume(fp_min_vol >> 8);
787 yield();
788 if (skipped_during_pause && !pcmbuf_is_crossfade_active())
789 pcmbuf_play_stop(); /* Flush old track on resume after skip */
790 skipped_during_pause = false;
791 pcmbuf_pause(false);
793 while (fp_volume < fp_global_vol - fp_step) {
794 fp_volume += fp_step;
795 sound_set_volume(fp_volume >> 8);
796 sleep(1);
798 sound_set_volume(global_settings.volume);
800 else {
801 /* fade out */
802 int fp_volume = fp_global_vol;
804 while (fp_volume > fp_min_vol + fp_step) {
805 fp_volume -= fp_step;
806 sound_set_volume(fp_volume >> 8);
807 sleep(1);
809 #if CONFIG_CODEC != SWCODEC
810 #ifndef SIMULATOR
811 /* let audio thread run and wait for the mas to run out of data */
812 while (!mp3_pause_done())
813 #endif
814 sleep(HZ/10);
815 #endif
817 /* reset volume to what it was before the fade */
818 sound_set_volume(global_settings.volume);
819 yield();
823 void audio_pause(void)
825 while(fading)
826 sleep(1);
827 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
828 /* Don't return until playback has actually paused */
829 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
832 void audio_resume(void)
834 while(fading)
835 sleep(1);
836 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
837 /* Don't return until playback has actually resumed */
838 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
841 void audio_skip(int direction)
843 if (playlist_check(ci.new_track + wps_offset + direction))
845 if (global_settings.beep)
846 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
848 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction);
849 queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
850 /* Update wps while our message travels inside deep playback queues. */
851 wps_offset += direction;
853 else
855 /* No more tracks. */
856 if (global_settings.beep)
857 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
861 void audio_next(void)
863 audio_skip(1);
866 void audio_prev(void)
868 audio_skip(-1);
871 void audio_next_dir(void)
873 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
874 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
877 void audio_prev_dir(void)
879 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
880 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
883 void audio_pre_ff_rewind(void)
885 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
886 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
889 void audio_ff_rewind(long newpos)
891 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
892 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
895 void audio_flush_and_reload_tracks(void)
897 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
898 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
901 void audio_error_clear(void)
903 #ifdef AUDIO_HAVE_RECORDING
904 pcm_rec_error_clear();
905 #endif
908 int audio_status(void)
910 int ret = 0;
912 if (playing)
913 ret |= AUDIO_STATUS_PLAY;
915 if (paused)
916 ret |= AUDIO_STATUS_PAUSE;
918 if (fading)
919 ret |= AUDIO_STATUS_FADING;
921 #ifdef HAVE_RECORDING
922 /* Do this here for constitency with mpeg.c version */
923 /* FIXME: pcm_rec_status() is deprecated */
924 ret |= pcm_rec_status();
925 #endif
927 return ret;
930 int audio_get_file_pos(void)
932 return 0;
935 #ifdef HAVE_DISK_STORAGE
936 void audio_set_buffer_margin(int setting)
938 static const unsigned short lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
939 buffer_margin = lookup[setting];
940 logf("buffer margin: %ld", (long)buffer_margin);
941 set_filebuf_watermark();
943 #endif
945 #ifdef HAVE_CROSSFADE
946 /* Take necessary steps to enable or disable the crossfade setting */
947 void audio_set_crossfade(int enable)
949 size_t offset;
950 bool was_playing;
951 size_t size;
953 /* Tell it the next setting to use */
954 pcmbuf_request_crossfade_enable(enable);
956 /* Return if size hasn't changed or this is too early to determine
957 which in the second case there's no way we could be playing
958 anything at all */
959 if (pcmbuf_is_same_size()) return;
961 offset = 0;
962 was_playing = playing;
964 /* Playback has to be stopped before changing the buffer size */
965 if (was_playing)
967 /* Store the track resume position */
968 offset = thistrack_id3->offset;
971 /* Blast it - audio buffer will have to be setup again next time
972 something plays */
973 audio_get_buffer(true, &size);
975 /* Restart playback if audio was running previously */
976 if (was_playing)
977 audio_play(offset);
979 #endif
981 /* --- Routines called from multiple threads --- */
983 static void set_filebuf_watermark(void)
985 if (!filebuf)
986 return; /* Audio buffers not yet set up */
988 #ifdef HAVE_DISK_STORAGE
989 int seconds;
990 int spinup = ata_spinup_time();
991 if (spinup)
992 seconds = (spinup / HZ) + 1;
993 else
994 seconds = 5;
996 seconds += buffer_margin;
997 #else
998 /* flash storage */
999 int seconds = 1;
1000 #endif
1002 /* bitrate of last track in buffer dictates watermark */
1003 struct mp3entry* id3 = NULL;
1004 if (tracks[track_widx].taginfo_ready)
1005 id3 = bufgetid3(tracks[track_widx].id3_hid);
1006 else
1007 id3 = bufgetid3(tracks[track_widx-1].id3_hid);
1008 if (!id3) {
1009 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
1010 return;
1012 size_t bytes = id3->bitrate * (1000/8) * seconds;
1013 buf_set_watermark(bytes);
1014 logf("fwmark: %d", bytes);
1017 /* --- Buffering callbacks --- */
1019 static void buffering_low_buffer_callback(void *data)
1021 (void)data;
1022 logf("low buffer callback");
1024 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) {
1025 /* force a refill */
1026 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1027 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1031 static void buffering_handle_rebuffer_callback(void *data)
1033 (void)data;
1034 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
1035 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
1038 static void buffering_handle_finished_callback(void *data)
1040 logf("handle %d finished buffering", *(int*)data);
1041 int hid = (*(int*)data);
1043 if (hid == tracks[track_widx].id3_hid)
1045 int offset = ci.new_track + wps_offset;
1046 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
1047 /* The metadata handle for the last loaded track has been buffered.
1048 We can ask the audio thread to load the rest of the track's data. */
1049 LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
1050 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
1051 if (tracks[next_idx].id3_hid == hid)
1052 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
1054 else
1056 /* This is most likely an audio handle, so we strip the useless
1057 trailing tags that are left. */
1058 strip_tags(hid);
1060 if (hid == tracks[track_widx-1].audio_hid
1061 && filling == STATE_END_OF_PLAYLIST)
1063 /* This was the last track in the playlist.
1064 We now have all the data we need. */
1065 logf("last track finished buffering");
1066 filling = STATE_FINISHED;
1072 /* --- Audio thread --- */
1074 static bool audio_have_tracks(void)
1076 return (audio_track_count() != 0);
1079 static int audio_free_track_count(void)
1081 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
1082 return MAX_TRACK - 1 - audio_track_count();
1085 int audio_track_count(void)
1087 /* Calculate difference from track_ridx to track_widx
1088 * taking into account a possible wrap-around. */
1089 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK;
1092 long audio_filebufused(void)
1094 return (long) buf_used();
1097 /* Update track info after successful a codec track change */
1098 static void audio_update_trackinfo(void)
1100 /* Load the curent track's metadata into curtrack_id3 */
1101 if (CUR_TI->id3_hid >= 0)
1102 copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid));
1104 /* Reset current position */
1105 thistrack_id3->elapsed = 0;
1106 thistrack_id3->offset = 0;
1108 /* Update the codec API */
1109 ci.filesize = CUR_TI->filesize;
1110 ci.id3 = thistrack_id3;
1111 ci.curpos = 0;
1112 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1115 /* Clear tracks between write and read, non inclusive */
1116 static void audio_clear_track_entries(void)
1118 int cur_idx = track_widx;
1120 logf("Clearing tracks: r%d/w%d", track_ridx, track_widx);
1122 /* Loop over all tracks from write-to-read */
1123 while (1)
1125 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1127 if (cur_idx == track_ridx)
1128 break;
1130 clear_track_info(&tracks[cur_idx]);
1134 /* Clear all tracks */
1135 static bool audio_release_tracks(void)
1137 int i, cur_idx;
1139 logf("releasing all tracks");
1141 for(i = 0; i < MAX_TRACK; i++)
1143 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
1144 if (!clear_track_info(&tracks[cur_idx]))
1145 return false;
1148 return true;
1151 static bool audio_loadcodec(bool start_play)
1153 int prev_track;
1154 char codec_path[MAX_PATH]; /* Full path to codec */
1155 const struct mp3entry *id3, *prev_id3;
1157 if (tracks[track_widx].id3_hid < 0) {
1158 return false;
1161 id3 = bufgetid3(tracks[track_widx].id3_hid);
1162 if (!id3)
1163 return false;
1165 const char *codec_fn = get_codec_filename(id3->codectype);
1166 if (codec_fn == NULL)
1167 return false;
1169 tracks[track_widx].codec_hid = -1;
1171 if (start_play)
1173 /* Load the codec directly from disk and save some memory. */
1174 track_ridx = track_widx;
1175 ci.filesize = CUR_TI->filesize;
1176 ci.id3 = thistrack_id3;
1177 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1178 ci.curpos = 0;
1179 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1180 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
1181 return true;
1183 else
1185 /* If we already have another track than this one buffered */
1186 if (track_widx != track_ridx)
1188 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1190 id3 = bufgetid3(tracks[track_widx].id3_hid);
1191 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1193 /* If the previous codec is the same as this one, there is no need
1194 * to put another copy of it on the file buffer */
1195 if (id3 && prev_id3 &&
1196 get_codec_base_type(id3->codectype) ==
1197 get_codec_base_type(prev_id3->codectype)
1198 && audio_codec_loaded)
1200 logf("Reusing prev. codec");
1201 return true;
1206 codec_get_full_path(codec_path, codec_fn);
1208 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1209 if (tracks[track_widx].codec_hid < 0)
1210 return false;
1212 logf("Loaded codec");
1214 return true;
1217 /* Load metadata for the next track (with bufopen). The rest of the track
1218 loading will be handled by audio_finish_load_track once the metadata has been
1219 actually loaded by the buffering thread. */
1220 static bool audio_load_track(size_t offset, bool start_play)
1222 const char *trackname;
1223 int fd = -1;
1225 if (track_load_started) {
1226 /* There is already a track load in progress, so track_widx hasn't been
1227 incremented yet. Loading another track would overwrite the one that
1228 hasn't finished loading. */
1229 logf("audio_load_track(): a track load is already in progress");
1230 return false;
1233 start_play_g = start_play; /* will be read by audio_finish_load_track */
1235 /* Stop buffer filling if there is no free track entries.
1236 Don't fill up the last track entry (we wan't to store next track
1237 metadata there). */
1238 if (!audio_free_track_count())
1240 logf("No free tracks");
1241 return false;
1244 last_peek_offset++;
1245 tracks[track_widx].taginfo_ready = false;
1247 logf("Buffering track: r%d/w%d", track_ridx, track_widx);
1248 /* Get track name from current playlist read position. */
1249 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
1251 /* Handle broken playlists. */
1252 fd = open(trackname, O_RDONLY);
1253 if (fd < 0)
1255 logf("Open failed");
1256 /* Skip invalid entry from playlist. */
1257 playlist_skip_entry(NULL, last_peek_offset);
1259 else
1260 break;
1263 if (!trackname)
1265 logf("End-of-playlist");
1266 memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
1267 filling = STATE_END_OF_PLAYLIST;
1269 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
1271 /* Stop playback if no valid track was found. */
1272 audio_stop_playback();
1275 return false;
1278 tracks[track_widx].filesize = filesize(fd);
1280 if (offset > tracks[track_widx].filesize)
1281 offset = 0;
1283 /* Set default values */
1284 if (start_play)
1286 buf_set_watermark(filebuflen/2);
1287 dsp_configure(ci.dsp, DSP_RESET, 0);
1288 playlist_update_resume_info(audio_current_track());
1291 /* Get track metadata if we don't already have it. */
1292 if (tracks[track_widx].id3_hid < 0)
1294 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL);
1296 if (tracks[track_widx].id3_hid < 0)
1298 /* Buffer is full. */
1299 get_metadata(&unbuffered_id3, fd, trackname);
1300 last_peek_offset--;
1301 close(fd);
1302 logf("buffer is full for now (get metadata)");
1303 filling = STATE_FULL;
1304 return false;
1307 if (track_widx == track_ridx)
1309 /* TODO: Superfluos buffering call? */
1310 buf_request_buffer_handle(tracks[track_widx].id3_hid);
1311 struct mp3entry *id3 = bufgetid3(tracks[track_widx].id3_hid);
1312 if (id3)
1314 copy_mp3entry(thistrack_id3, id3);
1315 thistrack_id3->offset = offset;
1317 else
1318 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1321 if (start_play)
1323 playlist_update_resume_info(audio_current_track());
1327 close(fd);
1328 track_load_started = true; /* Remember that we've started loading a track */
1329 return true;
1332 /* Second part of the track loading: We now have the metadata available, so we
1333 can load the codec, the album art and finally the audio data.
1334 This is called on the audio thread after the buffering thread calls the
1335 buffering_handle_finished_callback callback. */
1336 static void audio_finish_load_track(void)
1338 size_t file_offset = 0;
1339 size_t offset = 0;
1340 bool start_play = start_play_g;
1342 track_load_started = false;
1344 if (tracks[track_widx].id3_hid < 0) {
1345 logf("No metadata");
1346 return;
1349 struct mp3entry *track_id3;
1351 if (track_widx == track_ridx)
1352 track_id3 = thistrack_id3;
1353 else
1354 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
1356 if (track_id3->length == 0 && track_id3->filesize == 0)
1358 logf("audio_finish_load_track: invalid metadata");
1360 /* Invalid metadata */
1361 bufclose(tracks[track_widx].id3_hid);
1362 tracks[track_widx].id3_hid = -1;
1364 /* Skip invalid entry from playlist. */
1365 playlist_skip_entry(NULL, last_peek_offset--);
1367 /* load next track */
1368 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play);
1369 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1371 return;
1373 /* Try to load a cuesheet for the track */
1374 if (curr_cue)
1376 char cuepath[MAX_PATH];
1377 if (look_for_cuesheet_file(track_id3->path, cuepath))
1379 void *temp;
1380 tracks[track_widx].cuesheet_hid =
1381 bufalloc(NULL, sizeof(struct cuesheet), TYPE_CUESHEET);
1382 if (tracks[track_widx].cuesheet_hid >= 0)
1384 bufgetdata(tracks[track_widx].cuesheet_hid,
1385 sizeof(struct cuesheet), &temp);
1386 struct cuesheet *cuesheet = (struct cuesheet*)temp;
1387 if (!parse_cuesheet(cuepath, cuesheet))
1389 bufclose(tracks[track_widx].cuesheet_hid);
1390 track_id3->cuesheet = NULL;
1395 #ifdef HAVE_ALBUMART
1397 int i;
1398 char aa_path[MAX_PATH];
1399 FOREACH_ALBUMART(i)
1401 /* albumart_slots may change during a yield of bufopen,
1402 * but that's no problem */
1403 if (tracks[track_widx].aa_hid[i] >= 0 || !albumart_slots[i].used)
1404 continue;
1405 /* find_albumart will error out if the wps doesn't have AA */
1406 if (find_albumart(track_id3, aa_path, sizeof(aa_path),
1407 &(albumart_slots[i].dim)))
1409 int aa_hid = bufopen(aa_path, 0, TYPE_BITMAP,
1410 &(albumart_slots[i].dim));
1412 if(aa_hid == ERR_BUFFER_FULL)
1414 filling = STATE_FULL;
1415 logf("buffer is full for now (get album art)");
1416 return; /* No space for track's album art, not an error */
1418 else if (aa_hid < 0)
1420 /* another error, ignore AlbumArt */
1421 logf("Album art loading failed");
1423 tracks[track_widx].aa_hid[i] = aa_hid;
1428 #endif
1430 /* Load the codec. */
1431 if (!audio_loadcodec(start_play))
1433 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1435 /* No space for codec on buffer, not an error */
1436 filling = STATE_FULL;
1437 return;
1440 /* This is an error condition, either no codec was found, or reading
1441 * the codec file failed part way through, either way, skip the track */
1442 /* FIXME: We should not use splashf from audio thread! */
1443 splashf(HZ*2, "No codec for: %s", track_id3->path);
1444 /* Skip invalid entry from playlist. */
1445 playlist_skip_entry(NULL, last_peek_offset);
1446 return;
1449 track_id3->elapsed = 0;
1450 offset = track_id3->offset;
1451 size_t resume_rewind = (global_settings.resume_rewind *
1452 track_id3->bitrate * 1000) / 8;
1454 if (offset < resume_rewind)
1456 offset = 0;
1458 else
1460 offset -= resume_rewind;
1463 enum data_type type = TYPE_PACKET_AUDIO;
1465 switch (track_id3->codectype) {
1466 case AFMT_MPA_L1:
1467 case AFMT_MPA_L2:
1468 case AFMT_MPA_L3:
1469 if (offset > 0) {
1470 file_offset = offset;
1472 break;
1474 case AFMT_WAVPACK:
1475 if (offset > 0) {
1476 file_offset = offset;
1477 track_id3->elapsed = track_id3->length / 2;
1479 break;
1481 case AFMT_NSF:
1482 case AFMT_SPC:
1483 case AFMT_SID:
1484 logf("Loading atomic %d",track_id3->codectype);
1485 type = TYPE_ATOMIC_AUDIO;
1486 break;
1488 default:
1489 /* no special treatment needed */
1490 break;
1493 track_id3->offset = offset;
1495 logf("load track: %s", track_id3->path);
1497 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1498 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1499 else if (track_id3->first_frame_offset)
1500 file_offset = track_id3->first_frame_offset;
1501 else
1502 file_offset = 0;
1504 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type,
1505 NULL);
1507 /* No space left, not an error */
1508 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1510 filling = STATE_FULL;
1511 logf("buffer is full for now (load audio)");
1512 return;
1514 else if (tracks[track_widx].audio_hid < 0)
1516 /* another error, do not continue either */
1517 logf("Could not add audio data handle");
1518 return;
1521 /* All required data is now available for the codec. */
1522 tracks[track_widx].taginfo_ready = true;
1524 if (start_play)
1526 ci.curpos=file_offset;
1527 buf_request_buffer_handle(tracks[track_widx].audio_hid);
1530 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1532 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
1534 /* load next track */
1535 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1536 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1538 return;
1541 static void audio_fill_file_buffer(bool start_play, size_t offset)
1543 trigger_cpu_boost();
1545 /* No need to rebuffer if there are track skips pending,
1546 * however don't cancel buffering on skipping while filling. */
1547 if (ci.new_track != 0 && filling != STATE_FILLING)
1548 return;
1549 filling = STATE_FILLING;
1551 /* Must reset the buffer before use if trashed or voice only - voice
1552 file size shouldn't have changed so we can go straight from
1553 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1554 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1555 audio_reset_buffer();
1557 logf("Starting buffer fill");
1559 if (!start_play)
1560 audio_clear_track_entries();
1562 /* Save the current resume position once. */
1563 playlist_update_resume_info(audio_current_track());
1565 audio_load_track(offset, start_play);
1568 static void audio_rebuffer(void)
1570 logf("Forcing rebuffer");
1572 clear_track_info(CUR_TI);
1574 /* Reset track pointers */
1575 track_widx = track_ridx;
1576 audio_clear_track_entries();
1578 /* Reset a possibly interrupted track load */
1579 track_load_started = false;
1581 /* Fill the buffer */
1582 last_peek_offset = -1;
1583 ci.curpos = 0;
1585 if (!CUR_TI->taginfo_ready)
1586 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1588 audio_fill_file_buffer(false, 0);
1591 /* Called on request from the codec to get a new track. This is the codec part
1592 of the track transition. */
1593 static int audio_check_new_track(void)
1595 int track_count = audio_track_count();
1596 int old_track_ridx = track_ridx;
1597 int i, idx;
1598 bool forward;
1599 struct mp3entry *temp = thistrack_id3;
1601 /* Now it's good time to send track finish events. */
1602 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1603 /* swap the mp3entry pointers */
1604 thistrack_id3 = othertrack_id3;
1605 othertrack_id3 = temp;
1606 ci.id3 = thistrack_id3;
1607 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1609 if (dir_skip)
1611 dir_skip = false;
1612 /* regardless of the return value we need to rebuffer.
1613 if it fails the old playlist will resume, else the
1614 next dir will start playing */
1615 playlist_next_dir(ci.new_track);
1616 ci.new_track = 0;
1617 audio_rebuffer();
1618 goto skip_done;
1621 if (new_playlist)
1622 ci.new_track = 0;
1624 /* If the playlist isn't that big */
1625 if (automatic_skip)
1627 while (!playlist_check(ci.new_track))
1629 if (ci.new_track >= 0)
1631 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1632 return Q_CODEC_REQUEST_FAILED;
1634 ci.new_track++;
1638 /* Update the playlist */
1639 last_peek_offset -= ci.new_track;
1641 if (playlist_next(ci.new_track) < 0)
1643 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1644 return Q_CODEC_REQUEST_FAILED;
1647 if (new_playlist)
1649 ci.new_track = 1;
1650 new_playlist = false;
1653 /* Save a pointer to the old track to allow later clearing */
1654 prev_ti = CUR_TI;
1656 for (i = 0; i < ci.new_track; i++)
1658 idx = (track_ridx + i) & MAX_TRACK_MASK;
1659 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid);
1660 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid);
1661 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset)
1663 /* We don't have all the audio data for that track, so clear it,
1664 but keep the metadata. */
1665 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
1667 tracks[idx].audio_hid = -1;
1668 tracks[idx].filesize = 0;
1673 /* Move to the new track */
1674 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
1675 buf_set_base_handle(CUR_TI->audio_hid);
1678 if (automatic_skip)
1680 wps_offset = -ci.new_track;
1683 /* If it is not safe to even skip this many track entries */
1684 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
1686 ci.new_track = 0;
1687 audio_rebuffer();
1688 goto skip_done;
1691 forward = ci.new_track > 0;
1692 ci.new_track = 0;
1694 /* If the target track is clearly not in memory */
1695 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
1697 audio_rebuffer();
1698 goto skip_done;
1701 /* When skipping backwards, it is possible that we've found a track that's
1702 * buffered, but which is around the track-wrap and therefore not the track
1703 * we are looking for */
1704 if (!forward)
1706 int cur_idx = track_ridx;
1707 bool taginfo_ready = true;
1708 /* We've wrapped the buffer backwards if new > old */
1709 bool wrap = track_ridx > old_track_ridx;
1711 while (1)
1713 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1715 /* if we've advanced past the wrap when cur_idx is zeroed */
1716 if (!cur_idx)
1717 wrap = false;
1719 /* if we aren't still on the wrap and we've caught the old track */
1720 if (!(wrap || cur_idx < old_track_ridx))
1721 break;
1723 /* If we hit a track in between without valid tag info, bail */
1724 if (!tracks[cur_idx].taginfo_ready)
1726 taginfo_ready = false;
1727 break;
1730 if (!taginfo_ready)
1732 audio_rebuffer();
1736 skip_done:
1737 audio_update_trackinfo();
1738 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
1739 return Q_CODEC_REQUEST_COMPLETE;
1742 unsigned long audio_prev_elapsed(void)
1744 return prev_track_elapsed;
1747 void audio_set_prev_elapsed(unsigned long setting)
1749 prev_track_elapsed = setting;
1752 static void audio_stop_codec_flush(void)
1754 ci.stop_codec = true;
1755 pcmbuf_pause(true);
1757 while (audio_codec_loaded)
1758 yield();
1760 /* If the audio codec is not loaded any more, and the audio is still
1761 * playing, it is now and _only_ now safe to call this function from the
1762 * audio thread */
1763 if (pcm_is_playing())
1765 pcmbuf_play_stop();
1766 pcm_play_lock();
1767 queue_clear(&pcmbuf_queue);
1768 pcm_play_unlock();
1770 pcmbuf_pause(paused);
1773 static void audio_stop_playback(void)
1775 if (playing)
1777 /* If we were playing, save resume information */
1778 struct mp3entry *id3 = NULL;
1780 if (!ci.stop_codec)
1782 /* Set this early, the outside code yields and may allow the codec
1783 to try to wait for a reply on a buffer wait */
1784 ci.stop_codec = true;
1785 id3 = audio_current_track();
1788 /* Save the current playing spot, or NULL if the playlist has ended */
1789 playlist_update_resume_info(id3);
1791 /* TODO: Create auto bookmark too? */
1793 prev_track_elapsed = othertrack_id3->elapsed;
1795 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
1798 audio_stop_codec_flush();
1799 paused = false;
1800 playing = false;
1801 track_load_started = false;
1803 filling = STATE_IDLE;
1805 /* Mark all entries null. */
1806 audio_clear_track_entries();
1808 /* Close all tracks */
1809 audio_release_tracks();
1812 static void audio_play_start(size_t offset)
1814 int i;
1816 #if INPUT_SRC_CAPS != 0
1817 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1818 audio_set_output_source(AUDIO_SRC_PLAYBACK);
1819 #endif
1821 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
1822 paused = false;
1823 audio_stop_codec_flush();
1825 playing = true;
1826 track_load_started = false;
1828 ci.new_track = 0;
1829 ci.seek_time = 0;
1830 wps_offset = 0;
1832 sound_set_volume(global_settings.volume);
1833 track_widx = track_ridx = 0;
1834 buf_set_base_handle(-1);
1836 /* Clear all track entries. */
1837 for (i = 0; i < MAX_TRACK; i++) {
1838 clear_track_info(&tracks[i]);
1841 last_peek_offset = -1;
1843 /* Officially playing */
1844 queue_reply(&audio_queue, 1);
1846 audio_fill_file_buffer(true, offset);
1848 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
1850 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1851 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1855 /* Invalidates all but currently playing track. */
1856 static void audio_invalidate_tracks(void)
1858 if (audio_have_tracks())
1860 last_peek_offset = 0;
1861 track_widx = track_ridx;
1863 /* Mark all other entries null (also buffered wrong metadata). */
1864 audio_clear_track_entries();
1866 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1868 audio_fill_file_buffer(false, 0);
1869 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1873 static void audio_new_playlist(void)
1875 /* Prepare to start a new fill from the beginning of the playlist */
1876 last_peek_offset = -1;
1877 if (audio_have_tracks())
1879 if (paused)
1880 skipped_during_pause = true;
1881 track_widx = track_ridx;
1882 audio_clear_track_entries();
1884 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1886 /* Mark the current track as invalid to prevent skipping back to it */
1887 CUR_TI->taginfo_ready = false;
1890 /* Signal the codec to initiate a track change forward */
1891 new_playlist = true;
1892 ci.new_track = 1;
1894 /* Officially playing */
1895 queue_reply(&audio_queue, 1);
1897 audio_fill_file_buffer(false, 0);
1900 /* Called on manual track skip */
1901 static void audio_initiate_track_change(long direction)
1903 logf("audio_initiate_track_change(%ld)", direction);
1905 ci.new_track += direction;
1906 wps_offset -= direction;
1907 if (paused)
1908 skipped_during_pause = true;
1911 /* Called on manual dir skip */
1912 static void audio_initiate_dir_change(long direction)
1914 dir_skip = true;
1915 ci.new_track = direction;
1916 if (paused)
1917 skipped_during_pause = true;
1920 /* Called when PCM track change is complete */
1921 static void audio_finalise_track_change(void)
1923 logf("audio_finalise_track_change");
1925 if (automatic_skip)
1927 wps_offset = 0;
1928 automatic_skip = false;
1930 /* Invalidate prevtrack_id3 */
1931 memset(othertrack_id3, 0, sizeof(struct mp3entry));
1933 if (prev_ti && prev_ti->audio_hid < 0)
1935 /* No audio left so we clear all the track info. */
1936 clear_track_info(prev_ti);
1939 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1940 playlist_update_resume_info(audio_current_track());
1944 * Layout audio buffer as follows - iram buffer depends on target:
1945 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
1947 static void audio_reset_buffer(void)
1949 /* see audio_get_recording_buffer if this is modified */
1950 logf("audio_reset_buffer");
1952 /* If the setup of anything allocated before the file buffer is
1953 changed, do check the adjustments after the buffer_alloc call
1954 as it will likely be affected and need sliding over */
1956 /* Initially set up file buffer as all space available */
1957 malloc_buf = audiobuf + talk_get_bufsize();
1958 /* Align the malloc buf to line size. Especially important to cf
1959 targets that do line reads/writes. */
1960 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
1961 filebuf = malloc_buf; /* filebuf line align implied */
1962 filebuflen = audiobufend - filebuf;
1964 filebuflen &= ~15;
1966 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
1967 const size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) +GUARD_BUFSIZE;
1969 #ifdef DEBUG
1970 if(pcmbuf_size > filebuflen)
1971 panicf("Not enough memory for pcmbuf_init() : %d > %d",
1972 (int)pcmbuf_size, (int)filebuflen);
1973 #endif
1975 filebuflen -= pcmbuf_size;
1977 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
1978 will already be line aligned */
1979 filebuflen &= ~3;
1981 buffering_reset(filebuf, filebuflen);
1983 /* Clear any references to the file buffer */
1984 buffer_state = AUDIOBUF_STATE_INITIALIZED;
1986 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1987 /* Make sure everything adds up - yes, some info is a bit redundant but
1988 aids viewing and the sumation of certain variables should add up to
1989 the location of others. */
1991 size_t pcmbufsize;
1992 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
1993 logf("mabuf: %08X", (unsigned)malloc_buf);
1994 logf("fbuf: %08X", (unsigned)filebuf);
1995 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
1996 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
1997 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
1998 logf("pcmb: %08X", (unsigned)pcmbuf);
1999 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
2001 #endif
2004 static void audio_thread(void)
2006 struct queue_event ev;
2008 pcm_postinit();
2010 audio_thread_ready = true;
2012 while (1)
2014 if (filling != STATE_FILLING && filling != STATE_IDLE) {
2015 /* End of buffering, let's calculate the watermark and unboost */
2016 set_filebuf_watermark();
2017 cancel_cpu_boost();
2020 if (!pcmbuf_queue_scan(&ev))
2021 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
2023 switch (ev.id) {
2025 case Q_AUDIO_FILL_BUFFER:
2026 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
2027 audio_fill_file_buffer((bool)ev.data, 0);
2028 break;
2030 case Q_AUDIO_FINISH_LOAD:
2031 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2032 audio_finish_load_track();
2033 buf_set_base_handle(CUR_TI->audio_hid);
2034 break;
2036 case Q_AUDIO_PLAY:
2037 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2038 if (playing && ev.data <= 0)
2039 audio_new_playlist();
2040 else
2042 audio_stop_playback();
2043 audio_play_start((size_t)ev.data);
2045 break;
2047 case Q_AUDIO_STOP:
2048 LOGFQUEUE("audio < Q_AUDIO_STOP");
2049 if (playing)
2050 audio_stop_playback();
2051 if (ev.data != 0)
2052 queue_clear(&audio_queue);
2053 break;
2054 case Q_AUDIO_PAUSE_W_FADE:
2055 case Q_AUDIO_PAUSE:
2056 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2057 if (global_settings.fade_on_stop)
2059 fading = true;
2060 handle_fade(ev.data);
2062 if (!fading || (fading && !ev.data))
2063 { /* fade will do this for us */
2064 if (!(bool) ev.data && skipped_during_pause
2065 #ifdef HAVE_CROSSFADE
2066 && !pcmbuf_is_crossfade_active()
2067 #endif
2069 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2070 skipped_during_pause = false;
2072 if (!playing)
2073 break;
2074 if (!fading || (fading && !ev.data))
2075 pcmbuf_pause((bool)ev.data); /* done in fading */
2076 paused = (bool)ev.data;
2077 fading = false;
2078 break;
2080 case Q_AUDIO_SKIP:
2081 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2082 audio_initiate_track_change((long)ev.data);
2083 break;
2085 case Q_AUDIO_PRE_FF_REWIND:
2086 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2087 if (!playing)
2088 break;
2089 pcmbuf_pause(true);
2090 break;
2092 case Q_AUDIO_FF_REWIND:
2093 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2094 if (!playing)
2095 break;
2096 if (automatic_skip)
2098 /* An automatic track skip is in progress. Finalize it,
2099 then go back to the previous track */
2100 audio_finalise_track_change();
2101 ci.new_track = -1;
2103 ci.seek_time = (long)ev.data+1;
2104 break;
2106 case Q_AUDIO_CHECK_NEW_TRACK:
2107 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2108 queue_reply(&audio_queue, audio_check_new_track());
2109 break;
2111 case Q_AUDIO_DIR_SKIP:
2112 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2113 audio_initiate_dir_change(ev.data);
2114 break;
2116 case Q_AUDIO_FLUSH:
2117 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2118 audio_invalidate_tracks();
2119 break;
2121 case Q_AUDIO_TRACK_CHANGED:
2122 /* PCM track change done */
2123 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2124 audio_finalise_track_change();
2125 break;
2126 #ifndef SIMULATOR
2127 case SYS_USB_CONNECTED:
2128 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2129 if (playing)
2130 audio_stop_playback();
2131 #ifdef PLAYBACK_VOICE
2132 voice_stop();
2133 #endif
2134 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2135 usb_wait_for_disconnect(&audio_queue);
2137 /* Mark all entries null. */
2138 audio_clear_track_entries();
2140 /* release tracks to make sure all handles are closed */
2141 audio_release_tracks();
2142 break;
2143 #endif
2145 case SYS_TIMEOUT:
2146 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2147 break;
2149 default:
2150 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2151 break;
2152 } /* end switch */
2153 } /* end while */
2156 /* Initialize the audio system - called from init() in main.c.
2157 * Last function because of all the references to internal symbols
2159 void audio_init(void)
2161 unsigned int audio_thread_id;
2163 /* Can never do this twice */
2164 if (audio_is_initialized)
2166 logf("audio: already initialized");
2167 return;
2170 logf("audio: initializing");
2172 /* Initialize queues before giving control elsewhere in case it likes
2173 to send messages. Thread creation will be delayed however so nothing
2174 starts running until ready if something yields such as talk_init. */
2175 queue_init(&audio_queue, true);
2176 queue_init(&codec_queue, false);
2177 queue_init(&pcmbuf_queue, false);
2179 pcm_init();
2181 codec_init_codec_api();
2183 thistrack_id3 = &mp3entry_buf[0];
2184 othertrack_id3 = &mp3entry_buf[1];
2186 /* cuesheet support */
2187 if (global_settings.cuesheet)
2188 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2190 /* initialize the buffer */
2191 filebuf = audiobuf;
2193 /* audio_reset_buffer must to know the size of voice buffer so init
2194 talk first */
2195 talk_init();
2197 make_codec_thread();
2199 audio_thread_id = create_thread(audio_thread, audio_stack,
2200 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2201 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
2202 IF_COP(, CPU));
2204 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
2205 audio_thread_id);
2207 #ifdef PLAYBACK_VOICE
2208 voice_thread_init();
2209 #endif
2211 #ifdef HAVE_CROSSFADE
2212 /* Set crossfade setting for next buffer init which should be about... */
2213 pcmbuf_request_crossfade_enable(global_settings.crossfade);
2214 #endif
2216 /* initialize the buffering system */
2218 buffering_init();
2219 /* ...now! Set up the buffers */
2220 audio_reset_buffer();
2222 int i;
2223 for(i = 0; i < MAX_TRACK; i++)
2225 tracks[i].audio_hid = -1;
2226 tracks[i].id3_hid = -1;
2227 tracks[i].codec_hid = -1;
2228 tracks[i].cuesheet_hid = -1;
2230 #ifdef HAVE_ALBUMART
2231 FOREACH_ALBUMART(i)
2233 int j;
2234 for (j = 0; j < MAX_TRACK; j++)
2236 tracks[j].aa_hid[i] = -1;
2239 #endif
2241 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2242 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2244 /* Probably safe to say */
2245 audio_is_initialized = true;
2247 sound_settings_apply();
2248 #ifdef HAVE_DISK_STORAGE
2249 audio_set_buffer_margin(global_settings.buffer_margin);
2250 #endif
2252 /* it's safe to let the threads run now */
2253 #ifdef PLAYBACK_VOICE
2254 voice_thread_resume();
2255 #endif
2256 thread_thaw(codec_thread_id);
2257 thread_thaw(audio_thread_id);
2259 } /* audio_init */
2261 bool audio_is_thread_ready(void)
2263 return audio_thread_ready;
2266 size_t audio_get_filebuflen(void)
2268 return filebuflen;
2271 int get_audio_hid()
2273 return CUR_TI->audio_hid;
2276 int *get_codec_hid()
2278 return &tracks[track_ridx].codec_hid;