Remove malloc_buf references from playback.c since it's no longer used for anything...
[kugel-rb.git] / apps / playback.c
blobb72ed8a3b850514beb2fbddce018ed8c931d1d55
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 /**************************************/
237 /** Pcmbuf callbacks */
239 /* Between the codec and PCM track change, we need to keep updating the
240 * "elapsed" value of the previous (to the codec, but current to the
241 * user/PCM/WPS) track, so that the progressbar reaches the end.
242 * During that transition, the WPS will display othertrack_id3. */
243 void audio_pcmbuf_position_callback(unsigned int time)
245 time += othertrack_id3->elapsed;
246 othertrack_id3->elapsed = (time >= othertrack_id3->length)
247 ? othertrack_id3->length : time;
250 /* Post message from pcmbuf that the end of the previous track
251 * has just been played. */
252 void audio_post_track_change(bool pcmbuf)
254 if (pcmbuf)
256 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
257 queue_post(&pcmbuf_queue, Q_AUDIO_TRACK_CHANGED, 0);
259 else
261 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
262 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
266 /* Scan the pcmbuf queue and return true if a message pulled */
267 static bool pcmbuf_queue_scan(struct queue_event *ev)
269 if (!queue_empty(&pcmbuf_queue))
271 /* Transfer message to audio queue */
272 pcm_play_lock();
273 /* Pull message - never, ever any blocking call! */
274 queue_wait_w_tmo(&pcmbuf_queue, ev, 0);
275 pcm_play_unlock();
276 return true;
279 return false;
283 /** Helper functions */
285 static struct mp3entry *bufgetid3(int handle_id)
287 if (handle_id < 0)
288 return NULL;
290 struct mp3entry *id3;
291 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
293 if (ret != sizeof(struct mp3entry))
294 return NULL;
296 return id3;
299 static bool bufreadid3(int handle_id, struct mp3entry *id3out)
301 struct mp3entry *id3 = bufgetid3(handle_id);
303 if (id3)
305 copy_mp3entry(id3out, id3);
306 return true;
309 return false;
312 static bool clear_track_info(struct track_info *track)
314 /* bufclose returns true if the handle is not found, or if it is closed
315 * successfully, so these checks are safe on non-existant handles */
316 if (!track)
317 return false;
319 if (track->codec_hid >= 0) {
320 if (bufclose(track->codec_hid))
321 track->codec_hid = -1;
322 else
323 return false;
326 if (track->id3_hid >= 0) {
327 if (bufclose(track->id3_hid))
328 track->id3_hid = -1;
329 else
330 return false;
333 if (track->audio_hid >= 0) {
334 if (bufclose(track->audio_hid))
335 track->audio_hid = -1;
336 else
337 return false;
340 #ifdef HAVE_ALBUMART
342 int i;
343 FOREACH_ALBUMART(i)
345 if (track->aa_hid[i] >= 0) {
346 if (bufclose(track->aa_hid[i]))
347 track->aa_hid[i] = -1;
348 else
349 return false;
353 #endif
355 if (track->cuesheet_hid >= 0) {
356 if (bufclose(track->cuesheet_hid))
357 track->cuesheet_hid = -1;
358 else
359 return false;
362 track->filesize = 0;
363 track->taginfo_ready = false;
365 return true;
368 /* --- External interfaces --- */
370 /* This sends a stop message and the audio thread will dump all it's
371 subsequenct messages */
372 void audio_hard_stop(void)
374 /* Stop playback */
375 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
376 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
377 #ifdef PLAYBACK_VOICE
378 voice_stop();
379 #endif
382 bool audio_restore_playback(int type)
384 switch (type)
386 case AUDIO_WANT_PLAYBACK:
387 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
388 audio_reset_buffer();
389 return true;
390 case AUDIO_WANT_VOICE:
391 if (buffer_state == AUDIOBUF_STATE_TRASHED)
392 audio_reset_buffer();
393 return true;
394 default:
395 return false;
399 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
401 unsigned char *buf, *end;
403 if (audio_is_initialized)
405 audio_hard_stop();
407 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
409 /* Reset the buffering thread so that it doesn't try to use the data */
410 buffering_reset(filebuf, filebuflen);
412 if (buffer_size == NULL)
414 /* Special case for talk_init to use since it already knows it's
415 trashed */
416 buffer_state = AUDIOBUF_STATE_TRASHED;
417 return NULL;
420 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
421 || !talk_voice_required())
423 logf("get buffer: talk, audio");
424 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
425 the talk buffer is not needed because voice isn't being used, or
426 could be AUDIOBUF_STATE_TRASHED already. If state is
427 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
428 without the caller knowing what's going on. Changing certain settings
429 may move it to a worse condition but the memory in use by something
430 else will remain undisturbed.
432 if (buffer_state != AUDIOBUF_STATE_TRASHED)
434 talk_buffer_steal();
435 buffer_state = AUDIOBUF_STATE_TRASHED;
438 buf = audiobuf;
439 end = audiobufend;
441 else
443 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
444 still AUDIOBUF_STATE_INITIALIZED */
445 /* Skip talk buffer and move pcm buffer to end to maximize available
446 contiguous memory - no audio running means voice will not need the
447 swap space */
448 logf("get buffer: audio");
449 buf = audiobuf + talk_get_bufsize();
450 end = audiobufend - pcmbuf_init(audiobufend);
451 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
454 *buffer_size = end - buf;
456 return buf;
459 bool audio_buffer_state_trashed(void)
461 return buffer_state == AUDIOBUF_STATE_TRASHED;
464 #ifdef HAVE_RECORDING
465 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
467 /* Stop audio, voice and obtain all available buffer space */
468 audio_hard_stop();
469 talk_buffer_steal();
471 unsigned char *end = audiobufend;
472 buffer_state = AUDIOBUF_STATE_TRASHED;
473 *buffer_size = end - audiobuf;
475 return (unsigned char *)audiobuf;
478 bool audio_load_encoder(int afmt)
480 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
481 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt);
482 return queue_send(&audio_queue, Q_AUDIO_LOAD_ENCODER, afmt) > 0;
483 #else
484 (void)afmt;
485 return true;
486 #endif
487 } /* audio_load_encoder */
489 void audio_remove_encoder(void)
491 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
492 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
493 queue_send(&audio_queue, Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN);
494 #endif
495 } /* audio_remove_encoder */
497 #endif /* HAVE_RECORDING */
500 struct mp3entry* audio_current_track(void)
502 const char *filename;
503 struct playlist_track_info trackinfo;
504 int cur_idx;
505 int offset = ci.new_track + wps_offset;
506 struct mp3entry *write_id3;
508 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
510 if (cur_idx == track_ridx && *thistrack_id3->path)
512 /* The usual case */
513 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
515 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
516 thistrack_id3->cuesheet = curr_cue;
518 return thistrack_id3;
520 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
522 /* We're in a track transition. The codec has moved on to the next track,
523 but the audio being played is still the same (now previous) track.
524 othertrack_id3.elapsed is being updated in an ISR by
525 codec_pcmbuf_position_callback */
526 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
528 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
529 othertrack_id3->cuesheet = curr_cue;
531 return othertrack_id3;
534 if (offset != 0)
536 /* Codec may be using thistrack_id3, so it must not be overwritten.
537 If this is a manual skip, othertrack_id3 will become
538 thistrack_id3 in audio_check_new_track().
539 FIXME: If this is an automatic skip, it probably means multiple
540 short tracks fit in the PCM buffer. Overwriting othertrack_id3
541 can lead to an incorrect value later.
542 Note that othertrack_id3 may also be used for next track.
544 write_id3 = othertrack_id3;
546 else
548 write_id3 = thistrack_id3;
551 if (tracks[cur_idx].id3_hid >= 0)
553 /* The current track's info has been buffered but not read yet, so get it */
554 if (bufreadid3(tracks[cur_idx].id3_hid, write_id3))
555 return write_id3;
558 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
559 we have and return that. */
561 memset(write_id3, 0, sizeof(struct mp3entry));
563 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo);
564 filename = trackinfo.filename;
565 if (!filename)
566 filename = "No file!";
568 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
569 if (tagcache_fill_tags(write_id3, filename))
570 return write_id3;
571 #endif
573 strlcpy(write_id3->path, filename, sizeof(write_id3->path));
574 write_id3->title = strrchr(write_id3->path, '/');
575 if (!write_id3->title)
576 write_id3->title = &write_id3->path[0];
577 else
578 write_id3->title++;
580 return write_id3;
583 struct mp3entry* audio_next_track(void)
585 int next_idx;
586 int offset = ci.new_track + wps_offset;
588 if (!audio_have_tracks())
589 return NULL;
591 if (wps_offset == -1 && *thistrack_id3->path)
593 /* We're in a track transition. The next track for the WPS is the one
594 currently being decoded. */
595 return thistrack_id3;
598 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
600 if (tracks[next_idx].id3_hid >= 0)
602 if (bufreadid3(tracks[next_idx].id3_hid, othertrack_id3))
603 return othertrack_id3;
604 else
605 return NULL;
608 if (next_idx == track_widx)
610 /* The next track hasn't been buffered yet, so we return the static
611 version of its metadata. */
612 return &unbuffered_id3;
615 return NULL;
618 /* gets a copy of the id3 data */
619 bool audio_peek_track(struct mp3entry* id3, int offset)
621 int next_idx;
622 int new_offset = ci.new_track + wps_offset + offset;
624 if (!audio_have_tracks())
625 return false;
626 next_idx = (track_ridx + new_offset) & MAX_TRACK_MASK;
628 if (tracks[next_idx].id3_hid >= 0)
629 return bufreadid3(tracks[next_idx].id3_hid, id3);
631 return false;
634 #ifdef HAVE_ALBUMART
636 int playback_current_aa_hid(int slot)
638 if (slot < 0)
639 return -1;
640 int cur_idx;
641 int offset = ci.new_track + wps_offset;
643 cur_idx = track_ridx + offset;
644 cur_idx &= MAX_TRACK_MASK;
645 return tracks[cur_idx].aa_hid[slot];
648 int playback_claim_aa_slot(struct dim *dim)
650 int i;
652 /* first try to find a slot already having the size to reuse it
653 * since we don't want albumart of the same size buffered multiple times */
654 FOREACH_ALBUMART(i)
656 struct albumart_slot *slot = &albumart_slots[i];
657 if (slot->dim.width == dim->width
658 && slot->dim.height == dim->height)
660 slot->used++;
661 return i;
664 /* size is new, find a free slot */
665 FOREACH_ALBUMART(i)
667 if (!albumart_slots[i].used)
669 albumart_slots[i].used++;
670 albumart_slots[i].dim = *dim;
671 return i;
674 /* sorry, no free slot */
675 return -1;
678 void playback_release_aa_slot(int slot)
680 /* invalidate the albumart_slot */
681 struct albumart_slot *aa_slot = &albumart_slots[slot];
683 if (aa_slot->used > 0)
684 aa_slot->used--;
687 #endif
688 void audio_play(long offset)
690 logf("audio_play");
692 #ifdef PLAYBACK_VOICE
693 /* Truncate any existing voice output so we don't have spelling
694 * etc. over the first part of the played track */
695 talk_force_shutup();
696 #endif
698 /* Start playback */
699 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
700 /* Don't return until playback has actually started */
701 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
704 void audio_stop(void)
706 /* Stop playback */
707 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
708 /* Don't return until playback has actually stopped */
709 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
712 void audio_pause(void)
714 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
715 /* Don't return until playback has actually paused */
716 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
719 void audio_resume(void)
721 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
722 /* Don't return until playback has actually resumed */
723 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
726 void audio_skip(int direction)
728 if (playlist_check(ci.new_track + wps_offset + direction))
730 if (global_settings.beep)
731 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
733 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction);
734 queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
735 /* Update wps while our message travels inside deep playback queues. */
736 wps_offset += direction;
738 else
740 /* No more tracks. */
741 if (global_settings.beep)
742 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
746 void audio_next(void)
748 audio_skip(1);
751 void audio_prev(void)
753 audio_skip(-1);
756 void audio_next_dir(void)
758 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
759 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
762 void audio_prev_dir(void)
764 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
765 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
768 void audio_pre_ff_rewind(void)
770 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
771 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
774 void audio_ff_rewind(long newpos)
776 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
777 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
780 void audio_flush_and_reload_tracks(void)
782 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
783 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
786 void audio_error_clear(void)
788 #ifdef AUDIO_HAVE_RECORDING
789 pcm_rec_error_clear();
790 #endif
793 int audio_status(void)
795 int ret = 0;
797 if (playing)
798 ret |= AUDIO_STATUS_PLAY;
800 if (paused)
801 ret |= AUDIO_STATUS_PAUSE;
803 #ifdef HAVE_RECORDING
804 /* Do this here for constitency with mpeg.c version */
805 /* FIXME: pcm_rec_status() is deprecated */
806 ret |= pcm_rec_status();
807 #endif
809 return ret;
812 bool audio_automatic_skip(void)
814 return automatic_skip;
817 int audio_get_file_pos(void)
819 return 0;
822 #ifdef HAVE_DISK_STORAGE
823 void audio_set_buffer_margin(int setting)
825 static const unsigned short lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
826 buffer_margin = lookup[setting];
827 logf("buffer margin: %ld", (long)buffer_margin);
828 set_filebuf_watermark();
830 #endif
832 #ifdef HAVE_CROSSFADE
833 /* Take necessary steps to enable or disable the crossfade setting */
834 void audio_set_crossfade(int enable)
836 size_t offset;
837 bool was_playing;
838 size_t size;
840 /* Tell it the next setting to use */
841 pcmbuf_request_crossfade_enable(enable);
843 /* Return if size hasn't changed or this is too early to determine
844 which in the second case there's no way we could be playing
845 anything at all */
846 if (pcmbuf_is_same_size()) return;
848 offset = 0;
849 was_playing = playing;
851 /* Playback has to be stopped before changing the buffer size */
852 if (was_playing)
854 /* Store the track resume position */
855 offset = thistrack_id3->offset;
858 /* Blast it - audio buffer will have to be setup again next time
859 something plays */
860 audio_get_buffer(true, &size);
862 /* Restart playback if audio was running previously */
863 if (was_playing)
864 audio_play(offset);
866 #endif
868 /* --- Routines called from multiple threads --- */
870 static void set_filebuf_watermark(void)
872 if (!filebuf)
873 return; /* Audio buffers not yet set up */
875 #ifdef HAVE_DISK_STORAGE
876 int seconds;
877 int spinup = ata_spinup_time();
878 if (spinup)
879 seconds = (spinup / HZ) + 1;
880 else
881 seconds = 5;
883 seconds += buffer_margin;
884 #else
885 /* flash storage */
886 int seconds = 1;
887 #endif
889 /* bitrate of last track in buffer dictates watermark */
890 struct mp3entry* id3 = NULL;
891 if (tracks[track_widx].taginfo_ready)
892 id3 = bufgetid3(tracks[track_widx].id3_hid);
893 else
894 id3 = bufgetid3(tracks[track_widx-1].id3_hid);
895 if (!id3) {
896 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
897 return;
899 size_t bytes = id3->bitrate * (1000/8) * seconds;
900 buf_set_watermark(bytes);
901 logf("fwmark: %d", bytes);
904 /* --- Buffering callbacks --- */
906 static void buffering_low_buffer_callback(void *data)
908 (void)data;
909 logf("low buffer callback");
911 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) {
912 /* force a refill */
913 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
914 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
918 static void buffering_handle_rebuffer_callback(void *data)
920 (void)data;
921 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
922 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
925 static void buffering_handle_finished_callback(void *data)
927 logf("handle %d finished buffering", *(int*)data);
928 int hid = (*(int*)data);
930 if (hid == tracks[track_widx].id3_hid)
932 int offset = ci.new_track + wps_offset;
933 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
934 /* The metadata handle for the last loaded track has been buffered.
935 We can ask the audio thread to load the rest of the track's data. */
936 LOGFQUEUE("audio > audio Q_AUDIO_FINISH_LOAD");
937 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
938 if (tracks[next_idx].id3_hid == hid)
939 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
941 else
943 /* This is most likely an audio handle, so we strip the useless
944 trailing tags that are left. */
945 strip_tags(hid);
947 if (hid == tracks[track_widx-1].audio_hid
948 && filling == STATE_END_OF_PLAYLIST)
950 /* This was the last track in the playlist.
951 We now have all the data we need. */
952 logf("last track finished buffering");
953 filling = STATE_FINISHED;
959 /* --- Audio thread --- */
961 static bool audio_have_tracks(void)
963 return (audio_track_count() != 0);
966 static int audio_free_track_count(void)
968 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
969 return MAX_TRACK - 1 - audio_track_count();
972 int audio_track_count(void)
974 /* Calculate difference from track_ridx to track_widx
975 * taking into account a possible wrap-around. */
976 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK;
979 long audio_filebufused(void)
981 return (long) buf_used();
984 /* Update track info after successful a codec track change */
985 static void audio_update_trackinfo(void)
987 bool resume = false;
989 /* Load the curent track's metadata into curtrack_id3 */
990 if (CUR_TI->id3_hid >= 0)
991 bufreadid3(CUR_TI->id3_hid, thistrack_id3);
993 /* Reset current position */
994 thistrack_id3->elapsed = 0;
996 #ifdef HAVE_TAGCACHE
997 /* Ignoring resume position for automatic track change if so configured */
998 resume = global_settings.autoresume_enable &&
999 (!automatic_skip /* Resume all manually selected tracks */
1000 || global_settings.autoresume_automatic == AUTORESUME_NEXTTRACK_ALWAYS
1001 || (global_settings.autoresume_automatic != AUTORESUME_NEXTTRACK_NEVER
1002 /* Not never resume? */
1003 && autoresumable(thistrack_id3))); /* Pass Resume filter? */
1004 #endif
1006 if (!resume)
1008 thistrack_id3->offset = 0;
1011 logf("audio_update_trackinfo: Set offset for %s to %lX\n",
1012 thistrack_id3->title, thistrack_id3->offset);
1014 /* Update the codec API */
1015 ci.filesize = CUR_TI->filesize;
1016 ci.id3 = thistrack_id3;
1017 ci.curpos = 0;
1018 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1021 /* Clear tracks between write and read, non inclusive */
1022 static void audio_clear_track_entries(void)
1024 int cur_idx = track_widx;
1026 logf("Clearing tracks: r%d/w%d", track_ridx, track_widx);
1028 /* Loop over all tracks from write-to-read */
1029 while (1)
1031 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1033 if (cur_idx == track_ridx)
1034 break;
1036 clear_track_info(&tracks[cur_idx]);
1040 /* Clear all tracks */
1041 static bool audio_release_tracks(void)
1043 int i, cur_idx;
1045 logf("releasing all tracks");
1047 for(i = 0; i < MAX_TRACK; i++)
1049 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
1050 if (!clear_track_info(&tracks[cur_idx]))
1051 return false;
1054 return true;
1057 static bool audio_loadcodec(bool start_play)
1059 int prev_track, hid;
1060 char codec_path[MAX_PATH]; /* Full path to codec */
1061 const struct mp3entry *id3, *prev_id3;
1063 if (tracks[track_widx].id3_hid < 0) {
1064 return false;
1067 id3 = bufgetid3(tracks[track_widx].id3_hid);
1068 if (!id3)
1069 return false;
1071 const char *codec_fn = get_codec_filename(id3->codectype);
1072 if (codec_fn == NULL)
1073 return false;
1075 tracks[track_widx].codec_hid = -1;
1077 if (start_play)
1079 /* Load the codec directly from disk and save some memory. */
1080 track_ridx = track_widx;
1081 ci.filesize = CUR_TI->filesize;
1082 ci.id3 = thistrack_id3;
1083 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1084 ci.curpos = 0;
1085 return codec_load(-1, id3->codectype);
1087 else
1089 /* If we already have another track than this one buffered */
1090 if (track_widx != track_ridx)
1092 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1094 id3 = bufgetid3(tracks[track_widx].id3_hid);
1095 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1097 /* If the previous codec is the same as this one and the current
1098 * one is the correct one, there is no need to put another copy of
1099 * it on the file buffer */
1100 if (id3 && prev_id3)
1102 int codt = get_codec_base_type(id3->codectype);
1103 int prev_codt = get_codec_base_type(prev_id3->codectype);
1104 int cod_loaded = get_codec_base_type(codec_loaded());
1106 if (codt == prev_codt && codt == cod_loaded)
1108 logf("Reusing prev. codec");
1109 return true;
1115 codec_get_full_path(codec_path, codec_fn);
1117 hid = tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1119 /* not an error if codec load it supported, will load it from disk
1120 * application builds don't support it
1122 if (hid < 0 && hid != ERR_UNSUPPORTED_TYPE)
1123 return false;
1125 if (hid >= 0)
1126 logf("Loaded codec");
1127 else
1128 logf("Buffering codec unsupported, load later from disk");
1130 return true;
1133 /* Load metadata for the next track (with bufopen). The rest of the track
1134 loading will be handled by audio_finish_load_track once the metadata has been
1135 actually loaded by the buffering thread. */
1136 static bool audio_load_track(size_t offset, bool start_play)
1138 char name_buf[MAX_PATH + 1];
1139 const char *trackname;
1140 int fd = -1;
1142 if (track_load_started) {
1143 /* There is already a track load in progress, so track_widx hasn't been
1144 incremented yet. Loading another track would overwrite the one that
1145 hasn't finished loading. */
1146 logf("audio_load_track(): a track load is already in progress");
1147 return false;
1150 start_play_g = start_play; /* will be read by audio_finish_load_track */
1152 /* Stop buffer filling if there is no free track entries.
1153 Don't fill up the last track entry (we wan't to store next track
1154 metadata there). */
1155 if (!audio_free_track_count())
1157 logf("No free tracks");
1158 return false;
1161 last_peek_offset++;
1162 tracks[track_widx].taginfo_ready = false;
1164 logf("Buffering track: r%d/w%d", track_ridx, track_widx);
1165 /* Get track name from current playlist read position. */
1166 while ((trackname = playlist_peek(last_peek_offset, name_buf,
1167 sizeof(name_buf))) != NULL)
1169 /* Handle broken playlists. */
1170 fd = open(trackname, O_RDONLY);
1171 if (fd < 0)
1173 logf("Open failed");
1174 /* Skip invalid entry from playlist. */
1175 playlist_skip_entry(NULL, last_peek_offset);
1177 else
1178 break;
1181 if (!trackname)
1183 logf("End-of-playlist");
1184 memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
1185 filling = STATE_END_OF_PLAYLIST;
1187 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
1189 /* Stop playback if no valid track was found. */
1190 audio_stop_playback();
1193 return false;
1196 tracks[track_widx].filesize = filesize(fd);
1198 if (offset > tracks[track_widx].filesize)
1199 offset = 0;
1201 /* Set default values */
1202 if (start_play)
1204 buf_set_watermark(filebuflen/2);
1205 dsp_configure(ci.dsp, DSP_RESET, 0);
1206 playlist_update_resume_info(audio_current_track());
1209 /* Get track metadata if we don't already have it. */
1210 if (tracks[track_widx].id3_hid < 0)
1212 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL);
1214 if (tracks[track_widx].id3_hid < 0)
1216 /* Buffer is full. */
1217 get_metadata(&unbuffered_id3, fd, trackname);
1218 last_peek_offset--;
1219 close(fd);
1220 logf("buffer is full for now (get metadata)");
1221 filling = STATE_FULL;
1222 return false;
1225 if (track_widx == track_ridx)
1227 /* TODO: Superfluos buffering call? */
1228 buf_request_buffer_handle(tracks[track_widx].id3_hid);
1229 if (bufreadid3(tracks[track_widx].id3_hid, thistrack_id3))
1231 thistrack_id3->offset = offset;
1232 logf("audio_load_track: set offset for %s to %lX\n",
1233 thistrack_id3->title,
1234 offset);
1236 else
1237 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1240 if (start_play)
1242 playlist_update_resume_info(audio_current_track());
1246 close(fd);
1247 track_load_started = true; /* Remember that we've started loading a track */
1248 return true;
1251 #ifdef HAVE_ALBUMART
1252 /* Load any album art for the file */
1253 static void audio_load_albumart(struct mp3entry *track_id3)
1255 int i;
1257 FOREACH_ALBUMART(i)
1259 struct bufopen_bitmap_data user_data;
1260 int hid = ERR_HANDLE_NOT_FOUND;
1262 /* albumart_slots may change during a yield of bufopen,
1263 * but that's no problem */
1264 if (tracks[track_widx].aa_hid[i] >= 0 || !albumart_slots[i].used)
1265 continue;
1267 memset(&user_data, 0, sizeof(user_data));
1268 user_data.dim = &(albumart_slots[i].dim);
1270 /* we can only decode jpeg for embedded AA */
1271 if (track_id3->embed_albumart && track_id3->albumart.type == AA_TYPE_JPG)
1273 user_data.embedded_albumart = &(track_id3->albumart);
1274 hid = bufopen(track_id3->path, 0, TYPE_BITMAP, &user_data);
1277 if (hid < 0 && hid != ERR_BUFFER_FULL)
1279 /* no embedded AA or it couldn't be loaded, try other sources */
1280 char path[MAX_PATH];
1282 if (find_albumart(track_id3, path, sizeof(path),
1283 &(albumart_slots[i].dim)))
1285 user_data.embedded_albumart = NULL;
1286 hid = bufopen(path, 0, TYPE_BITMAP, &user_data);
1290 if (hid == ERR_BUFFER_FULL)
1292 filling = STATE_FULL;
1293 logf("buffer is full for now (get album art)");
1295 else if (hid < 0)
1297 logf("Album art loading failed");
1300 tracks[track_widx].aa_hid[i] = hid;
1303 #endif
1305 /* Second part of the track loading: We now have the metadata available, so we
1306 can load the codec, the album art and finally the audio data.
1307 This is called on the audio thread after the buffering thread calls the
1308 buffering_handle_finished_callback callback. */
1309 static void audio_finish_load_track(void)
1311 size_t file_offset = 0;
1312 size_t offset = 0;
1313 bool start_play = start_play_g;
1315 track_load_started = false;
1317 if (tracks[track_widx].id3_hid < 0) {
1318 logf("No metadata");
1319 return;
1322 struct mp3entry *track_id3;
1324 if (track_widx == track_ridx)
1325 track_id3 = thistrack_id3;
1326 else
1327 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
1329 if (track_id3->length == 0 && track_id3->filesize == 0)
1331 logf("audio_finish_load_track: invalid metadata");
1333 /* Invalid metadata */
1334 bufclose(tracks[track_widx].id3_hid);
1335 tracks[track_widx].id3_hid = -1;
1337 /* Skip invalid entry from playlist. */
1338 playlist_skip_entry(NULL, last_peek_offset--);
1340 /* load next track */
1341 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play);
1342 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1344 return;
1346 /* Try to load a cuesheet for the track */
1347 if (curr_cue)
1349 char cuepath[MAX_PATH];
1350 if (look_for_cuesheet_file(track_id3->path, cuepath))
1352 void *temp;
1353 tracks[track_widx].cuesheet_hid =
1354 bufalloc(NULL, sizeof(struct cuesheet), TYPE_CUESHEET);
1355 if (tracks[track_widx].cuesheet_hid >= 0)
1357 bufgetdata(tracks[track_widx].cuesheet_hid,
1358 sizeof(struct cuesheet), &temp);
1359 struct cuesheet *cuesheet = (struct cuesheet*)temp;
1360 if (!parse_cuesheet(cuepath, cuesheet))
1362 bufclose(tracks[track_widx].cuesheet_hid);
1363 track_id3->cuesheet = NULL;
1369 #ifdef HAVE_ALBUMART
1370 audio_load_albumart(track_id3);
1371 #endif
1373 /* Load the codec. */
1374 if (!audio_loadcodec(start_play))
1376 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1378 /* No space for codec on buffer, not an error */
1379 filling = STATE_FULL;
1380 return;
1383 /* This is an error condition, either no codec was found, or reading
1384 * the codec file failed part way through, either way, skip the track */
1385 /* FIXME: We should not use splashf from audio thread! */
1386 splashf(HZ*2, "No codec for: %s", track_id3->path);
1387 /* Skip invalid entry from playlist. */
1388 playlist_skip_entry(NULL, last_peek_offset);
1389 return;
1392 track_id3->elapsed = 0;
1393 offset = track_id3->offset;
1394 size_t resume_rewind = (global_settings.resume_rewind *
1395 track_id3->bitrate * 1000) / 8;
1397 if (offset < resume_rewind)
1399 offset = 0;
1401 else
1403 offset -= resume_rewind;
1406 enum data_type type = TYPE_PACKET_AUDIO;
1408 switch (track_id3->codectype) {
1409 case AFMT_MPA_L1:
1410 case AFMT_MPA_L2:
1411 case AFMT_MPA_L3:
1412 if (offset > 0) {
1413 file_offset = offset;
1415 break;
1417 case AFMT_WAVPACK:
1418 if (offset > 0) {
1419 file_offset = offset;
1420 track_id3->elapsed = track_id3->length / 2;
1422 break;
1424 case AFMT_NSF:
1425 case AFMT_SPC:
1426 case AFMT_SID:
1427 logf("Loading atomic %d",track_id3->codectype);
1428 type = TYPE_ATOMIC_AUDIO;
1429 break;
1431 default:
1432 /* no special treatment needed */
1433 break;
1436 track_id3->offset = offset;
1438 logf("load track: %s", track_id3->path);
1440 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1441 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1442 else if (track_id3->first_frame_offset)
1443 file_offset = track_id3->first_frame_offset;
1444 else
1445 file_offset = 0;
1447 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type,
1448 NULL);
1450 /* No space left, not an error */
1451 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1453 filling = STATE_FULL;
1454 logf("buffer is full for now (load audio)");
1455 return;
1457 else if (tracks[track_widx].audio_hid < 0)
1459 /* another error, do not continue either */
1460 logf("Could not add audio data handle");
1461 return;
1464 /* All required data is now available for the codec -- unless the
1465 autoresume feature is in effect. In the latter case, the codec
1466 must wait until after PLAYBACK_EVENT_TRACK_BUFFER, which may
1467 generate a resume position. */
1468 #ifdef HAVE_TAGCACHE
1469 if (!global_settings.autoresume_enable || offset)
1470 #endif
1471 tracks[track_widx].taginfo_ready = true;
1473 if (start_play)
1475 ci.curpos=file_offset;
1476 buf_request_buffer_handle(tracks[track_widx].audio_hid);
1479 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
1481 #ifdef HAVE_TAGCACHE
1482 /* In case the autoresume feature has been enabled, finally all
1483 required data is available for the codec. */
1484 if (global_settings.autoresume_enable && !offset)
1485 tracks[track_widx].taginfo_ready = true;
1486 #endif
1488 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1490 /* load next track */
1491 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1492 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1494 return;
1497 static void audio_fill_file_buffer(bool start_play, size_t offset)
1499 trigger_cpu_boost();
1501 /* No need to rebuffer if there are track skips pending,
1502 * however don't cancel buffering on skipping while filling. */
1503 if (ci.new_track != 0 && filling != STATE_FILLING)
1504 return;
1505 filling = STATE_FILLING;
1507 /* Must reset the buffer before use if trashed or voice only - voice
1508 file size shouldn't have changed so we can go straight from
1509 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1510 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1511 audio_reset_buffer();
1513 logf("Starting buffer fill");
1515 if (!start_play)
1516 audio_clear_track_entries();
1518 /* Save the current resume position once. */
1519 playlist_update_resume_info(audio_current_track());
1521 audio_load_track(offset, start_play);
1524 static void audio_rebuffer(void)
1526 logf("Forcing rebuffer");
1528 clear_track_info(CUR_TI);
1530 /* Reset track pointers */
1531 track_widx = track_ridx;
1532 audio_clear_track_entries();
1534 /* Reset a possibly interrupted track load */
1535 track_load_started = false;
1537 /* Fill the buffer */
1538 last_peek_offset = -1;
1539 ci.curpos = 0;
1541 if (!CUR_TI->taginfo_ready)
1542 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1544 audio_fill_file_buffer(false, 0);
1547 /* Called on request from the codec to get a new track. This is the codec part
1548 of the track transition. */
1549 static void audio_last_track(bool automatic)
1551 if (automatic)
1553 ci.new_track = 0;
1554 automatic_skip = false;
1556 if (filling != STATE_ENDING)
1558 /* Monitor remaining PCM before stopping */
1559 filling = STATE_ENDING;
1560 pcmbuf_monitor_track_change(true);
1563 codec_stop();
1565 else
1567 audio_stop_playback();
1571 static void audio_check_new_track(void)
1573 int track_count;
1574 int old_track_ridx;
1575 int i, idx;
1576 bool forward;
1577 struct mp3entry *temp;
1579 if (ci.new_track == 0)
1581 ci.new_track++;
1582 automatic_skip = true;
1585 track_count = audio_track_count();
1586 old_track_ridx = track_ridx;
1588 /* Now it's good time to send track finish events. */
1589 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1590 /* swap the mp3entry pointers */
1591 temp = thistrack_id3;
1592 thistrack_id3 = othertrack_id3;
1593 othertrack_id3 = temp;
1594 ci.id3 = thistrack_id3;
1595 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1597 if (dir_skip)
1599 dir_skip = false;
1600 /* regardless of the return value we need to rebuffer.
1601 if it fails the old playlist will resume, else the
1602 next dir will start playing */
1603 playlist_next_dir(ci.new_track);
1604 ci.new_track = 0;
1605 audio_rebuffer();
1606 goto skip_done;
1609 if (new_playlist)
1610 ci.new_track = 0;
1612 /* If the playlist isn't that big */
1613 if (automatic_skip)
1615 while (!playlist_check(ci.new_track))
1617 if (ci.new_track >= 0)
1619 audio_last_track(true);
1620 return;
1622 ci.new_track++;
1626 /* Update the playlist */
1627 last_peek_offset -= ci.new_track;
1629 if (playlist_next(ci.new_track) < 0)
1631 /* End of list */
1632 audio_last_track(automatic_skip);
1633 return;
1636 if (new_playlist)
1638 ci.new_track = 1;
1639 new_playlist = false;
1642 /* Save a pointer to the old track to allow later clearing */
1643 prev_ti = CUR_TI;
1645 for (i = 0; i < ci.new_track; i++)
1647 idx = (track_ridx + i) & MAX_TRACK_MASK;
1648 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid);
1649 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid);
1650 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset)
1652 /* We don't have all the audio data for that track, so clear it,
1653 but keep the metadata. */
1654 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
1656 tracks[idx].audio_hid = -1;
1657 tracks[idx].filesize = 0;
1662 /* Move to the new track */
1663 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
1664 buf_set_base_handle(CUR_TI->audio_hid);
1666 if (automatic_skip)
1668 wps_offset = -ci.new_track;
1671 /* If it is not safe to even skip this many track entries */
1672 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
1674 ci.new_track = 0;
1675 audio_rebuffer();
1676 goto skip_done;
1679 forward = ci.new_track > 0;
1680 ci.new_track = 0;
1682 /* If the target track is clearly not in memory */
1683 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
1685 audio_rebuffer();
1686 goto skip_done;
1689 /* When skipping backwards, it is possible that we've found a track that's
1690 * buffered, but which is around the track-wrap and therefore not the track
1691 * we are looking for */
1692 if (!forward)
1694 int cur_idx = track_ridx;
1695 bool taginfo_ready = true;
1696 /* We've wrapped the buffer backwards if new > old */
1697 bool wrap = track_ridx > old_track_ridx;
1699 while (1)
1701 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1703 /* if we've advanced past the wrap when cur_idx is zeroed */
1704 if (!cur_idx)
1705 wrap = false;
1707 /* if we aren't still on the wrap and we've caught the old track */
1708 if (!(wrap || cur_idx < old_track_ridx))
1709 break;
1711 /* If we hit a track in between without valid tag info, bail */
1712 if (!tracks[cur_idx].taginfo_ready)
1714 taginfo_ready = false;
1715 break;
1718 if (!taginfo_ready)
1720 audio_rebuffer();
1724 skip_done:
1725 audio_update_trackinfo();
1726 pcmbuf_start_track_change(automatic_skip);
1728 if (get_codec_base_type(codec_loaded()) ==
1729 get_codec_base_type(thistrack_id3->codectype))
1731 /* codec is the same base type */
1732 logf("New track loaded");
1733 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE, false);
1735 else
1737 /* a codec change is required */
1738 logf("New codec: %d/%d", thistrack_id3->codectype, codec_loaded());
1739 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE, true);
1740 codec_load(tracks[track_ridx].codec_hid, thistrack_id3->codectype);
1741 tracks[track_ridx].codec_hid = -1; /* Codec thread will close it */
1745 unsigned long audio_prev_elapsed(void)
1747 return prev_track_elapsed;
1750 void audio_set_prev_elapsed(unsigned long setting)
1752 prev_track_elapsed = setting;
1755 /* Stop the codec and reset the PCM buffer */
1756 static void audio_stop_codec_flush(void)
1758 bool pcm_playing;
1760 pcmbuf_pause(true);
1762 codec_stop();
1764 pcm_play_lock();
1766 pcm_playing = pcm_is_playing();
1768 pcmbuf_play_stop();
1769 queue_clear(&pcmbuf_queue);
1771 if (pcm_playing)
1772 pcmbuf_pause(paused);
1774 pcm_play_unlock();
1777 static void audio_stop_playback(void)
1779 if (playing)
1781 /* If we were playing, save resume information */
1782 struct mp3entry *id3 = NULL;
1784 if (!ci.stop_codec)
1785 id3 = audio_current_track();
1787 /* Save the current playing spot, or NULL if the playlist has ended */
1788 playlist_update_resume_info(id3);
1790 /* Now it's good time to send track finish events. Do this
1791 only if this hasn't been done already as part of a track
1792 switch. */
1793 if (id3 == thistrack_id3)
1794 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1796 /* TODO: Create auto bookmark too? */
1798 prev_track_elapsed = othertrack_id3->elapsed;
1800 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
1803 audio_stop_codec_flush();
1804 paused = false;
1805 playing = false;
1806 track_load_started = false;
1808 filling = STATE_IDLE;
1810 /* Mark all entries null. */
1811 audio_clear_track_entries();
1813 /* Close all tracks */
1814 audio_release_tracks();
1817 static void audio_play_start(size_t offset)
1819 int i;
1821 send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL);
1822 #if INPUT_SRC_CAPS != 0
1823 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1824 audio_set_output_source(AUDIO_SRC_PLAYBACK);
1825 #endif
1827 paused = false;
1828 audio_stop_codec_flush();
1830 playing = true;
1831 track_load_started = false;
1833 ci.new_track = 0;
1834 ci.seek_time = 0;
1835 wps_offset = 0;
1837 sound_set_volume(global_settings.volume);
1838 track_widx = track_ridx = 0;
1839 buf_set_base_handle(-1);
1841 /* Clear all track entries. */
1842 for (i = 0; i < MAX_TRACK; i++) {
1843 clear_track_info(&tracks[i]);
1846 last_peek_offset = -1;
1848 /* Officially playing */
1849 queue_reply(&audio_queue, 1);
1851 audio_fill_file_buffer(true, offset);
1853 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
1855 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1856 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1860 /* Invalidates all but currently playing track. */
1861 static void audio_invalidate_tracks(void)
1863 if (audio_have_tracks())
1865 last_peek_offset = 0;
1866 track_widx = track_ridx;
1868 /* Mark all other entries null (also buffered wrong metadata). */
1869 audio_clear_track_entries();
1871 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1873 audio_fill_file_buffer(false, 0);
1874 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1878 static void audio_new_playlist(void)
1880 /* Prepare to start a new fill from the beginning of the playlist */
1881 last_peek_offset = -1;
1883 /* Signal the codec to initiate a track change forward */
1884 new_playlist = true;
1885 ci.new_track = 1;
1887 if (audio_have_tracks())
1889 if (paused)
1890 skipped_during_pause = true;
1891 track_widx = track_ridx;
1892 audio_clear_track_entries();
1894 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1896 /* Mark the current track as invalid to prevent skipping back to it */
1897 CUR_TI->taginfo_ready = false;
1900 /* Officially playing */
1901 queue_reply(&audio_queue, 1);
1903 audio_fill_file_buffer(false, 0);
1906 /* Called on manual track skip */
1907 static void audio_initiate_track_change(long direction)
1909 logf("audio_initiate_track_change(%ld)", direction);
1911 ci.new_track += direction;
1912 wps_offset -= direction;
1913 if (paused)
1914 skipped_during_pause = true;
1917 /* Called on manual dir skip */
1918 static void audio_initiate_dir_change(long direction)
1920 dir_skip = true;
1921 ci.new_track = direction;
1922 if (paused)
1923 skipped_during_pause = true;
1926 /* Called when PCM track change is complete */
1927 static void audio_finalise_track_change(void)
1929 logf("audio_finalise_track_change");
1931 if (automatic_skip)
1933 wps_offset = 0;
1934 automatic_skip = false;
1936 /* Invalidate prevtrack_id3 */
1937 memset(othertrack_id3, 0, sizeof(struct mp3entry));
1939 if (prev_ti && prev_ti->audio_hid < 0)
1941 /* No audio left so we clear all the track info. */
1942 clear_track_info(prev_ti);
1945 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1946 playlist_update_resume_info(audio_current_track());
1949 static void audio_seek_complete(void)
1951 logf("audio_seek_complete");
1953 if (!playing)
1954 return;
1956 /* If seeking-while-playing, pcm_is_paused() is true.
1957 * If seeking-while-paused, audio_status PAUSE is true.
1958 * A seamless seek skips this section. */
1959 ci.seek_time = 0;
1961 pcm_play_lock();
1963 if (pcm_is_paused() || paused)
1965 /* Clear the buffer */
1966 pcmbuf_play_stop();
1968 /* If seeking-while-playing, resume PCM playback */
1969 if (!paused)
1970 pcmbuf_pause(false);
1973 pcm_play_unlock();
1976 static void audio_codec_status_message(long reason, int status)
1978 /* TODO: Push the errors up to the normal UI somewhere */
1979 switch (reason)
1981 case Q_CODEC_LOAD_DISK:
1982 case Q_CODEC_LOAD:
1983 if (!playing)
1984 return;
1986 if (status < 0)
1988 splash(HZ*2, "Codec failure");
1989 audio_check_new_track();
1991 break;
1993 #ifdef AUDIO_HAVE_RECORDING
1994 case Q_ENCODER_LOAD_DISK:
1995 if (status < 0)
1996 splash(HZ*2, "Encoder failure");
1997 break;
1998 #endif /* AUDIO_HAVE_RECORDING */
2003 * Layout audio buffer as follows - iram buffer depends on target:
2004 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
2006 static void audio_reset_buffer(void)
2008 /* see audio_get_recording_buffer if this is modified */
2009 logf("audio_reset_buffer");
2011 /* If the setup of anything allocated before the file buffer is
2012 changed, do check the adjustments after the buffer_alloc call
2013 as it will likely be affected and need sliding over */
2015 /* Initially set up file buffer as all space available */
2016 filebuf = audiobuf + talk_get_bufsize();
2017 filebuflen = audiobufend - filebuf;
2019 ALIGN_BUFFER(filebuf, filebuflen, sizeof (intptr_t));
2021 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
2022 size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE;
2024 /* Make sure filebuflen is a pointer sized multiple after adjustment */
2025 pcmbuf_size = ALIGN_UP(pcmbuf_size, sizeof (intptr_t));
2027 if(pcmbuf_size > filebuflen)
2028 panicf("%s(): EOM (%zu > %zu)", __func__, pcmbuf_size, filebuflen);
2030 filebuflen -= pcmbuf_size;
2031 buffering_reset(filebuf, filebuflen);
2033 /* Clear any references to the file buffer */
2034 buffer_state = AUDIOBUF_STATE_INITIALIZED;
2036 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
2037 /* Make sure everything adds up - yes, some info is a bit redundant but
2038 aids viewing and the sumation of certain variables should add up to
2039 the location of others. */
2041 size_t pcmbufsize;
2042 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
2043 logf("fbuf: %08X", (unsigned)filebuf);
2044 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
2045 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
2046 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
2047 logf("pcmb: %08X", (unsigned)pcmbuf);
2048 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
2050 #endif
2053 static void audio_thread(void)
2055 struct queue_event ev;
2057 pcm_postinit();
2059 audio_thread_ready = true;
2061 while (1)
2063 switch (filling) {
2064 case STATE_IDLE:
2065 queue_wait(&audio_queue, &ev);
2066 break;
2068 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2069 case STATE_USB:
2070 queue_wait(&audio_queue, &ev);
2071 switch (ev.id) {
2072 #ifdef AUDIO_HAVE_RECORDING
2073 /* Must monitor the encoder message for recording so it can
2074 remove it if we process the insertion before it does. It
2075 cannot simply be removed from under recording however. */
2076 case Q_AUDIO_LOAD_ENCODER:
2077 break;
2078 #endif
2079 case SYS_USB_DISCONNECTED:
2080 filling = STATE_IDLE;
2081 default:
2082 continue;
2084 break;
2085 #endif /* CONFIG_PLATFORM */
2087 default:
2088 /* End of buffering, let's calculate the watermark and
2089 unboost */
2090 set_filebuf_watermark();
2091 cancel_cpu_boost();
2092 /* Fall-through */
2093 case STATE_FILLING:
2094 case STATE_ENDING:
2095 if (!pcmbuf_queue_scan(&ev))
2096 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
2097 break;
2100 switch (ev.id) {
2102 case Q_AUDIO_FILL_BUFFER:
2103 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
2104 audio_fill_file_buffer((bool)ev.data, 0);
2105 break;
2107 case Q_AUDIO_FINISH_LOAD:
2108 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2109 audio_finish_load_track();
2110 buf_set_base_handle(CUR_TI->audio_hid);
2111 break;
2113 case Q_AUDIO_PLAY:
2114 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2115 if (playing && ev.data <= 0)
2116 audio_new_playlist();
2117 else
2119 audio_stop_playback();
2120 audio_play_start((size_t)ev.data);
2122 break;
2124 case Q_AUDIO_STOP:
2125 LOGFQUEUE("audio < Q_AUDIO_STOP");
2126 if (playing)
2127 audio_stop_playback();
2128 if (ev.data != 0)
2129 queue_clear(&audio_queue);
2130 break;
2132 case Q_AUDIO_PAUSE:
2133 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2134 if (!(bool) ev.data && skipped_during_pause
2135 #ifdef HAVE_CROSSFADE
2136 && !pcmbuf_is_crossfade_active()
2137 #endif
2139 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2140 skipped_during_pause = false;
2141 if (!playing)
2142 break;
2143 pcmbuf_pause((bool)ev.data);
2144 paused = (bool)ev.data;
2145 break;
2147 case Q_AUDIO_SKIP:
2148 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2149 audio_initiate_track_change((long)ev.data);
2150 break;
2152 case Q_AUDIO_PRE_FF_REWIND:
2153 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2154 if (!playing)
2155 break;
2156 pcmbuf_pause(true);
2157 break;
2159 case Q_AUDIO_FF_REWIND:
2160 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2161 if (!playing)
2162 break;
2164 if (filling == STATE_ENDING)
2166 /* Temp workaround: There is no codec available */
2167 if (!paused)
2168 pcmbuf_pause(false);
2169 break;
2172 if ((long)ev.data == 0)
2174 /* About to restart the track - send track finish
2175 events if not already done. */
2176 if (thistrack_id3 == audio_current_track())
2177 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
2180 if (automatic_skip)
2182 /* An automatic track skip is in progress. Finalize it,
2183 then go back to the previous track */
2184 audio_finalise_track_change();
2185 ci.new_track = -1;
2187 ci.seek_time = (long)ev.data+1;
2188 break;
2190 case Q_AUDIO_CHECK_NEW_TRACK:
2191 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2192 audio_check_new_track();
2193 break;
2195 case Q_AUDIO_DIR_SKIP:
2196 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2197 audio_initiate_dir_change(ev.data);
2198 break;
2200 case Q_AUDIO_FLUSH:
2201 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2202 audio_invalidate_tracks();
2203 break;
2205 case Q_AUDIO_TRACK_CHANGED:
2206 /* PCM track change done */
2207 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2208 if (filling != STATE_ENDING)
2209 audio_finalise_track_change();
2210 else if (playing)
2211 audio_stop_playback();
2212 break;
2214 case Q_AUDIO_SEEK_COMPLETE:
2215 /* Codec seek done */
2216 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
2217 audio_seek_complete();
2218 codec_ack_msg(Q_AUDIO_SEEK_COMPLETE, false);
2219 break;
2221 case Q_CODEC_LOAD:
2222 case Q_CODEC_LOAD_DISK:
2223 #ifdef AUDIO_HAVE_RECORDING
2224 case Q_ENCODER_LOAD_DISK:
2225 #endif
2226 /* These are received when a codec has finished normally or
2227 upon a codec error */
2228 audio_codec_status_message(ev.id, ev.data);
2229 break;
2231 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2232 case SYS_USB_CONNECTED:
2233 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2234 if (playing)
2235 audio_stop_playback();
2236 #ifdef PLAYBACK_VOICE
2237 voice_stop();
2238 #endif
2239 filling = STATE_USB;
2240 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2241 break;
2242 #endif
2244 #ifdef AUDIO_HAVE_RECORDING
2245 case Q_AUDIO_LOAD_ENCODER:
2246 if (playing)
2247 audio_stop_playback();
2248 else
2249 codec_stop(); /* If encoder still loaded, stop it */
2251 if (ev.data == AFMT_UNKNOWN)
2252 break;
2254 queue_reply(&audio_queue,
2255 codec_load(-1, ev.data | CODEC_TYPE_ENCODER));
2256 break;
2257 #endif /* AUDIO_HAVE_RECORDING */
2259 case SYS_TIMEOUT:
2260 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2261 break;
2263 default:
2264 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2265 break;
2266 } /* end switch */
2267 } /* end while */
2270 /* Initialize the audio system - called from init() in main.c.
2271 * Last function because of all the references to internal symbols
2273 void audio_init(void)
2275 unsigned int audio_thread_id;
2277 /* Can never do this twice */
2278 if (audio_is_initialized)
2280 logf("audio: already initialized");
2281 return;
2284 logf("audio: initializing");
2286 /* Initialize queues before giving control elsewhere in case it likes
2287 to send messages. Thread creation will be delayed however so nothing
2288 starts running until ready if something yields such as talk_init. */
2289 queue_init(&audio_queue, true);
2290 queue_init(&pcmbuf_queue, false);
2292 pcm_init();
2294 codec_init_codec_api();
2296 thistrack_id3 = &mp3entry_buf[0];
2297 othertrack_id3 = &mp3entry_buf[1];
2299 /* cuesheet support */
2300 if (global_settings.cuesheet)
2301 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2303 /* initialize the buffer */
2304 filebuf = audiobuf;
2306 /* audio_reset_buffer must to know the size of voice buffer so init
2307 talk first */
2308 talk_init();
2310 make_codec_thread();
2312 audio_thread_id = create_thread(audio_thread, audio_stack,
2313 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2314 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
2315 IF_COP(, CPU));
2317 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
2318 audio_thread_id);
2320 #ifdef PLAYBACK_VOICE
2321 voice_thread_init();
2322 #endif
2324 #ifdef HAVE_CROSSFADE
2325 /* Set crossfade setting for next buffer init which should be about... */
2326 pcmbuf_request_crossfade_enable(global_settings.crossfade);
2327 #endif
2329 /* initialize the buffering system */
2331 buffering_init();
2332 /* ...now! Set up the buffers */
2333 audio_reset_buffer();
2335 int i;
2336 for(i = 0; i < MAX_TRACK; i++)
2338 tracks[i].audio_hid = -1;
2339 tracks[i].id3_hid = -1;
2340 tracks[i].codec_hid = -1;
2341 tracks[i].cuesheet_hid = -1;
2343 #ifdef HAVE_ALBUMART
2344 FOREACH_ALBUMART(i)
2346 int j;
2347 for (j = 0; j < MAX_TRACK; j++)
2349 tracks[j].aa_hid[i] = -1;
2352 #endif
2354 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2355 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2357 /* Probably safe to say */
2358 audio_is_initialized = true;
2360 sound_settings_apply();
2361 #ifdef HAVE_DISK_STORAGE
2362 audio_set_buffer_margin(global_settings.buffer_margin);
2363 #endif
2365 /* it's safe to let the threads run now */
2366 #ifdef PLAYBACK_VOICE
2367 voice_thread_resume();
2368 #endif
2369 codec_thread_resume();
2370 thread_thaw(audio_thread_id);
2372 } /* audio_init */
2374 bool audio_is_thread_ready(void)
2376 return audio_thread_ready;
2379 size_t audio_get_filebuflen(void)
2381 return filebuflen;
2384 int get_audio_hid()
2386 return CUR_TI->audio_hid;