Fix red and yellow. Move resume_index from mp3entry to playlist_info struct. Bump...
[kugel-rb.git] / apps / playback.c
blob632fd05d3deb564c4c6d920e1c462804778ffc38
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 */
25 #include "config.h"
26 #include "system.h"
27 #include <string.h>
28 #include "playback.h"
29 #include "codec_thread.h"
30 #include "kernel.h"
31 #include "codecs.h"
32 #include "buffering.h"
33 #include "voice_thread.h"
34 #include "usb.h"
35 #include "ata.h"
36 #include "playlist.h"
37 #include "pcmbuf.h"
38 #include "buffer.h"
39 #include "cuesheet.h"
40 #ifdef HAVE_TAGCACHE
41 #include "tagcache.h"
42 #endif
43 #ifdef HAVE_LCD_BITMAP
44 #ifdef HAVE_ALBUMART
45 #include "albumart.h"
46 #endif
47 #endif
48 #include "sound.h"
49 #include "metadata.h"
50 #include "splash.h"
51 #include "talk.h"
52 #include "panic.h"
54 #ifdef HAVE_RECORDING
55 #include "pcm_record.h"
56 #endif
58 #define PLAYBACK_VOICE
60 /* amount of guess-space to allow for codecs that must hunt and peck
61 * for their correct seeek target, 32k seems a good size */
62 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
64 /* Define LOGF_ENABLE to enable logf output in this file */
65 /*#define LOGF_ENABLE*/
66 #include "logf.h"
68 /* macros to enable logf for queues
69 logging on SYS_TIMEOUT can be disabled */
70 #ifdef SIMULATOR
71 /* Define this for logf output of all queuing except SYS_TIMEOUT */
72 #define PLAYBACK_LOGQUEUES
73 /* Define this to logf SYS_TIMEOUT messages */
74 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
75 #endif
77 #ifdef PLAYBACK_LOGQUEUES
78 #define LOGFQUEUE logf
79 #else
80 #define LOGFQUEUE(...)
81 #endif
83 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
84 #define LOGFQUEUE_SYS_TIMEOUT logf
85 #else
86 #define LOGFQUEUE_SYS_TIMEOUT(...)
87 #endif
90 static enum filling_state {
91 STATE_IDLE, /* audio is stopped: nothing to do */
92 STATE_FILLING, /* adding tracks to the buffer */
93 STATE_FULL, /* can't add any more tracks */
94 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
95 STATE_FINISHED, /* all remaining tracks are fully buffered */
96 STATE_ENDING, /* audio playback is ending */
97 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
98 STATE_USB, /* USB mode, ignore most messages */
99 #endif
100 } filling;
102 /* As defined in plugins/lib/xxx2wav.h */
103 #define GUARD_BUFSIZE (32*1024)
105 bool audio_is_initialized = false;
106 static bool audio_thread_ready SHAREDBSS_ATTR = false;
108 /* Variables are commented with the threads that use them: *
109 * A=audio, C=codec, V=voice. A suffix of - indicates that *
110 * the variable is read but not updated on that thread. */
111 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
113 /* Main state control */
114 static volatile bool playing SHAREDBSS_ATTR = false;/* Is audio playing? (A) */
115 static volatile bool paused SHAREDBSS_ATTR = false; /* Is audio paused? (A/C-) */
117 /* Ring buffer where compressed audio and codecs are loaded */
118 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
119 static size_t filebuflen = 0; /* Size of buffer (A/C-) */
120 /* FIXME: make buf_ridx (C/A-) */
122 /* Possible arrangements of the buffer */
123 enum audio_buffer_state
125 AUDIOBUF_STATE_TRASHED = -1, /* trashed; must be reset */
126 AUDIOBUF_STATE_INITIALIZED = 0, /* voice+audio OR audio-only */
127 AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
129 static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
131 /* These are used to store the current and next (or prev if the current is the last)
132 * mp3entry's in a round-robin system. This guarentees that the pointer returned
133 * by audio_current/next_track will be valid for the full duration of the
134 * currently playing track */
135 static struct mp3entry mp3entry_buf[2];
136 struct mp3entry *thistrack_id3, /* the currently playing track */
137 *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
138 * next track otherwise */
139 static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
141 /* for cuesheet support */
142 static struct cuesheet *curr_cue = NULL;
145 #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
147 #ifdef HAVE_ALBUMART
149 static struct albumart_slot {
150 struct dim dim; /* holds width, height of the albumart */
151 int used; /* counter, increments if something uses it */
152 } albumart_slots[MAX_MULTIPLE_AA];
154 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
155 #endif
158 #define MAX_TRACK 128
159 #define MAX_TRACK_MASK (MAX_TRACK-1)
161 /* Track info structure about songs in the file buffer (A/C-) */
162 static struct track_info {
163 int audio_hid; /* The ID for the track's buffer handle */
164 int id3_hid; /* The ID for the track's metadata handle */
165 int codec_hid; /* The ID for the track's codec handle */
166 #ifdef HAVE_ALBUMART
167 int aa_hid[MAX_MULTIPLE_AA];/* The ID for the track's album art handle */
168 #endif
169 int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */
171 size_t filesize; /* File total length */
173 bool taginfo_ready; /* Is metadata read */
175 } tracks[MAX_TRACK];
177 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
178 static int track_widx = 0; /* Track being buffered (A) */
179 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
181 static struct track_info *prev_ti = NULL; /* Pointer to the previously played
182 track */
184 /* Information used only for filling the buffer */
185 /* Playlist steps from playing track to next track to be buffered (A) */
186 static int last_peek_offset = 0;
188 /* Scrobbler support */
189 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
191 /* Track change controls */
192 static bool automatic_skip = false; /* Who initiated in-progress skip? (A) */
193 extern bool track_transition; /* Are we in a track transition? */
194 static bool dir_skip = false; /* Is a directory skip pending? (A) */
195 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
196 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
197 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
199 static bool start_play_g = false; /* Used by audio_load_track to notify
200 audio_finish_load_track about start_play */
202 /* True when a track load is in progress, i.e. audio_load_track() has returned
203 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
204 * audio_load_track() to get called twice in a row, which would cause problems.
206 static bool track_load_started = false;
208 #ifdef HAVE_DISK_STORAGE
209 static size_t buffer_margin = 5; /* Buffer margin aka anti-skip buffer (A/C-) */
210 #endif
212 /* Event queues */
213 struct event_queue audio_queue SHAREDBSS_ATTR;
214 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR;
216 extern struct codec_api ci;
217 extern unsigned int codec_thread_id;
219 /* Multiple threads */
220 /* Set the watermark to trigger buffer fill (A/C) */
221 static void set_filebuf_watermark(void);
223 /* Audio thread */
224 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
225 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
226 static const char audio_thread_name[] = "audio";
228 static void audio_thread(void);
229 static void audio_initiate_track_change(long direction);
230 static bool audio_have_tracks(void);
231 static void audio_reset_buffer(void);
232 static void audio_stop_playback(void);
234 /**************************************/
236 /** Pcmbuf callbacks */
238 /* Between the codec and PCM track change, we need to keep updating the
239 * "elapsed" value of the previous (to the codec, but current to the
240 * user/PCM/WPS) track, so that the progressbar reaches the end.
241 * During that transition, the WPS will display othertrack_id3. */
242 void audio_pcmbuf_position_callback(unsigned int time)
244 time += othertrack_id3->elapsed;
245 othertrack_id3->elapsed = (time >= othertrack_id3->length)
246 ? othertrack_id3->length : time;
249 /* Post message from pcmbuf that the end of the previous track
250 * has just been played. */
251 void audio_post_track_change(bool pcmbuf)
253 if (pcmbuf)
255 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
256 queue_post(&pcmbuf_queue, Q_AUDIO_TRACK_CHANGED, 0);
258 else
260 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
261 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
265 /* Scan the pcmbuf queue and return true if a message pulled */
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;
282 /** Helper functions */
284 static struct mp3entry *bufgetid3(int handle_id)
286 if (handle_id < 0)
287 return NULL;
289 struct mp3entry *id3;
290 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
292 if (ret != sizeof(struct mp3entry))
293 return NULL;
295 return id3;
298 static bool bufreadid3(int handle_id, struct mp3entry *id3out)
300 struct mp3entry *id3 = bufgetid3(handle_id);
302 if (id3)
304 copy_mp3entry(id3out, id3);
305 return true;
308 return false;
311 static bool clear_track_info(struct track_info *track)
313 /* bufclose returns true if the handle is not found, or if it is closed
314 * successfully, so these checks are safe on non-existant handles */
315 if (!track)
316 return false;
318 if (track->codec_hid >= 0) {
319 if (bufclose(track->codec_hid))
320 track->codec_hid = -1;
321 else
322 return false;
325 if (track->id3_hid >= 0) {
326 if (bufclose(track->id3_hid))
327 track->id3_hid = -1;
328 else
329 return false;
332 if (track->audio_hid >= 0) {
333 if (bufclose(track->audio_hid))
334 track->audio_hid = -1;
335 else
336 return false;
339 #ifdef HAVE_ALBUMART
341 int i;
342 FOREACH_ALBUMART(i)
344 if (track->aa_hid[i] >= 0) {
345 if (bufclose(track->aa_hid[i]))
346 track->aa_hid[i] = -1;
347 else
348 return false;
352 #endif
354 if (track->cuesheet_hid >= 0) {
355 if (bufclose(track->cuesheet_hid))
356 track->cuesheet_hid = -1;
357 else
358 return false;
361 track->filesize = 0;
362 track->taginfo_ready = false;
364 return true;
367 /* --- External interfaces --- */
369 /* This sends a stop message and the audio thread will dump all it's
370 subsequenct messages */
371 void audio_hard_stop(void)
373 /* Stop playback */
374 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
375 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
376 #ifdef PLAYBACK_VOICE
377 voice_stop();
378 #endif
381 bool audio_restore_playback(int type)
383 switch (type)
385 case AUDIO_WANT_PLAYBACK:
386 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
387 audio_reset_buffer();
388 return true;
389 case AUDIO_WANT_VOICE:
390 if (buffer_state == AUDIOBUF_STATE_TRASHED)
391 audio_reset_buffer();
392 return true;
393 default:
394 return false;
398 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
400 unsigned char *buf, *end;
402 if (audio_is_initialized)
404 audio_hard_stop();
406 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
408 /* Reset the buffering thread so that it doesn't try to use the data */
409 buffering_reset(filebuf, filebuflen);
411 if (buffer_size == NULL)
413 /* Special case for talk_init to use since it already knows it's
414 trashed */
415 buffer_state = AUDIOBUF_STATE_TRASHED;
416 return NULL;
419 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
420 || !talk_voice_required())
422 logf("get buffer: talk, audio");
423 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
424 the talk buffer is not needed because voice isn't being used, or
425 could be AUDIOBUF_STATE_TRASHED already. If state is
426 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
427 without the caller knowing what's going on. Changing certain settings
428 may move it to a worse condition but the memory in use by something
429 else will remain undisturbed.
431 if (buffer_state != AUDIOBUF_STATE_TRASHED)
433 talk_buffer_steal();
434 buffer_state = AUDIOBUF_STATE_TRASHED;
437 buf = audiobuf;
438 end = audiobufend;
440 else
442 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
443 still AUDIOBUF_STATE_INITIALIZED */
444 /* Skip talk buffer and move pcm buffer to end to maximize available
445 contiguous memory - no audio running means voice will not need the
446 swap space */
447 logf("get buffer: audio");
448 buf = audiobuf + talk_get_bufsize();
449 end = audiobufend - pcmbuf_init(audiobufend);
450 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
453 *buffer_size = end - buf;
455 return buf;
458 bool audio_buffer_state_trashed(void)
460 return buffer_state == AUDIOBUF_STATE_TRASHED;
463 #ifdef HAVE_RECORDING
464 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
466 /* Stop audio, voice and obtain all available buffer space */
467 audio_hard_stop();
468 talk_buffer_steal();
470 unsigned char *end = audiobufend;
471 buffer_state = AUDIOBUF_STATE_TRASHED;
472 *buffer_size = end - audiobuf;
474 return (unsigned char *)audiobuf;
477 bool audio_load_encoder(int afmt)
479 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
480 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt);
481 return queue_send(&audio_queue, Q_AUDIO_LOAD_ENCODER, afmt) > 0;
482 #else
483 (void)afmt;
484 return true;
485 #endif
486 } /* audio_load_encoder */
488 void audio_remove_encoder(void)
490 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
491 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
492 queue_send(&audio_queue, Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN);
493 #endif
494 } /* audio_remove_encoder */
496 #endif /* HAVE_RECORDING */
499 struct mp3entry* audio_current_track(void)
501 const char *filename;
502 struct playlist_track_info trackinfo;
503 int cur_idx;
504 int offset = ci.new_track + wps_offset;
505 struct mp3entry *write_id3;
507 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
509 if (cur_idx == track_ridx && *thistrack_id3->path)
511 /* The usual case */
512 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
514 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
515 thistrack_id3->cuesheet = curr_cue;
517 return thistrack_id3;
519 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
521 /* We're in a track transition. The codec has moved on to the next track,
522 but the audio being played is still the same (now previous) track.
523 othertrack_id3.elapsed is being updated in an ISR by
524 codec_pcmbuf_position_callback */
525 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
527 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
528 othertrack_id3->cuesheet = curr_cue;
530 return othertrack_id3;
533 if (offset != 0)
535 /* Codec may be using thistrack_id3, so it must not be overwritten.
536 If this is a manual skip, othertrack_id3 will become
537 thistrack_id3 in audio_check_new_track().
538 FIXME: If this is an automatic skip, it probably means multiple
539 short tracks fit in the PCM buffer. Overwriting othertrack_id3
540 can lead to an incorrect value later.
541 Note that othertrack_id3 may also be used for next track.
543 write_id3 = othertrack_id3;
545 else
547 write_id3 = thistrack_id3;
550 if (tracks[cur_idx].id3_hid >= 0)
552 /* The current track's info has been buffered but not read yet, so get it */
553 if (bufreadid3(tracks[cur_idx].id3_hid, write_id3))
554 return write_id3;
557 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
558 we have and return that. */
560 memset(write_id3, 0, sizeof(struct mp3entry));
562 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo);
563 filename = trackinfo.filename;
564 if (!filename)
565 filename = "No file!";
567 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
568 if (tagcache_fill_tags(write_id3, filename))
569 return write_id3;
570 #endif
572 strlcpy(write_id3->path, filename, sizeof(write_id3->path));
573 write_id3->title = strrchr(write_id3->path, '/');
574 if (!write_id3->title)
575 write_id3->title = &write_id3->path[0];
576 else
577 write_id3->title++;
579 return write_id3;
582 struct mp3entry* audio_next_track(void)
584 int next_idx;
585 int offset = ci.new_track + wps_offset;
587 if (!audio_have_tracks())
588 return NULL;
590 if (wps_offset == -1 && *thistrack_id3->path)
592 /* We're in a track transition. The next track for the WPS is the one
593 currently being decoded. */
594 return thistrack_id3;
597 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
599 if (tracks[next_idx].id3_hid >= 0)
601 if (bufreadid3(tracks[next_idx].id3_hid, othertrack_id3))
602 return othertrack_id3;
603 else
604 return NULL;
607 if (next_idx == track_widx)
609 /* The next track hasn't been buffered yet, so we return the static
610 version of its metadata. */
611 return &unbuffered_id3;
614 return NULL;
617 /* gets a copy of the id3 data */
618 bool audio_peek_track(struct mp3entry* id3, int offset)
620 int next_idx;
621 int new_offset = ci.new_track + wps_offset + offset;
623 if (!audio_have_tracks())
624 return false;
625 next_idx = (track_ridx + new_offset) & MAX_TRACK_MASK;
627 if (tracks[next_idx].id3_hid >= 0)
628 return bufreadid3(tracks[next_idx].id3_hid, id3);
630 return false;
633 #ifdef HAVE_ALBUMART
635 int playback_current_aa_hid(int slot)
637 if (slot < 0)
638 return -1;
639 int cur_idx;
640 int offset = ci.new_track + wps_offset;
642 cur_idx = track_ridx + offset;
643 cur_idx &= MAX_TRACK_MASK;
644 return tracks[cur_idx].aa_hid[slot];
647 int playback_claim_aa_slot(struct dim *dim)
649 int i;
651 /* first try to find a slot already having the size to reuse it
652 * since we don't want albumart of the same size buffered multiple times */
653 FOREACH_ALBUMART(i)
655 struct albumart_slot *slot = &albumart_slots[i];
656 if (slot->dim.width == dim->width
657 && slot->dim.height == dim->height)
659 slot->used++;
660 return i;
663 /* size is new, find a free slot */
664 FOREACH_ALBUMART(i)
666 if (!albumart_slots[i].used)
668 albumart_slots[i].used++;
669 albumart_slots[i].dim = *dim;
670 return i;
673 /* sorry, no free slot */
674 return -1;
677 void playback_release_aa_slot(int slot)
679 /* invalidate the albumart_slot */
680 struct albumart_slot *aa_slot = &albumart_slots[slot];
682 if (aa_slot->used > 0)
683 aa_slot->used--;
686 #endif
687 void audio_play(long offset)
689 logf("audio_play");
691 #ifdef PLAYBACK_VOICE
692 /* Truncate any existing voice output so we don't have spelling
693 * etc. over the first part of the played track */
694 talk_force_shutup();
695 #endif
697 /* Start playback */
698 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
699 /* Don't return until playback has actually started */
700 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
703 void audio_stop(void)
705 /* Stop playback */
706 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
707 /* Don't return until playback has actually stopped */
708 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
711 void audio_pause(void)
713 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
714 /* Don't return until playback has actually paused */
715 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
718 void audio_resume(void)
720 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
721 /* Don't return until playback has actually resumed */
722 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
725 void audio_skip(int direction)
727 if (playlist_check(ci.new_track + wps_offset + direction))
729 if (global_settings.beep)
730 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
732 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction);
733 queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
734 /* Update wps while our message travels inside deep playback queues. */
735 wps_offset += direction;
737 else
739 /* No more tracks. */
740 if (global_settings.beep)
741 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
745 void audio_next(void)
747 audio_skip(1);
750 void audio_prev(void)
752 audio_skip(-1);
755 void audio_next_dir(void)
757 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
758 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
761 void audio_prev_dir(void)
763 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
764 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
767 void audio_pre_ff_rewind(void)
769 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
770 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
773 void audio_ff_rewind(long newpos)
775 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
776 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
779 void audio_flush_and_reload_tracks(void)
781 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
782 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
785 void audio_error_clear(void)
787 #ifdef AUDIO_HAVE_RECORDING
788 pcm_rec_error_clear();
789 #endif
792 int audio_status(void)
794 int ret = 0;
796 if (playing)
797 ret |= AUDIO_STATUS_PLAY;
799 if (paused)
800 ret |= AUDIO_STATUS_PAUSE;
802 #ifdef HAVE_RECORDING
803 /* Do this here for constitency with mpeg.c version */
804 /* FIXME: pcm_rec_status() is deprecated */
805 ret |= pcm_rec_status();
806 #endif
808 return ret;
811 bool audio_automatic_skip(void)
813 return automatic_skip;
816 int audio_get_file_pos(void)
818 return 0;
821 #ifdef HAVE_DISK_STORAGE
822 void audio_set_buffer_margin(int setting)
824 static const unsigned short lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
825 buffer_margin = lookup[setting];
826 logf("buffer margin: %ld", (long)buffer_margin);
827 set_filebuf_watermark();
829 #endif
831 #ifdef HAVE_CROSSFADE
832 /* Take necessary steps to enable or disable the crossfade setting */
833 void audio_set_crossfade(int enable)
835 size_t offset;
836 bool was_playing;
837 size_t size;
839 /* Tell it the next setting to use */
840 pcmbuf_request_crossfade_enable(enable);
842 /* Return if size hasn't changed or this is too early to determine
843 which in the second case there's no way we could be playing
844 anything at all */
845 if (pcmbuf_is_same_size()) return;
847 offset = 0;
848 was_playing = playing;
850 /* Playback has to be stopped before changing the buffer size */
851 if (was_playing)
853 /* Store the track resume position */
854 offset = thistrack_id3->offset;
857 /* Blast it - audio buffer will have to be setup again next time
858 something plays */
859 audio_get_buffer(true, &size);
861 /* Restart playback if audio was running previously */
862 if (was_playing)
863 audio_play(offset);
865 #endif
867 /* --- Routines called from multiple threads --- */
869 static void set_filebuf_watermark(void)
871 if (!filebuf)
872 return; /* Audio buffers not yet set up */
874 #ifdef HAVE_DISK_STORAGE
875 int seconds;
876 int spinup = ata_spinup_time();
877 if (spinup)
878 seconds = (spinup / HZ) + 1;
879 else
880 seconds = 5;
882 seconds += buffer_margin;
883 #else
884 /* flash storage */
885 int seconds = 1;
886 #endif
888 /* bitrate of last track in buffer dictates watermark */
889 struct mp3entry* id3 = NULL;
890 if (tracks[track_widx].taginfo_ready)
891 id3 = bufgetid3(tracks[track_widx].id3_hid);
892 else
893 id3 = bufgetid3(tracks[track_widx-1].id3_hid);
894 if (!id3) {
895 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
896 return;
898 size_t bytes = id3->bitrate * (1000/8) * seconds;
899 buf_set_watermark(bytes);
900 logf("fwmark: %d", bytes);
903 /* --- Buffering callbacks --- */
905 static void buffering_low_buffer_callback(void *data)
907 (void)data;
908 logf("low buffer callback");
910 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) {
911 /* force a refill */
912 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
913 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
917 static void buffering_handle_rebuffer_callback(void *data)
919 (void)data;
920 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
921 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
924 static void buffering_handle_finished_callback(void *data)
926 logf("handle %d finished buffering", *(int*)data);
927 int hid = (*(int*)data);
929 if (hid == tracks[track_widx].id3_hid)
931 int offset = ci.new_track + wps_offset;
932 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
933 /* The metadata handle for the last loaded track has been buffered.
934 We can ask the audio thread to load the rest of the track's data. */
935 LOGFQUEUE("audio > audio Q_AUDIO_FINISH_LOAD");
936 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
937 if (tracks[next_idx].id3_hid == hid)
938 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
940 else
942 /* This is most likely an audio handle, so we strip the useless
943 trailing tags that are left. */
944 strip_tags(hid);
946 if (hid == tracks[track_widx-1].audio_hid
947 && filling == STATE_END_OF_PLAYLIST)
949 /* This was the last track in the playlist.
950 We now have all the data we need. */
951 logf("last track finished buffering");
952 filling = STATE_FINISHED;
958 /* --- Audio thread --- */
960 static bool audio_have_tracks(void)
962 return (audio_track_count() != 0);
965 static int audio_free_track_count(void)
967 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
968 return MAX_TRACK - 1 - audio_track_count();
971 int audio_track_count(void)
973 /* Calculate difference from track_ridx to track_widx
974 * taking into account a possible wrap-around. */
975 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK;
978 long audio_filebufused(void)
980 return (long) buf_used();
983 /* Update track info after successful a codec track change */
984 static void audio_update_trackinfo(void)
986 bool resume = false;
988 /* Load the curent track's metadata into curtrack_id3 */
989 if (CUR_TI->id3_hid >= 0)
990 bufreadid3(CUR_TI->id3_hid, thistrack_id3);
992 /* Reset current position */
993 thistrack_id3->elapsed = 0;
995 #ifdef HAVE_TAGCACHE
996 /* Ignoring resume position for automatic track change if so configured */
997 resume = global_settings.autoresume_enable &&
998 (!automatic_skip /* Resume all manually selected tracks */
999 || global_settings.autoresume_automatic == AUTORESUME_NEXTTRACK_ALWAYS
1000 || (global_settings.autoresume_automatic != AUTORESUME_NEXTTRACK_NEVER
1001 /* Not never resume? */
1002 && autoresumable(thistrack_id3))); /* Pass Resume filter? */
1003 #endif
1005 if (!resume)
1007 thistrack_id3->offset = 0;
1010 logf("audio_update_trackinfo: Set offset for %s to %lX\n",
1011 thistrack_id3->title, thistrack_id3->offset);
1013 /* Update the codec API */
1014 ci.filesize = CUR_TI->filesize;
1015 ci.id3 = thistrack_id3;
1016 ci.curpos = 0;
1017 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1020 /* Clear tracks between write and read, non inclusive */
1021 static void audio_clear_track_entries(void)
1023 int cur_idx = track_widx;
1025 logf("Clearing tracks: r%d/w%d", track_ridx, track_widx);
1027 /* Loop over all tracks from write-to-read */
1028 while (1)
1030 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1032 if (cur_idx == track_ridx)
1033 break;
1035 clear_track_info(&tracks[cur_idx]);
1039 /* Clear all tracks */
1040 static bool audio_release_tracks(void)
1042 int i, cur_idx;
1044 logf("releasing all tracks");
1046 for(i = 0; i < MAX_TRACK; i++)
1048 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
1049 if (!clear_track_info(&tracks[cur_idx]))
1050 return false;
1053 return true;
1056 static bool audio_loadcodec(bool start_play)
1058 int prev_track, hid;
1059 char codec_path[MAX_PATH]; /* Full path to codec */
1060 const struct mp3entry *id3, *prev_id3;
1062 if (tracks[track_widx].id3_hid < 0) {
1063 return false;
1066 id3 = bufgetid3(tracks[track_widx].id3_hid);
1067 if (!id3)
1068 return false;
1070 const char *codec_fn = get_codec_filename(id3->codectype);
1071 if (codec_fn == NULL)
1072 return false;
1074 tracks[track_widx].codec_hid = -1;
1076 if (start_play)
1078 /* Load the codec directly from disk and save some memory. */
1079 track_ridx = track_widx;
1080 ci.filesize = CUR_TI->filesize;
1081 ci.id3 = thistrack_id3;
1082 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1083 ci.curpos = 0;
1084 return codec_load(-1, id3->codectype);
1086 else
1088 /* If we already have another track than this one buffered */
1089 if (track_widx != track_ridx)
1091 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1093 id3 = bufgetid3(tracks[track_widx].id3_hid);
1094 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1096 /* If the previous codec is the same as this one and the current
1097 * one is the correct one, there is no need to put another copy of
1098 * it on the file buffer */
1099 if (id3 && prev_id3)
1101 int codt = get_codec_base_type(id3->codectype);
1102 int prev_codt = get_codec_base_type(prev_id3->codectype);
1103 int cod_loaded = get_codec_base_type(codec_loaded());
1105 if (codt == prev_codt && codt == cod_loaded)
1107 logf("Reusing prev. codec");
1108 return true;
1114 codec_get_full_path(codec_path, codec_fn);
1116 hid = tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1118 /* not an error if codec load it supported, will load it from disk
1119 * application builds don't support it
1121 if (hid < 0 && hid != ERR_UNSUPPORTED_TYPE)
1122 return false;
1124 if (hid >= 0)
1125 logf("Loaded codec");
1126 else
1127 logf("Buffering codec unsupported, load later from disk");
1129 return true;
1132 /* Load metadata for the next track (with bufopen). The rest of the track
1133 loading will be handled by audio_finish_load_track once the metadata has been
1134 actually loaded by the buffering thread. */
1135 static bool audio_load_track(size_t offset, bool start_play)
1137 char name_buf[MAX_PATH + 1];
1138 const char *trackname;
1139 int fd = -1;
1141 if (track_load_started) {
1142 /* There is already a track load in progress, so track_widx hasn't been
1143 incremented yet. Loading another track would overwrite the one that
1144 hasn't finished loading. */
1145 logf("audio_load_track(): a track load is already in progress");
1146 return false;
1149 start_play_g = start_play; /* will be read by audio_finish_load_track */
1151 /* Stop buffer filling if there is no free track entries.
1152 Don't fill up the last track entry (we wan't to store next track
1153 metadata there). */
1154 if (!audio_free_track_count())
1156 logf("No free tracks");
1157 return false;
1160 last_peek_offset++;
1161 tracks[track_widx].taginfo_ready = false;
1163 logf("Buffering track: r%d/w%d", track_ridx, track_widx);
1164 /* Get track name from current playlist read position. */
1165 while ((trackname = playlist_peek(last_peek_offset, name_buf,
1166 sizeof(name_buf))) != NULL)
1168 /* Handle broken playlists. */
1169 fd = open(trackname, O_RDONLY);
1170 if (fd < 0)
1172 logf("Open failed");
1173 /* Skip invalid entry from playlist. */
1174 playlist_skip_entry(NULL, last_peek_offset);
1176 else
1177 break;
1180 if (!trackname)
1182 logf("End-of-playlist");
1183 memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
1184 filling = STATE_END_OF_PLAYLIST;
1186 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
1188 /* Stop playback if no valid track was found. */
1189 audio_stop_playback();
1192 return false;
1195 tracks[track_widx].filesize = filesize(fd);
1197 if (offset > tracks[track_widx].filesize)
1198 offset = 0;
1200 /* Set default values */
1201 if (start_play)
1203 buf_set_watermark(filebuflen/2);
1204 dsp_configure(ci.dsp, DSP_RESET, 0);
1205 playlist_update_resume_info(audio_current_track());
1208 /* Get track metadata if we don't already have it. */
1209 if (tracks[track_widx].id3_hid < 0)
1211 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL);
1213 if (tracks[track_widx].id3_hid < 0)
1215 /* Buffer is full. */
1216 get_metadata(&unbuffered_id3, fd, trackname);
1217 last_peek_offset--;
1218 close(fd);
1219 logf("buffer is full for now (get metadata)");
1220 filling = STATE_FULL;
1221 return false;
1224 if (track_widx == track_ridx)
1226 /* TODO: Superfluos buffering call? */
1227 buf_request_buffer_handle(tracks[track_widx].id3_hid);
1228 if (bufreadid3(tracks[track_widx].id3_hid, thistrack_id3))
1230 thistrack_id3->offset = offset;
1231 logf("audio_load_track: set offset for %s to %lX\n",
1232 thistrack_id3->title,
1233 offset);
1235 else
1236 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1239 if (start_play)
1241 playlist_update_resume_info(audio_current_track());
1245 close(fd);
1246 track_load_started = true; /* Remember that we've started loading a track */
1247 return true;
1250 #ifdef HAVE_ALBUMART
1251 /* Load any album art for the file */
1252 static void audio_load_albumart(struct mp3entry *track_id3)
1254 int i;
1256 FOREACH_ALBUMART(i)
1258 struct bufopen_bitmap_data user_data;
1259 int hid = ERR_HANDLE_NOT_FOUND;
1261 /* albumart_slots may change during a yield of bufopen,
1262 * but that's no problem */
1263 if (tracks[track_widx].aa_hid[i] >= 0 || !albumart_slots[i].used)
1264 continue;
1266 memset(&user_data, 0, sizeof(user_data));
1267 user_data.dim = &(albumart_slots[i].dim);
1269 /* we can only decode jpeg for embedded AA */
1270 if (track_id3->embed_albumart && track_id3->albumart.type == AA_TYPE_JPG)
1272 user_data.embedded_albumart = &(track_id3->albumart);
1273 hid = bufopen(track_id3->path, 0, TYPE_BITMAP, &user_data);
1276 if (hid < 0 && hid != ERR_BUFFER_FULL)
1278 /* no embedded AA or it couldn't be loaded, try other sources */
1279 char path[MAX_PATH];
1281 if (find_albumart(track_id3, path, sizeof(path),
1282 &(albumart_slots[i].dim)))
1284 user_data.embedded_albumart = NULL;
1285 hid = bufopen(path, 0, TYPE_BITMAP, &user_data);
1289 if (hid == ERR_BUFFER_FULL)
1291 filling = STATE_FULL;
1292 logf("buffer is full for now (get album art)");
1294 else if (hid < 0)
1296 logf("Album art loading failed");
1299 tracks[track_widx].aa_hid[i] = hid;
1302 #endif
1304 /* Second part of the track loading: We now have the metadata available, so we
1305 can load the codec, the album art and finally the audio data.
1306 This is called on the audio thread after the buffering thread calls the
1307 buffering_handle_finished_callback callback. */
1308 static void audio_finish_load_track(void)
1310 size_t file_offset = 0;
1311 size_t offset = 0;
1312 bool start_play = start_play_g;
1314 track_load_started = false;
1316 if (tracks[track_widx].id3_hid < 0) {
1317 logf("No metadata");
1318 return;
1321 struct mp3entry *track_id3;
1323 if (track_widx == track_ridx)
1324 track_id3 = thistrack_id3;
1325 else
1326 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
1328 if (track_id3->length == 0 && track_id3->filesize == 0)
1330 logf("audio_finish_load_track: invalid metadata");
1332 /* Invalid metadata */
1333 bufclose(tracks[track_widx].id3_hid);
1334 tracks[track_widx].id3_hid = -1;
1336 /* Skip invalid entry from playlist. */
1337 playlist_skip_entry(NULL, last_peek_offset--);
1339 /* load next track */
1340 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play);
1341 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1343 return;
1345 /* Try to load a cuesheet for the track */
1346 if (curr_cue)
1348 char cuepath[MAX_PATH];
1349 if (look_for_cuesheet_file(track_id3->path, cuepath))
1351 void *temp;
1352 tracks[track_widx].cuesheet_hid =
1353 bufalloc(NULL, sizeof(struct cuesheet), TYPE_CUESHEET);
1354 if (tracks[track_widx].cuesheet_hid >= 0)
1356 bufgetdata(tracks[track_widx].cuesheet_hid,
1357 sizeof(struct cuesheet), &temp);
1358 struct cuesheet *cuesheet = (struct cuesheet*)temp;
1359 if (!parse_cuesheet(cuepath, cuesheet))
1361 bufclose(tracks[track_widx].cuesheet_hid);
1362 track_id3->cuesheet = NULL;
1368 #ifdef HAVE_ALBUMART
1369 audio_load_albumart(track_id3);
1370 #endif
1372 /* Load the codec. */
1373 if (!audio_loadcodec(start_play))
1375 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1377 /* No space for codec on buffer, not an error */
1378 filling = STATE_FULL;
1379 return;
1382 /* This is an error condition, either no codec was found, or reading
1383 * the codec file failed part way through, either way, skip the track */
1384 /* FIXME: We should not use splashf from audio thread! */
1385 splashf(HZ*2, "No codec for: %s", track_id3->path);
1386 /* Skip invalid entry from playlist. */
1387 playlist_skip_entry(NULL, last_peek_offset);
1388 return;
1391 track_id3->elapsed = 0;
1392 offset = track_id3->offset;
1393 size_t resume_rewind = (global_settings.resume_rewind *
1394 track_id3->bitrate * 1000) / 8;
1396 if (offset < resume_rewind)
1398 offset = 0;
1400 else
1402 offset -= resume_rewind;
1405 enum data_type type = TYPE_PACKET_AUDIO;
1407 switch (track_id3->codectype) {
1408 case AFMT_MPA_L1:
1409 case AFMT_MPA_L2:
1410 case AFMT_MPA_L3:
1411 if (offset > 0) {
1412 file_offset = offset;
1414 break;
1416 case AFMT_WAVPACK:
1417 if (offset > 0) {
1418 file_offset = offset;
1419 track_id3->elapsed = track_id3->length / 2;
1421 break;
1423 case AFMT_NSF:
1424 case AFMT_SPC:
1425 case AFMT_SID:
1426 logf("Loading atomic %d",track_id3->codectype);
1427 type = TYPE_ATOMIC_AUDIO;
1428 break;
1430 default:
1431 /* no special treatment needed */
1432 break;
1435 track_id3->offset = offset;
1437 logf("load track: %s", track_id3->path);
1439 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1440 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1441 else if (track_id3->first_frame_offset)
1442 file_offset = track_id3->first_frame_offset;
1443 else
1444 file_offset = 0;
1446 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type,
1447 NULL);
1449 /* No space left, not an error */
1450 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1452 filling = STATE_FULL;
1453 logf("buffer is full for now (load audio)");
1454 return;
1456 else if (tracks[track_widx].audio_hid < 0)
1458 /* another error, do not continue either */
1459 logf("Could not add audio data handle");
1460 return;
1463 /* All required data is now available for the codec -- unless the
1464 autoresume feature is in effect. In the latter case, the codec
1465 must wait until after PLAYBACK_EVENT_TRACK_BUFFER, which may
1466 generate a resume position. */
1467 #ifdef HAVE_TAGCACHE
1468 if (!global_settings.autoresume_enable || offset)
1469 #endif
1470 tracks[track_widx].taginfo_ready = true;
1472 if (start_play)
1474 ci.curpos=file_offset;
1475 buf_request_buffer_handle(tracks[track_widx].audio_hid);
1478 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
1480 #ifdef HAVE_TAGCACHE
1481 /* In case the autoresume feature has been enabled, finally all
1482 required data is available for the codec. */
1483 if (global_settings.autoresume_enable && !offset)
1484 tracks[track_widx].taginfo_ready = true;
1485 #endif
1487 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1489 /* load next track */
1490 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1491 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1493 return;
1496 static void audio_fill_file_buffer(bool start_play, size_t offset)
1498 trigger_cpu_boost();
1500 /* No need to rebuffer if there are track skips pending,
1501 * however don't cancel buffering on skipping while filling. */
1502 if (ci.new_track != 0 && filling != STATE_FILLING)
1503 return;
1504 filling = STATE_FILLING;
1506 /* Must reset the buffer before use if trashed or voice only - voice
1507 file size shouldn't have changed so we can go straight from
1508 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1509 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1510 audio_reset_buffer();
1512 logf("Starting buffer fill");
1514 if (!start_play)
1515 audio_clear_track_entries();
1517 /* Save the current resume position once. */
1518 playlist_update_resume_info(audio_current_track());
1520 audio_load_track(offset, start_play);
1523 static void audio_rebuffer(void)
1525 logf("Forcing rebuffer");
1527 clear_track_info(CUR_TI);
1529 /* Reset track pointers */
1530 track_widx = track_ridx;
1531 audio_clear_track_entries();
1533 /* Reset a possibly interrupted track load */
1534 track_load_started = false;
1536 /* Fill the buffer */
1537 last_peek_offset = -1;
1538 ci.curpos = 0;
1540 if (!CUR_TI->taginfo_ready)
1541 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1543 audio_fill_file_buffer(false, 0);
1546 /* Called on request from the codec to get a new track. This is the codec part
1547 of the track transition. */
1548 static void audio_last_track(bool automatic)
1550 if (automatic)
1552 ci.new_track = 0;
1553 automatic_skip = false;
1555 if (filling != STATE_ENDING)
1557 /* Monitor remaining PCM before stopping */
1558 filling = STATE_ENDING;
1559 pcmbuf_monitor_track_change(true);
1562 codec_stop();
1564 else
1566 audio_stop_playback();
1570 static void audio_check_new_track(void)
1572 int track_count;
1573 int old_track_ridx;
1574 int i, idx;
1575 bool forward;
1576 struct mp3entry *temp;
1578 if (ci.new_track == 0)
1580 ci.new_track++;
1581 automatic_skip = true;
1584 track_count = audio_track_count();
1585 old_track_ridx = track_ridx;
1587 /* Now it's good time to send track finish events. */
1588 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1589 /* swap the mp3entry pointers */
1590 temp = thistrack_id3;
1591 thistrack_id3 = othertrack_id3;
1592 othertrack_id3 = temp;
1593 ci.id3 = thistrack_id3;
1594 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1596 if (dir_skip)
1598 dir_skip = false;
1599 /* regardless of the return value we need to rebuffer.
1600 if it fails the old playlist will resume, else the
1601 next dir will start playing */
1602 playlist_next_dir(ci.new_track);
1603 ci.new_track = 0;
1604 audio_rebuffer();
1605 goto skip_done;
1608 if (new_playlist)
1609 ci.new_track = 0;
1611 /* If the playlist isn't that big */
1612 if (automatic_skip)
1614 while (!playlist_check(ci.new_track))
1616 if (ci.new_track >= 0)
1618 audio_last_track(true);
1619 return;
1621 ci.new_track++;
1625 /* Update the playlist */
1626 last_peek_offset -= ci.new_track;
1628 if (playlist_next(ci.new_track) < 0)
1630 /* End of list */
1631 audio_last_track(automatic_skip);
1632 return;
1635 if (new_playlist)
1637 ci.new_track = 1;
1638 new_playlist = false;
1641 /* Save a pointer to the old track to allow later clearing */
1642 prev_ti = CUR_TI;
1644 for (i = 0; i < ci.new_track; i++)
1646 idx = (track_ridx + i) & MAX_TRACK_MASK;
1647 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid);
1648 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid);
1649 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset)
1651 /* We don't have all the audio data for that track, so clear it,
1652 but keep the metadata. */
1653 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
1655 tracks[idx].audio_hid = -1;
1656 tracks[idx].filesize = 0;
1661 /* Move to the new track */
1662 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
1663 buf_set_base_handle(CUR_TI->audio_hid);
1665 if (automatic_skip)
1667 wps_offset = -ci.new_track;
1670 /* If it is not safe to even skip this many track entries */
1671 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
1673 ci.new_track = 0;
1674 audio_rebuffer();
1675 goto skip_done;
1678 forward = ci.new_track > 0;
1679 ci.new_track = 0;
1681 /* If the target track is clearly not in memory */
1682 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
1684 audio_rebuffer();
1685 goto skip_done;
1688 /* When skipping backwards, it is possible that we've found a track that's
1689 * buffered, but which is around the track-wrap and therefore not the track
1690 * we are looking for */
1691 if (!forward)
1693 int cur_idx = track_ridx;
1694 bool taginfo_ready = true;
1695 /* We've wrapped the buffer backwards if new > old */
1696 bool wrap = track_ridx > old_track_ridx;
1698 while (1)
1700 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1702 /* if we've advanced past the wrap when cur_idx is zeroed */
1703 if (!cur_idx)
1704 wrap = false;
1706 /* if we aren't still on the wrap and we've caught the old track */
1707 if (!(wrap || cur_idx < old_track_ridx))
1708 break;
1710 /* If we hit a track in between without valid tag info, bail */
1711 if (!tracks[cur_idx].taginfo_ready)
1713 taginfo_ready = false;
1714 break;
1717 if (!taginfo_ready)
1719 audio_rebuffer();
1723 skip_done:
1724 audio_update_trackinfo();
1725 pcmbuf_start_track_change(automatic_skip);
1727 if (get_codec_base_type(codec_loaded()) ==
1728 get_codec_base_type(thistrack_id3->codectype))
1730 /* codec is the same base type */
1731 logf("New track loaded");
1732 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE, false);
1734 else
1736 /* a codec change is required */
1737 logf("New codec: %d/%d", thistrack_id3->codectype, codec_loaded());
1738 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE, true);
1739 codec_load(tracks[track_ridx].codec_hid, thistrack_id3->codectype);
1740 tracks[track_ridx].codec_hid = -1; /* Codec thread will close it */
1744 unsigned long audio_prev_elapsed(void)
1746 return prev_track_elapsed;
1749 void audio_set_prev_elapsed(unsigned long setting)
1751 prev_track_elapsed = setting;
1754 /* Stop the codec and reset the PCM buffer */
1755 static void audio_stop_codec_flush(void)
1757 bool pcm_playing;
1759 pcmbuf_pause(true);
1761 codec_stop();
1763 pcm_play_lock();
1765 pcm_playing = pcm_is_playing();
1767 pcmbuf_play_stop();
1768 queue_clear(&pcmbuf_queue);
1770 if (pcm_playing)
1771 pcmbuf_pause(paused);
1773 pcm_play_unlock();
1776 static void audio_stop_playback(void)
1778 if (playing)
1780 /* If we were playing, save resume information */
1781 struct mp3entry *id3 = NULL;
1783 if (!ci.stop_codec)
1784 id3 = audio_current_track();
1786 /* Save the current playing spot, or NULL if the playlist has ended */
1787 playlist_update_resume_info(id3);
1789 /* Now it's good time to send track finish events. Do this
1790 only if this hasn't been done already as part of a track
1791 switch. */
1792 if (id3 == thistrack_id3)
1793 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1795 /* TODO: Create auto bookmark too? */
1797 prev_track_elapsed = othertrack_id3->elapsed;
1799 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
1802 audio_stop_codec_flush();
1803 paused = false;
1804 playing = false;
1805 track_load_started = false;
1807 filling = STATE_IDLE;
1809 /* Mark all entries null. */
1810 audio_clear_track_entries();
1812 /* Close all tracks */
1813 audio_release_tracks();
1816 static void audio_play_start(size_t offset)
1818 int i;
1820 send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL);
1821 #if INPUT_SRC_CAPS != 0
1822 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1823 audio_set_output_source(AUDIO_SRC_PLAYBACK);
1824 #endif
1826 paused = false;
1827 audio_stop_codec_flush();
1829 playing = true;
1830 track_load_started = false;
1832 ci.new_track = 0;
1833 ci.seek_time = 0;
1834 wps_offset = 0;
1836 #ifndef PLATFORM_HAS_VOLUME_CHANGE
1837 sound_set_volume(global_settings.volume);
1838 #endif
1839 track_widx = track_ridx = 0;
1840 buf_set_base_handle(-1);
1842 /* Clear all track entries. */
1843 for (i = 0; i < MAX_TRACK; i++) {
1844 clear_track_info(&tracks[i]);
1847 last_peek_offset = -1;
1849 /* Officially playing */
1850 queue_reply(&audio_queue, 1);
1852 audio_fill_file_buffer(true, offset);
1854 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
1856 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1857 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1861 /* Invalidates all but currently playing track. */
1862 static void audio_invalidate_tracks(void)
1864 if (audio_have_tracks())
1866 last_peek_offset = 0;
1867 track_widx = track_ridx;
1869 /* Mark all other entries null (also buffered wrong metadata). */
1870 audio_clear_track_entries();
1872 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1874 audio_fill_file_buffer(false, 0);
1875 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1879 static void audio_new_playlist(void)
1881 /* Prepare to start a new fill from the beginning of the playlist */
1882 last_peek_offset = -1;
1884 /* Signal the codec to initiate a track change forward */
1885 new_playlist = true;
1886 ci.new_track = 1;
1888 if (audio_have_tracks())
1890 if (paused)
1891 skipped_during_pause = true;
1892 track_widx = track_ridx;
1893 audio_clear_track_entries();
1895 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1897 /* Mark the current track as invalid to prevent skipping back to it */
1898 CUR_TI->taginfo_ready = false;
1901 /* Officially playing */
1902 queue_reply(&audio_queue, 1);
1904 audio_fill_file_buffer(false, 0);
1907 /* Called on manual track skip */
1908 static void audio_initiate_track_change(long direction)
1910 logf("audio_initiate_track_change(%ld)", direction);
1912 ci.new_track += direction;
1913 wps_offset -= direction;
1914 if (paused)
1915 skipped_during_pause = true;
1918 /* Called on manual dir skip */
1919 static void audio_initiate_dir_change(long direction)
1921 dir_skip = true;
1922 ci.new_track = direction;
1923 if (paused)
1924 skipped_during_pause = true;
1927 /* Called when PCM track change is complete */
1928 static void audio_finalise_track_change(void)
1930 logf("audio_finalise_track_change");
1932 if (automatic_skip)
1934 wps_offset = 0;
1935 automatic_skip = false;
1937 /* Invalidate prevtrack_id3 */
1938 memset(othertrack_id3, 0, sizeof(struct mp3entry));
1940 if (prev_ti && prev_ti->audio_hid < 0)
1942 /* No audio left so we clear all the track info. */
1943 clear_track_info(prev_ti);
1946 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1947 playlist_update_resume_info(audio_current_track());
1950 static void audio_seek_complete(void)
1952 logf("audio_seek_complete");
1954 if (!playing)
1955 return;
1957 /* If seeking-while-playing, pcm_is_paused() is true.
1958 * If seeking-while-paused, audio_status PAUSE is true.
1959 * A seamless seek skips this section. */
1960 ci.seek_time = 0;
1962 pcm_play_lock();
1964 if (pcm_is_paused() || paused)
1966 /* Clear the buffer */
1967 pcmbuf_play_stop();
1969 /* If seeking-while-playing, resume PCM playback */
1970 if (!paused)
1971 pcmbuf_pause(false);
1974 pcm_play_unlock();
1977 static void audio_codec_status_message(long reason, int status)
1979 /* TODO: Push the errors up to the normal UI somewhere */
1980 switch (reason)
1982 case Q_CODEC_LOAD_DISK:
1983 case Q_CODEC_LOAD:
1984 if (!playing)
1985 return;
1987 if (status < 0)
1989 splash(HZ*2, "Codec failure");
1990 audio_check_new_track();
1992 break;
1994 #ifdef AUDIO_HAVE_RECORDING
1995 case Q_ENCODER_LOAD_DISK:
1996 if (status < 0)
1997 splash(HZ*2, "Encoder failure");
1998 break;
1999 #endif /* AUDIO_HAVE_RECORDING */
2004 * Layout audio buffer as follows - iram buffer depends on target:
2005 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
2007 static void audio_reset_buffer(void)
2009 /* see audio_get_recording_buffer if this is modified */
2010 logf("audio_reset_buffer");
2012 /* If the setup of anything allocated before the file buffer is
2013 changed, do check the adjustments after the buffer_alloc call
2014 as it will likely be affected and need sliding over */
2016 /* Initially set up file buffer as all space available */
2017 filebuf = audiobuf + talk_get_bufsize();
2018 filebuflen = audiobufend - filebuf;
2020 ALIGN_BUFFER(filebuf, filebuflen, sizeof (intptr_t));
2022 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
2023 size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
2025 /* Make sure filebuflen is a pointer sized multiple after adjustment */
2026 pcmbuf_size = ALIGN_UP(pcmbuf_size, sizeof (intptr_t));
2028 if(pcmbuf_size > filebuflen)
2029 panicf("%s(): EOM (%zu > %zu)", __func__, pcmbuf_size, filebuflen);
2031 filebuflen -= pcmbuf_size;
2032 buffering_reset(filebuf, filebuflen);
2034 /* Clear any references to the file buffer */
2035 buffer_state = AUDIOBUF_STATE_INITIALIZED;
2037 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
2038 /* Make sure everything adds up - yes, some info is a bit redundant but
2039 aids viewing and the sumation of certain variables should add up to
2040 the location of others. */
2042 size_t pcmbufsize;
2043 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
2044 logf("fbuf: %08X", (unsigned)filebuf);
2045 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
2046 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
2047 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
2048 logf("pcmb: %08X", (unsigned)pcmbuf);
2049 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
2051 #endif
2054 static void audio_thread(void)
2056 struct queue_event ev;
2058 pcm_postinit();
2060 audio_thread_ready = true;
2062 while (1)
2064 switch (filling) {
2065 case STATE_IDLE:
2066 queue_wait(&audio_queue, &ev);
2067 break;
2069 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2070 case STATE_USB:
2071 queue_wait(&audio_queue, &ev);
2072 switch (ev.id) {
2073 #ifdef AUDIO_HAVE_RECORDING
2074 /* Must monitor the encoder message for recording so it can
2075 remove it if we process the insertion before it does. It
2076 cannot simply be removed from under recording however. */
2077 case Q_AUDIO_LOAD_ENCODER:
2078 break;
2079 #endif
2080 case SYS_USB_DISCONNECTED:
2081 filling = STATE_IDLE;
2082 default:
2083 continue;
2085 break;
2086 #endif /* CONFIG_PLATFORM */
2088 default:
2089 /* End of buffering, let's calculate the watermark and
2090 unboost */
2091 set_filebuf_watermark();
2092 cancel_cpu_boost();
2093 /* Fall-through */
2094 case STATE_FILLING:
2095 case STATE_ENDING:
2096 if (!pcmbuf_queue_scan(&ev))
2097 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
2098 break;
2101 switch (ev.id) {
2103 case Q_AUDIO_FILL_BUFFER:
2104 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
2105 audio_fill_file_buffer((bool)ev.data, 0);
2106 break;
2108 case Q_AUDIO_FINISH_LOAD:
2109 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2110 audio_finish_load_track();
2111 buf_set_base_handle(CUR_TI->audio_hid);
2112 break;
2114 case Q_AUDIO_PLAY:
2115 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2116 if (playing && ev.data <= 0)
2117 audio_new_playlist();
2118 else
2120 audio_stop_playback();
2121 audio_play_start((size_t)ev.data);
2123 break;
2125 case Q_AUDIO_STOP:
2126 LOGFQUEUE("audio < Q_AUDIO_STOP");
2127 if (playing)
2128 audio_stop_playback();
2129 if (ev.data != 0)
2130 queue_clear(&audio_queue);
2131 break;
2133 case Q_AUDIO_PAUSE:
2134 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2135 if (!(bool) ev.data && skipped_during_pause
2136 #ifdef HAVE_CROSSFADE
2137 && !pcmbuf_is_crossfade_active()
2138 #endif
2140 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2141 skipped_during_pause = false;
2142 if (!playing)
2143 break;
2144 pcmbuf_pause((bool)ev.data);
2145 paused = (bool)ev.data;
2146 break;
2148 case Q_AUDIO_SKIP:
2149 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2150 audio_initiate_track_change((long)ev.data);
2151 break;
2153 case Q_AUDIO_PRE_FF_REWIND:
2154 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2155 if (!playing)
2156 break;
2157 pcmbuf_pause(true);
2158 break;
2160 case Q_AUDIO_FF_REWIND:
2161 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2162 if (!playing)
2163 break;
2165 if (filling == STATE_ENDING)
2167 /* Temp workaround: There is no codec available */
2168 if (!paused)
2169 pcmbuf_pause(false);
2170 break;
2173 if ((long)ev.data == 0)
2175 /* About to restart the track - send track finish
2176 events if not already done. */
2177 if (thistrack_id3 == audio_current_track())
2178 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
2181 if (automatic_skip)
2183 /* An automatic track skip is in progress. Finalize it,
2184 then go back to the previous track */
2185 audio_finalise_track_change();
2186 ci.new_track = -1;
2188 ci.seek_time = (long)ev.data+1;
2189 break;
2191 case Q_AUDIO_CHECK_NEW_TRACK:
2192 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2193 audio_check_new_track();
2194 break;
2196 case Q_AUDIO_DIR_SKIP:
2197 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2198 audio_initiate_dir_change(ev.data);
2199 break;
2201 case Q_AUDIO_FLUSH:
2202 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2203 audio_invalidate_tracks();
2204 break;
2206 case Q_AUDIO_TRACK_CHANGED:
2207 /* PCM track change done */
2208 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2209 /* Set new playlist position for resuming. */
2210 playlist_update_resume_index();
2211 if (filling != STATE_ENDING)
2212 audio_finalise_track_change();
2213 else if (playing)
2214 audio_stop_playback();
2215 break;
2217 case Q_AUDIO_SEEK_COMPLETE:
2218 /* Codec seek done */
2219 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
2220 audio_seek_complete();
2221 codec_ack_msg(Q_AUDIO_SEEK_COMPLETE, false);
2222 break;
2224 case Q_CODEC_LOAD:
2225 case Q_CODEC_LOAD_DISK:
2226 #ifdef AUDIO_HAVE_RECORDING
2227 case Q_ENCODER_LOAD_DISK:
2228 #endif
2229 /* These are received when a codec has finished normally or
2230 upon a codec error */
2231 audio_codec_status_message(ev.id, ev.data);
2232 break;
2234 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2235 case SYS_USB_CONNECTED:
2236 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2237 if (playing)
2238 audio_stop_playback();
2239 #ifdef PLAYBACK_VOICE
2240 voice_stop();
2241 #endif
2242 filling = STATE_USB;
2243 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2244 break;
2245 #endif
2247 #ifdef AUDIO_HAVE_RECORDING
2248 case Q_AUDIO_LOAD_ENCODER:
2249 if (playing)
2250 audio_stop_playback();
2251 else
2252 codec_stop(); /* If encoder still loaded, stop it */
2254 if (ev.data == AFMT_UNKNOWN)
2255 break;
2257 queue_reply(&audio_queue,
2258 codec_load(-1, ev.data | CODEC_TYPE_ENCODER));
2259 break;
2260 #endif /* AUDIO_HAVE_RECORDING */
2262 case SYS_TIMEOUT:
2263 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2264 break;
2266 default:
2267 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2268 break;
2269 } /* end switch */
2270 } /* end while */
2273 /* Initialize the audio system - called from init() in main.c.
2274 * Last function because of all the references to internal symbols
2276 void audio_init(void)
2278 unsigned int audio_thread_id;
2280 /* Can never do this twice */
2281 if (audio_is_initialized)
2283 logf("audio: already initialized");
2284 return;
2287 logf("audio: initializing");
2289 /* Initialize queues before giving control elsewhere in case it likes
2290 to send messages. Thread creation will be delayed however so nothing
2291 starts running until ready if something yields such as talk_init. */
2292 queue_init(&audio_queue, true);
2293 queue_init(&pcmbuf_queue, false);
2295 pcm_init();
2297 codec_init_codec_api();
2299 thistrack_id3 = &mp3entry_buf[0];
2300 othertrack_id3 = &mp3entry_buf[1];
2302 /* cuesheet support */
2303 if (global_settings.cuesheet)
2304 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2306 /* initialize the buffer */
2307 filebuf = audiobuf;
2309 /* audio_reset_buffer must to know the size of voice buffer so init
2310 talk first */
2311 talk_init();
2313 make_codec_thread();
2315 audio_thread_id = create_thread(audio_thread, audio_stack,
2316 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2317 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
2318 IF_COP(, CPU));
2320 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
2321 audio_thread_id);
2323 #ifdef PLAYBACK_VOICE
2324 voice_thread_init();
2325 #endif
2327 #ifdef HAVE_CROSSFADE
2328 /* Set crossfade setting for next buffer init which should be about... */
2329 pcmbuf_request_crossfade_enable(global_settings.crossfade);
2330 #endif
2332 /* initialize the buffering system */
2334 buffering_init();
2335 /* ...now! Set up the buffers */
2336 audio_reset_buffer();
2338 int i;
2339 for(i = 0; i < MAX_TRACK; i++)
2341 tracks[i].audio_hid = -1;
2342 tracks[i].id3_hid = -1;
2343 tracks[i].codec_hid = -1;
2344 tracks[i].cuesheet_hid = -1;
2346 #ifdef HAVE_ALBUMART
2347 FOREACH_ALBUMART(i)
2349 int j;
2350 for (j = 0; j < MAX_TRACK; j++)
2352 tracks[j].aa_hid[i] = -1;
2355 #endif
2357 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2358 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2360 /* Probably safe to say */
2361 audio_is_initialized = true;
2363 sound_settings_apply();
2364 #ifdef HAVE_DISK_STORAGE
2365 audio_set_buffer_margin(global_settings.buffer_margin);
2366 #endif
2368 /* it's safe to let the threads run now */
2369 #ifdef PLAYBACK_VOICE
2370 voice_thread_resume();
2371 #endif
2372 codec_thread_resume();
2373 thread_thaw(audio_thread_id);
2375 } /* audio_init */
2377 bool audio_is_thread_ready(void)
2379 return audio_thread_ready;
2382 size_t audio_get_filebuflen(void)
2384 return filebuflen;
2387 int get_audio_hid()
2389 return CUR_TI->audio_hid;