GSoC/Buflib: Enable compaction in buflib.
[kugel-rb.git] / apps / playback.c
blob9a913871a4dc061a5478ac7e5f90c55f1be9983e
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
12 * Copyright (C) 2011 Michael Sevakis
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "config.h"
24 #include "system.h"
25 #include "kernel.h"
26 #include "panic.h"
27 #include "core_alloc.h"
28 #include "sound.h"
29 #include "ata.h"
30 #include "usb.h"
31 #include "codecs.h"
32 #include "codec_thread.h"
33 #include "voice_thread.h"
34 #include "metadata.h"
35 #include "cuesheet.h"
36 #include "buffering.h"
37 #include "talk.h"
38 #include "playlist.h"
39 #include "abrepeat.h"
40 #include "pcmbuf.h"
41 #include "playback.h"
42 #include "misc.h"
44 #ifdef HAVE_TAGCACHE
45 #include "tagcache.h"
46 #endif
48 #ifdef AUDIO_HAVE_RECORDING
49 #include "pcm_record.h"
50 #endif
52 #ifdef HAVE_LCD_BITMAP
53 #ifdef HAVE_ALBUMART
54 #include "albumart.h"
55 #endif
56 #endif
58 /* TODO: The audio thread really is doing multitasking of acting like a
59 consumer and producer of tracks. It may be advantageous to better
60 logically separate the two functions. I won't go that far just yet. */
62 /* Internal support for voice playback */
63 #define PLAYBACK_VOICE
65 #if CONFIG_PLATFORM & PLATFORM_NATIVE
66 /* Application builds don't support direct code loading */
67 #define HAVE_CODEC_BUFFERING
68 #endif
70 /* Amount of guess-space to allow for codecs that must hunt and peck
71 * for their correct seek target, 32k seems a good size */
72 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
74 /* Define LOGF_ENABLE to enable logf output in this file */
75 /* #define LOGF_ENABLE */
76 #include "logf.h"
78 /* Macros to enable logf for queues
79 logging on SYS_TIMEOUT can be disabled */
80 #ifdef SIMULATOR
81 /* Define this for logf output of all queuing except SYS_TIMEOUT */
82 #define PLAYBACK_LOGQUEUES
83 /* Define this to logf SYS_TIMEOUT messages */
84 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
85 #endif
87 #ifdef PLAYBACK_LOGQUEUES
88 #define LOGFQUEUE logf
89 #else
90 #define LOGFQUEUE(...)
91 #endif
93 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
94 #define LOGFQUEUE_SYS_TIMEOUT logf
95 #else
96 #define LOGFQUEUE_SYS_TIMEOUT(...)
97 #endif
99 /* Variables are commented with the threads that use them:
100 * A=audio, C=codec, O=other. A suffix of "-" indicates that the variable is
101 * read but not updated on that thread. Audio is the only user unless otherwise
102 * specified.
105 /** Miscellaneous **/
106 bool audio_is_initialized = false; /* (A,O-) */
107 extern struct codec_api ci; /* (A,C) */
109 /** Possible arrangements of the main buffer **/
110 static enum audio_buffer_state
112 AUDIOBUF_STATE_TRASHED = -1, /* trashed; must be reset */
113 AUDIOBUF_STATE_INITIALIZED = 0, /* voice+audio OR audio-only */
114 AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
115 } buffer_state = AUDIOBUF_STATE_TRASHED; /* (A,O) */
117 /** Main state control **/
118 static bool ff_rw_mode SHAREDBSS_ATTR = false; /* Pre-ff-rewind mode (A,O-) */
120 enum play_status
122 PLAY_STOPPED = 0,
123 PLAY_PLAYING = AUDIO_STATUS_PLAY,
124 PLAY_PAUSED = AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE,
125 } play_status = PLAY_STOPPED;
127 /* Sizeable things that only need exist during playback and not when stopped */
128 static struct audio_scratch_memory
130 struct mp3entry codec_id3; /* (A,C) */
131 struct mp3entry unbuffered_id3;
132 struct cuesheet *curr_cue; /* Will follow this structure */
133 } * audio_scratch_memory = NULL;
135 /* These are used to store the current, next and optionally the peek-ahead
136 * mp3entry's - this guarantees that the pointer returned by audio_current/
137 * next_track will be valid for the full duration of the currently playing
138 * track */
139 enum audio_id3_types
141 /* These are allocated statically */
142 PLAYING_ID3 = 0,
143 NEXTTRACK_ID3,
144 #ifdef AUDIO_FAST_SKIP_PREVIEW
145 /* The real playing metadata must has to be protected since it contains
146 critical info for other features */
147 PLAYING_PEEK_ID3,
148 #endif
149 ID3_TYPE_NUM_STATIC,
150 /* These go in the scratch memory */
151 UNBUFFERED_ID3 = ID3_TYPE_NUM_STATIC,
152 CODEC_ID3,
154 static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */
156 /* Peeking functions can yield and mess us up */
157 static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,O)*/
160 /** For Scrobbler support **/
162 /* Previous track elapsed time */
163 static unsigned long prev_track_elapsed = 0; /* (A,O-) */
166 /** For album art support **/
167 #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
168 #ifdef HAVE_ALBUMART
170 static struct albumart_slot
172 struct dim dim; /* Holds width, height of the albumart */
173 int used; /* Counter; increments if something uses it */
174 } albumart_slots[MAX_MULTIPLE_AA]; /* (A,O) */
176 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
177 #endif /* HAVE_ALBUMART */
180 /** Information used for tracking buffer fills **/
182 /* Buffer and thread state tracking */
183 static enum filling_state
185 STATE_BOOT = 0, /* audio thread is not ready yet */
186 STATE_IDLE, /* audio is stopped: nothing to do */
187 STATE_FILLING, /* adding tracks to the buffer */
188 STATE_FULL, /* can't add any more tracks */
189 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
190 STATE_FINISHED, /* all remaining tracks are fully buffered */
191 STATE_ENDING, /* audio playback is ending */
192 STATE_ENDED, /* audio playback is done */
193 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
194 STATE_USB, /* USB mode, ignore most messages */
195 #endif
196 } filling = STATE_BOOT;
198 /* Track info - holds information about each track in the buffer */
199 struct track_info
201 /* In per-track allocated order: */
202 int id3_hid; /* Metadata handle ID */
203 int cuesheet_hid; /* Parsed cuesheet handle ID */
204 #ifdef HAVE_ALBUMART
205 int aa_hid[MAX_MULTIPLE_AA];/* Album art handle IDs */
206 #endif
207 #ifdef HAVE_CODEC_BUFFERING
208 int codec_hid; /* Buffered codec handle ID */
209 #endif
210 int audio_hid; /* Main audio data handle ID */
211 size_t filesize; /* File total length on disk
212 TODO: This should be stored
213 in the handle or the
214 id3 and would use less
215 ram */
218 /* Track list - holds info about all buffered tracks */
219 #if MEMORYSIZE >= 32
220 #define TRACK_LIST_LEN 128 /* Must be 2^int(+n) */
221 #elif MEMORYSIZE >= 16
222 #define TRACK_LIST_LEN 64
223 #elif MEMORYSIZE >= 8
224 #define TRACK_LIST_LEN 32
225 #else
226 #define TRACK_LIST_LEN 16
227 #endif
229 #define TRACK_LIST_MASK (TRACK_LIST_LEN-1)
231 static struct
233 /* read, write and current are maintained unwrapped, limited only by the
234 unsigned int range and wrap-safe comparisons are used */
236 /* NOTE: there appears to be a bug in arm-elf-eabi-gcc 4.4.4 for ARMv4 where
237 if 'end' follows 'start' in this structure, track_list_count performs
238 'start - end' rather than 'end - start', giving negative count values...
239 so leave it this way for now! */
240 unsigned int end; /* Next open position */
241 unsigned int start; /* First track in list */
242 unsigned int current; /* Currently decoding track */
243 struct track_info tracks[TRACK_LIST_LEN]; /* Buffered track information */
244 } track_list; /* (A, O-) */
247 /* Playlist steps from playlist position to next track to be buffered */
248 static int playlist_peek_offset = 0;
250 /* Metadata handle of track load in progress (meaning all handles have not
251 yet been opened for the track, id3 always exists or the track does not)
253 Tracks are keyed by their metadata handles if track list pointers are
254 insufficient to make comparisons */
255 static int in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
257 #ifdef HAVE_DISK_STORAGE
258 /* Buffer margin A.K.A. anti-skip buffer (in seconds) */
259 static size_t buffer_margin = 5;
260 #endif
262 /* Values returned for track loading */
263 enum track_load_status
265 LOAD_TRACK_ERR_START_CODEC = -6,
266 LOAD_TRACK_ERR_FINISH_FAILED = -5,
267 LOAD_TRACK_ERR_FINISH_FULL = -4,
268 LOAD_TRACK_ERR_BUSY = -3,
269 LOAD_TRACK_ERR_NO_MORE = -2,
270 LOAD_TRACK_ERR_FAILED = -1,
271 LOAD_TRACK_OK = 0,
272 LOAD_TRACK_READY = 1,
275 /** Track change controls **/
277 /* What sort of skip is pending globally? */
278 enum track_skip_type
280 /* Relative to what user is intended to see: */
281 /* Codec: +0, Track List: +0, Playlist: +0 */
282 TRACK_SKIP_NONE = 0, /* no track skip */
283 /* Codec: +1, Track List: +1, Playlist: +0 */
284 TRACK_SKIP_AUTO, /* codec-initiated skip */
285 /* Codec: +1, Track List: +1, Playlist: +1 */
286 TRACK_SKIP_AUTO_NEW_PLAYLIST, /* codec-initiated skip is new playlist */
287 /* Codec: xx, Track List: +0, Playlist: +0 */
288 TRACK_SKIP_AUTO_END_PLAYLIST, /* codec-initiated end of playlist */
289 /* Manual skip: Never pends */
290 TRACK_SKIP_MANUAL, /* manual track skip */
291 /* Manual skip: Never pends */
292 TRACK_SKIP_DIR_CHANGE, /* manual directory skip */
293 } skip_pending = TRACK_SKIP_NONE;
295 /* Note about TRACK_SKIP_AUTO_NEW_PLAYLIST:
296 Fixing playlist code to be able to peek into the first song of
297 the next playlist would fix any issues and this wouldn't need
298 to be a special case since pre-advancing the playlist would be
299 unneeded - it could be much more like TRACK_SKIP_AUTO and all
300 actions that require reversal during an in-progress transition
301 would work as expected */
303 /* Used to indicate status for the events. Must be separate to satisfy all
304 clients so the correct metadata is read when sending the change events
305 and also so that it is read correctly outside the events. */
306 static bool automatic_skip = false; /* (A, O-) */
308 /* Pending manual track skip offset */
309 static int skip_offset = 0; /* (A, O) */
311 /* Track change notification */
312 static struct
314 unsigned int in; /* Number of pcmbuf posts (audio isr) */
315 unsigned int out; /* Number of times audio has read the difference */
316 } track_change = { 0, 0 };
318 /** Codec status **/
319 /* Did the codec notify us it finished while we were paused or while still
320 in an automatic transition?
322 If paused, it is necessary to defer a codec-initiated skip until resuming
323 or else the track will move forward while not playing audio!
325 If in-progress, skips should not build-up ahead of where the WPS is when
326 really short tracks finish decoding.
328 If it is forgotten, it will be missed altogether and playback will just sit
329 there looking stupid and comatose until the user does something */
330 static bool codec_skip_pending = false;
331 static int codec_skip_status;
332 static bool codec_seeking = false; /* Codec seeking ack expected? */
335 /* Event queues */
336 static struct event_queue audio_queue SHAREDBSS_ATTR;
338 /* Audio thread */
339 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
340 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
341 static const char audio_thread_name[] = "audio";
342 static unsigned int audio_thread_id = 0;
344 /* Forward declarations */
345 enum audio_start_playback_flags
347 AUDIO_START_RESTART = 0x1, /* "Restart" playback (flush _all_ tracks) */
348 AUDIO_START_NEWBUF = 0x2, /* Mark the audiobuffer as invalid */
351 static void audio_start_playback(size_t offset, unsigned int flags);
352 static void audio_stop_playback(void);
353 static void buffer_event_buffer_low_callback(void *data);
354 static void buffer_event_rebuffer_callback(void *data);
355 static void buffer_event_finished_callback(void *data);
358 /**************************************/
360 /** --- audio_queue helpers --- **/
362 /* codec thread needs access */
363 void audio_queue_post(long id, intptr_t data)
365 queue_post(&audio_queue, id, data);
368 static intptr_t audio_queue_send(long id, intptr_t data)
370 return queue_send(&audio_queue, id, data);
374 /** --- MP3Entry --- **/
376 /* Does the mp3entry have enough info for us to use it? */
377 static struct mp3entry * valid_mp3entry(const struct mp3entry *id3)
379 return id3 && (id3->length != 0 || id3->filesize != 0) &&
380 id3->codectype != AFMT_UNKNOWN ? (struct mp3entry *)id3 : NULL;
383 /* Return a pointer to an mp3entry on the buffer, as it is */
384 static struct mp3entry * bufgetid3(int handle_id)
386 if (handle_id < 0)
387 return NULL;
389 struct mp3entry *id3;
390 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
392 if (ret != sizeof(struct mp3entry))
393 return NULL;
395 return id3;
398 /* Read an mp3entry from the buffer, adjusted */
399 static bool bufreadid3(int handle_id, struct mp3entry *id3out)
401 struct mp3entry *id3 = bufgetid3(handle_id);
403 if (id3)
405 copy_mp3entry(id3out, id3);
406 return true;
409 return false;
412 /* Lock the id3 mutex */
413 static void id3_mutex_lock(void)
415 mutex_lock(&id3_mutex);
418 /* Unlock the id3 mutex */
419 static void id3_mutex_unlock(void)
421 mutex_unlock(&id3_mutex);
424 /* Return one of the collection of mp3entry pointers - collect them all here */
425 static inline struct mp3entry * id3_get(enum audio_id3_types id3_num)
427 switch (id3_num)
429 case UNBUFFERED_ID3:
430 return &audio_scratch_memory->unbuffered_id3;
431 case CODEC_ID3:
432 return &audio_scratch_memory->codec_id3;
433 default:
434 return &static_id3_entries[id3_num];
438 /* Copy an mp3entry into one of the mp3 entries */
439 static void id3_write(enum audio_id3_types id3_num,
440 const struct mp3entry *id3_src)
442 struct mp3entry *dest_id3 = id3_get(id3_num);
444 if (id3_src)
445 copy_mp3entry(dest_id3, id3_src);
446 else
447 wipe_mp3entry(dest_id3);
450 /* Call id3_write "safely" because peek aheads can yield, even if the fast
451 preview isn't enabled */
452 static void id3_write_locked(enum audio_id3_types id3_num,
453 const struct mp3entry *id3_src)
455 id3_mutex_lock();
456 id3_write(id3_num, id3_src);
457 id3_mutex_unlock();
461 /** --- Track info --- **/
463 /* Close a handle and mark it invalid */
464 static void track_info_close_handle(int *hid_p)
466 int hid = *hid_p;
468 /* bufclose returns true if the handle is not found, or if it is closed
469 * successfully, so these checks are safe on non-existant handles */
470 if (hid >= 0)
471 bufclose(hid);
473 /* Always reset to "no handle" in case it was something else */
474 *hid_p = ERR_HANDLE_NOT_FOUND;
477 /* Close all handles in a struct track_info and clear it */
478 static void track_info_close(struct track_info *info)
480 /* Close them in the order they are allocated on the buffer to speed up
481 the handle searching */
482 track_info_close_handle(&info->id3_hid);
483 track_info_close_handle(&info->cuesheet_hid);
484 #ifdef HAVE_ALBUMART
485 int i;
486 FOREACH_ALBUMART(i)
487 track_info_close_handle(&info->aa_hid[i]);
488 #endif
489 #ifdef HAVE_CODEC_BUFFERING
490 track_info_close_handle(&info->codec_hid);
491 #endif
492 track_info_close_handle(&info->audio_hid);
493 info->filesize = 0;
496 /* Invalidate all members to initial values - does not close handles */
497 static void track_info_wipe(struct track_info * info)
499 info->id3_hid = ERR_HANDLE_NOT_FOUND;
500 info->cuesheet_hid = ERR_HANDLE_NOT_FOUND;
501 #ifdef HAVE_ALBUMART
502 int i;
503 FOREACH_ALBUMART(i)
504 info->aa_hid[i] = ERR_HANDLE_NOT_FOUND;
505 #endif
506 #ifdef HAVE_CODEC_BUFFERING
507 info->codec_hid = ERR_HANDLE_NOT_FOUND;
508 #endif
509 info->audio_hid = ERR_HANDLE_NOT_FOUND;
510 info->filesize = 0;
514 /** --- Track list --- **/
516 /* Initialize the track list */
517 static void track_list_init(void)
519 int i;
520 for (i = 0; i < TRACK_LIST_LEN; i++)
521 track_info_wipe(&track_list.tracks[i]);
523 track_list.start = track_list.end = track_list.current;
526 /* Return number of items allocated in the list */
527 static unsigned int track_list_count(void)
529 return track_list.end - track_list.start;
532 /* Return true if the list is empty */
533 static inline bool track_list_empty(void)
535 return track_list.end == track_list.start;
538 /* Returns true if the list is holding the maximum number of items */
539 static bool track_list_full(void)
541 return track_list.end - track_list.start >= TRACK_LIST_LEN;
544 /* Test if the index is within the allocated range */
545 static bool track_list_in_range(int pos)
547 return (int)(pos - track_list.start) >= 0 &&
548 (int)(pos - track_list.end) < 0;
551 static struct track_info * track_list_entry(int pos)
553 return &track_list.tracks[pos & TRACK_LIST_MASK];
556 /* Return the info of the last allocation plus an offset, NULL if result is
557 out of bounds */
558 static struct track_info * track_list_last(int offset)
560 /* Last is before the end since the end isn't inclusive */
561 unsigned int pos = track_list.end + offset - 1;
563 if (!track_list_in_range(pos))
564 return NULL;
566 return track_list_entry(pos);
569 /* Allocate space at the end for another track if not full */
570 static struct track_info * track_list_alloc_track(void)
572 if (track_list_full())
573 return NULL;
575 return track_list_entry(track_list.end++);
578 /* Remove the last track entry allocated in order to support backing out
579 of a track load */
580 static void track_list_unalloc_track(void)
582 if (track_list_empty())
583 return;
585 track_list.end--;
587 if (track_list.current == track_list.end &&
588 track_list.current != track_list.start)
590 /* Current _must_ remain within bounds */
591 track_list.current--;
595 /* Return current track plus an offset, NULL if result is out of bounds */
596 static struct track_info * track_list_current(int offset)
598 unsigned int pos = track_list.current + offset;
600 if (!track_list_in_range(pos))
601 return NULL;
603 return track_list_entry(pos);
606 /* Return current based upon what's intended that the user sees - not
607 necessarily where decoding is taking place */
608 static struct track_info * track_list_user_current(int offset)
610 if (skip_pending == TRACK_SKIP_AUTO ||
611 skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)
613 offset--;
616 return track_list_current(offset);
619 /* Advance current track by an offset, return false if result is out of
620 bounds */
621 static struct track_info * track_list_advance_current(int offset)
623 unsigned int pos = track_list.current + offset;
625 if (!track_list_in_range(pos))
626 return NULL;
628 track_list.current = pos;
629 return track_list_entry(pos);
632 /* Clear tracks in the list, optionally preserving the current track -
633 returns 'false' if the operation was changed */
634 enum track_clear_action
636 TRACK_LIST_CLEAR_ALL = 0, /* Clear all tracks */
637 TRACK_LIST_KEEP_CURRENT, /* Keep current only; clear before + after */
638 TRACK_LIST_KEEP_NEW /* Keep current and those that follow */
641 static void track_list_clear(enum track_clear_action action)
643 logf("%s(%d)", __func__, (int)action);
645 /* Don't care now since rebuffering is imminent */
646 buf_set_watermark(0);
648 if (action != TRACK_LIST_CLEAR_ALL)
650 struct track_info *cur = track_list_current(0);
652 if (!cur || cur->id3_hid < 0)
653 action = TRACK_LIST_CLEAR_ALL; /* Nothing worthwhile keeping */
656 /* Noone should see this progressing */
657 int start = track_list.start;
658 int current = track_list.current;
659 int end = track_list.end;
661 track_list.start = current;
663 switch (action)
665 case TRACK_LIST_CLEAR_ALL:
666 /* Result: .start = .current, .end = .current */
667 track_list.end = current;
668 break;
670 case TRACK_LIST_KEEP_CURRENT:
671 /* Result: .start = .current, .end = .current + 1 */
672 track_list.end = current + 1;
673 break;
675 case TRACK_LIST_KEEP_NEW:
676 /* Result: .start = .current, .end = .end */
677 end = current;
678 break;
681 /* Close all open handles in the range except the for the current track
682 if preserving that */
683 while (start != end)
685 if (action != TRACK_LIST_KEEP_CURRENT || start != current)
687 struct track_info *info =
688 &track_list.tracks[start & TRACK_LIST_MASK];
690 /* If this is the in-progress load, abort it */
691 if (in_progress_id3_hid >= 0 &&
692 info->id3_hid == in_progress_id3_hid)
694 in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
697 track_info_close(info);
700 start++;
705 /** --- Audio buffer -- **/
707 /* What size is needed for the scratch buffer? */
708 static size_t scratch_mem_size(void)
710 size_t size = sizeof (struct audio_scratch_memory);
712 if (global_settings.cuesheet)
713 size += sizeof (struct cuesheet);
715 return size;
718 /* Initialize the memory area where data is stored that is only used when
719 playing audio and anything depending upon it */
720 static void scratch_mem_init(void *mem)
722 audio_scratch_memory = (struct audio_scratch_memory *)mem;
723 id3_write_locked(UNBUFFERED_ID3, NULL);
724 id3_write(CODEC_ID3, NULL);
725 ci.id3 = id3_get(CODEC_ID3);
726 audio_scratch_memory->curr_cue = NULL;
728 if (global_settings.cuesheet)
730 audio_scratch_memory->curr_cue =
731 SKIPBYTES((struct cuesheet *)audio_scratch_memory,
732 sizeof (struct audio_scratch_memory));
736 static int audiobuf_handle;
737 static size_t filebuflen;
739 size_t audio_buffer_available(void)
741 if (audiobuf_handle > 0) /* if allocated return what we got */
742 return filebuflen;
743 return core_available();
746 /* Set up the audio buffer for playback
747 * filebuflen must be pre-initialized with the maximum size */
748 static void audio_reset_buffer_noalloc(void* filebuf)
751 * Layout audio buffer as follows:
752 * [[|TALK]|SCRATCH|BUFFERING|PCM|[VOICE|]]
755 /* see audio_get_recording_buffer if this is modified */
756 logf("%s()", __func__);
758 /* If the setup of anything allocated before the file buffer is
759 changed, do check the adjustments after the buffer_alloc call
760 as it will likely be affected and need sliding over */
762 /* Initially set up file buffer as all space available */
763 size_t allocsize;
765 /* Subtract whatever voice needs */
766 allocsize = talkbuf_init(filebuf);
767 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
768 if (allocsize > filebuflen)
769 goto bufpanic;
771 filebuf += allocsize;
772 filebuflen -= allocsize;
774 if (talk_voice_required())
776 /* Need a space for voice PCM output */
777 allocsize = voicebuf_init(filebuf + filebuflen);
779 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
780 if (allocsize > filebuflen)
781 goto bufpanic;
783 filebuflen -= allocsize;
786 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
787 allocsize = pcmbuf_init(filebuf + filebuflen);
789 /* Make sure filebuflen is a pointer sized multiple after adjustment */
790 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
791 if (allocsize > filebuflen)
792 goto bufpanic;
794 filebuflen -= allocsize;
796 /* Scratch memory */
797 allocsize = scratch_mem_size();
798 if (allocsize > filebuflen)
799 goto bufpanic;
801 scratch_mem_init(filebuf);
802 filebuf += allocsize;
803 filebuflen -= allocsize;
805 buffering_reset(filebuf, filebuflen);
807 /* Clear any references to the file buffer */
808 buffer_state = AUDIOBUF_STATE_INITIALIZED;
810 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
811 /* Make sure everything adds up - yes, some info is a bit redundant but
812 aids viewing and the summation of certain variables should add up to
813 the location of others. */
815 size_t pcmbufsize;
816 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
817 logf("fbuf: %08X", (unsigned)filebuf);
818 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
819 logf("sbuf: %08X", (unsigned)audio_scratch_memory);
820 logf("sbufe: %08X", (unsigned)(audio_scratch_memory + allocsize));
821 logf("pcmb: %08X", (unsigned)pcmbuf);
822 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
824 #endif
826 return;
828 bufpanic:
829 panicf("%s(): EOM (%zu > %zu)", __func__, allocsize, filebuflen);
833 /* Buffer must not move. */
834 static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size)
836 DEBUGF("%s()\n", __func__);
838 long offset = audio_current_track()->offset;
839 int status = audio_status();
840 /* TODO: Do it without stopping playback, if possible */
841 /* don't call audio_hard_stop() as it frees this handle */
842 if (thread_self() == audio_thread_id)
843 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
844 * if we're in the audio thread */
845 audio_stop_playback();
846 queue_clear(&audio_queue);
848 else
849 audio_queue_send(Q_AUDIO_STOP, 1);
850 #ifdef PLAYBACK_VOICE
851 voice_stop();
852 #endif
853 /* we should be free to change the buffer now */
854 size_t wanted_size = (hints & BUFLIB_SHRINK_SIZE_MASK);
855 ssize_t size = (ssize_t)old_size - wanted_size;
856 /* set final buffer size before calling audio_reset_buffer_noalloc() */
857 filebuflen = size;
858 DEBUGF("%s(): %zu %d\n", __func__, wanted_size, (hints & BUFLIB_SHRINK_POS_MASK) >> 30);
859 switch (hints & BUFLIB_SHRINK_POS_MASK)
861 case BUFLIB_SHRINK_POS_BACK:
862 core_shrink(handle, start, size);
863 audio_reset_buffer_noalloc(start);
864 break;
865 case BUFLIB_SHRINK_POS_FRONT:
866 core_shrink(handle, start + wanted_size, size);
867 audio_reset_buffer_noalloc(start + wanted_size);
868 break;
870 if (!(status & AUDIO_STATUS_PAUSE))
872 DEBUGF("%s(): Resuming from %ld\n", __func__, offset);
873 if (thread_self() == audio_thread_id)
874 audio_start_playback(offset, 0); /* inline Q_AUDIO_PLAY */
875 else
876 audio_play(offset);
879 return BUFLIB_CB_OK;
882 static struct buflib_callbacks ops = {
883 .move_callback = NULL,
884 .shrink_callback = shrink_callback,
887 static void audio_reset_buffer(void)
889 if (audiobuf_handle > 0)
891 core_free(audiobuf_handle);
892 audiobuf_handle = 0;
894 audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops);
895 unsigned char *filebuf = core_get_data(audiobuf_handle);
897 audio_reset_buffer_noalloc(filebuf);
900 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
901 static void audio_update_filebuf_watermark(int seconds)
903 size_t bytes = 0;
905 #ifdef HAVE_DISK_STORAGE
906 int spinup = ata_spinup_time();
908 if (seconds == 0)
910 /* By current setting */
911 seconds = buffer_margin;
913 else
915 /* New setting */
916 buffer_margin = seconds;
918 if (buf_get_watermark() == 0)
920 /* Write a watermark only if the audio thread already did so for
921 itself or it will fail to set the event and the watermark - if
922 it hasn't yet, it will use the new setting when it does */
923 return;
927 if (spinup)
928 seconds += (spinup / HZ) + 1;
929 else
930 seconds += 5;
932 seconds += buffer_margin;
933 #else
934 /* flash storage */
935 seconds = 1;
936 #endif
938 /* Watermark is a function of the bitrate of the last track in the buffer */
939 struct mp3entry *id3 = NULL;
940 struct track_info *info = track_list_last(0);
942 if (info)
943 id3 = valid_mp3entry(bufgetid3(info->id3_hid));
945 if (id3)
947 if (get_audio_base_data_type(id3->codectype) == TYPE_PACKET_AUDIO)
949 bytes = id3->bitrate * (1000/8) * seconds;
951 else
953 /* Bitrate has no meaning to buffering margin for atomic audio -
954 rebuffer when it's the only track left unless it's the only
955 track that fits, in which case we should avoid constant buffer
956 low events */
957 if (track_list_count() > 1)
958 bytes = info->filesize + 1;
961 else
963 /* Then set the minimum - this should not occur anyway */
964 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
965 track_list.start, track_list.current, track_list.end);
968 /* Actually setting zero disables the notification and we use that
969 to detect that it has been reset */
970 buf_set_watermark(MAX(bytes, 1));
971 logf("fwmark: %lu", (unsigned long)bytes);
975 /** -- Track change notification -- **/
977 /* Check the pcmbuf track changes and return write the message into the event
978 if there are any */
979 static inline bool audio_pcmbuf_track_change_scan(void)
981 if (track_change.out != track_change.in)
983 track_change.out++;
984 return true;
987 return false;
990 /* Clear outstanding track change posts */
991 static inline void audio_pcmbuf_track_change_clear(void)
993 track_change.out = track_change.in;
996 /* Post a track change notification - called by audio ISR */
997 static inline void audio_pcmbuf_track_change_post(void)
999 track_change.in++;
1003 /** --- Helper functions --- **/
1005 /* Removes messages that might end up in the queue before or while processing
1006 a manual track change. Responding to them would be harmful since they
1007 belong to a previous track's playback period. Anything that would generate
1008 the stale messages must first be put into a state where it will not do so.
1010 static void audio_clear_track_notifications(void)
1012 static const long filter_list[][2] =
1014 /* codec messages */
1015 { Q_AUDIO_CODEC_SEEK_COMPLETE, Q_AUDIO_CODEC_COMPLETE },
1016 /* track change messages */
1017 { Q_AUDIO_TRACK_CHANGED, Q_AUDIO_TRACK_CHANGED },
1020 const int filter_count = ARRAYLEN(filter_list) - 1;
1022 /* Remove any pcmbuf notifications */
1023 pcmbuf_monitor_track_change(false);
1024 audio_pcmbuf_track_change_clear();
1026 /* Scrub the audio queue of the old mold */
1027 while (queue_peek_ex(&audio_queue, NULL,
1028 filter_count | QPEEK_REMOVE_EVENTS,
1029 filter_list))
1031 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1035 /* Takes actions based upon track load status codes */
1036 static void audio_handle_track_load_status(int trackstat)
1038 switch (trackstat)
1040 case LOAD_TRACK_ERR_NO_MORE:
1041 if (track_list_count() > 0)
1042 break;
1044 case LOAD_TRACK_ERR_START_CODEC:
1045 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, CODEC_ERROR);
1046 break;
1048 default:
1049 break;
1053 /* Announce the end of playing the current track */
1054 static void audio_playlist_track_finish(void)
1056 struct mp3entry *id3 = valid_mp3entry(id3_get(PLAYING_ID3));
1058 playlist_update_resume_info(filling == STATE_ENDED ? NULL : id3);
1060 if (id3)
1062 send_event(PLAYBACK_EVENT_TRACK_FINISH, id3);
1063 prev_track_elapsed = id3->elapsed;
1065 else
1067 prev_track_elapsed = 0;
1071 /* Announce the beginning of the new track */
1072 static void audio_playlist_track_change(void)
1074 struct mp3entry *id3 = valid_mp3entry(id3_get(PLAYING_ID3));
1076 if (id3)
1077 send_event(PLAYBACK_EVENT_TRACK_CHANGE, id3);
1079 playlist_update_resume_info(id3);
1082 /* Change the data for the next track and send the event */
1083 static void audio_update_and_announce_next_track(const struct mp3entry *id3_next)
1085 id3_write_locked(NEXTTRACK_ID3, id3_next);
1086 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE,
1087 id3_get(NEXTTRACK_ID3));
1090 /* Bring the user current mp3entry up to date and set a new offset for the
1091 buffered metadata */
1092 static void playing_id3_sync(struct track_info *user_info, size_t offset)
1094 id3_mutex_lock();
1096 struct mp3entry *id3 = bufgetid3(user_info->id3_hid);
1098 if (offset == (size_t)-1)
1100 struct mp3entry *ply_id3 = id3_get(PLAYING_ID3);
1101 size_t play_offset = ply_id3->offset;
1102 long play_elapsed = ply_id3->elapsed;
1103 id3_write(PLAYING_ID3, id3);
1104 ply_id3->offset = play_offset;
1105 ply_id3->elapsed = play_elapsed;
1106 offset = 0;
1108 else
1110 id3_write(PLAYING_ID3, id3);
1113 if (id3)
1114 id3->offset = offset;
1116 id3_mutex_unlock();
1119 /* Wipe-out track metadata - current is optional */
1120 static void wipe_track_metadata(bool current)
1122 id3_mutex_lock();
1124 if (current)
1125 id3_write(PLAYING_ID3, NULL);
1127 id3_write(NEXTTRACK_ID3, NULL);
1128 id3_write(UNBUFFERED_ID3, NULL);
1130 id3_mutex_unlock();
1133 /* Called when buffering is completed on the last track handle */
1134 static void filling_is_finished(void)
1136 logf("last track finished buffering");
1138 /* There's no more to load or watch for */
1139 buf_set_watermark(0);
1140 filling = STATE_FINISHED;
1143 /* Stop the codec decoding or waiting for its data to be ready - returns
1144 'false' if the codec ended up stopped */
1145 static bool halt_decoding_track(bool stop)
1147 /* If it was waiting for us to clear the buffer to make a rebuffer
1148 happen, it should cease otherwise codec_stop could deadlock waiting
1149 for the codec to go to its main loop - codec's request will now
1150 force-fail */
1151 bool retval = false;
1153 buf_signal_handle(ci.audio_hid, true);
1155 if (stop)
1156 codec_stop();
1157 else
1158 retval = codec_pause();
1160 audio_clear_track_notifications();
1162 /* We now know it's idle and not waiting for buffered data */
1163 buf_signal_handle(ci.audio_hid, false);
1165 codec_skip_pending = false;
1166 codec_seeking = false;
1168 return retval;
1171 /* Clear the PCM on a manual skip */
1172 static void audio_clear_paused_pcm(void)
1174 if (play_status == PLAY_PAUSED && !pcmbuf_is_crossfade_active())
1175 pcmbuf_play_stop();
1178 /* End the ff/rw mode */
1179 static void audio_ff_rewind_end(void)
1181 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1182 section */
1183 if (ff_rw_mode)
1185 ff_rw_mode = false;
1187 if (codec_seeking)
1189 /* Clear the buffer */
1190 pcmbuf_play_stop();
1193 if (play_status != PLAY_PAUSED)
1195 /* Seeking-while-playing, resume PCM playback */
1196 pcmbuf_pause(false);
1201 /* Complete the codec seek */
1202 static void audio_complete_codec_seek(void)
1204 /* If a seek completed while paused, 'paused' is true.
1205 * If seeking from seek mode, 'ff_rw_mode' is true. */
1206 if (codec_seeking)
1208 audio_ff_rewind_end();
1209 codec_seeking = false; /* set _after_ the call! */
1211 /* else it's waiting and we must repond */
1214 /* Get the current cuesheet pointer */
1215 static inline struct cuesheet * get_current_cuesheet(void)
1217 return audio_scratch_memory->curr_cue;
1220 /* Read the cuesheet from the buffer */
1221 static void buf_read_cuesheet(int handle_id)
1223 struct cuesheet *cue = get_current_cuesheet();
1225 if (!cue || handle_id < 0)
1226 return;
1228 bufread(handle_id, sizeof (struct cuesheet), cue);
1231 /* Backend to peek/current/next track metadata interface functions -
1232 fill in the mp3entry with as much information as we may obtain about
1233 the track at the specified offset from the user current track -
1234 returns false if no information exists with us */
1235 static bool audio_get_track_metadata(int offset, struct mp3entry *id3)
1237 if (play_status == PLAY_STOPPED)
1238 return false;
1240 if (id3->path[0] != '\0')
1241 return true; /* Already filled */
1243 struct track_info *info = track_list_user_current(offset);
1245 if (!info)
1247 struct mp3entry *ub_id3 = id3_get(UNBUFFERED_ID3);
1249 if (offset > 0 && track_list_user_current(offset - 1))
1251 /* Try the unbuffered id3 since we're moving forward */
1252 if (ub_id3->path[0] != '\0')
1254 copy_mp3entry(id3, ub_id3);
1255 return true;
1259 else if (bufreadid3(info->id3_hid, id3))
1261 return true;
1264 /* We didn't find the ID3 metadata, so we fill it with the little info we
1265 have and return that */
1267 char path[MAX_PATH+1];
1268 if (playlist_peek(offset, path, sizeof (path)))
1270 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1271 /* Try to get it from the database */
1272 if (!tagcache_fill_tags(id3, path))
1273 #endif
1275 /* By now, filename is the only source of info */
1276 fill_metadata_from_path(id3, path);
1279 return true;
1282 wipe_mp3entry(id3);
1284 return false;
1287 /* Get a resume rewind adjusted offset from the ID3 */
1288 unsigned long resume_rewind_adjusted_offset(const struct mp3entry *id3)
1290 unsigned long offset = id3->offset;
1291 size_t resume_rewind = global_settings.resume_rewind *
1292 id3->bitrate * (1000/8);
1294 if (offset < resume_rewind)
1295 offset = 0;
1296 else
1297 offset -= resume_rewind;
1299 return offset;
1302 /* Get the codec into ram and initialize it - keep it if it's ready */
1303 static bool audio_init_codec(struct track_info *track_info,
1304 struct mp3entry *track_id3)
1306 int codt_loaded = get_audio_base_codec_type(codec_loaded());
1307 int hid = ERR_HANDLE_NOT_FOUND;
1309 if (codt_loaded != AFMT_UNKNOWN)
1311 int codt = get_audio_base_codec_type(track_id3->codectype);
1313 if (codt == codt_loaded)
1315 /* Codec is the same base type */
1316 logf("Reusing prev. codec: %d", track_id3->codectype);
1317 #ifdef HAVE_CODEC_BUFFERING
1318 /* Close any buffered codec (we could have skipped directly to a
1319 format transistion that is the same format as the current track
1320 and the buffered one is no longer needed) */
1321 track_info_close_handle(&track_info->codec_hid);
1322 #endif
1323 return true;
1325 else
1327 /* New codec - first make sure the old one's gone */
1328 logf("Removing prev. codec: %d", codt_loaded);
1329 codec_unload();
1333 logf("New codec: %d/%d", track_id3->codectype, codec_loaded());
1335 #ifdef HAVE_CODEC_BUFFERING
1336 /* Codec thread will close the handle even if it fails and will load from
1337 storage if hid is not valid or the buffer load fails */
1338 hid = track_info->codec_hid;
1339 track_info->codec_hid = ERR_HANDLE_NOT_FOUND;
1340 #endif
1342 return codec_load(hid, track_id3->codectype);
1343 (void)track_info; /* When codec buffering isn't supported */
1346 /* Start the codec for the current track scheduled to be decoded */
1347 static bool audio_start_codec(bool auto_skip)
1349 struct track_info *info = track_list_current(0);
1350 struct mp3entry *cur_id3 = valid_mp3entry(bufgetid3(info->id3_hid));
1352 if (!cur_id3)
1353 return false;
1355 buf_pin_handle(info->id3_hid, true);
1357 if (!audio_init_codec(info, cur_id3))
1359 buf_pin_handle(info->id3_hid, false);
1360 return false;
1363 #ifdef HAVE_TAGCACHE
1364 bool autoresume_enable = global_settings.autoresume_enable;
1366 if (autoresume_enable && !cur_id3->offset)
1368 /* Resume all manually selected tracks */
1369 bool resume = !auto_skip;
1371 /* Send the "buffer" event to obtain the resume position for the codec */
1372 send_event(PLAYBACK_EVENT_TRACK_BUFFER, cur_id3);
1374 if (!resume)
1376 /* Automatic skip - do further tests to see if we should just
1377 ignore any autoresume position */
1378 int autoresume_automatic = global_settings.autoresume_automatic;
1380 switch (autoresume_automatic)
1382 case AUTORESUME_NEXTTRACK_ALWAYS:
1383 /* Just resume unconditionally */
1384 resume = true;
1385 break;
1386 case AUTORESUME_NEXTTRACK_NEVER:
1387 /* Force-rewind it */
1388 break;
1389 default:
1390 /* Not "never resume" - pass resume filter? */
1391 resume = autoresumable(cur_id3);
1395 if (!resume)
1396 cur_id3->offset = 0;
1398 logf("%s: Set offset for %s to %lX\n", __func__,
1399 cur_id3->title, cur_id3->offset);
1401 #endif /* HAVE_TAGCACHE */
1403 /* Rewind the required amount - if an autoresume was done, this also rewinds
1404 that by the setting's amount
1406 It would be best to have bookkeeping about whether or not the track
1407 sounded or not since skipping to it or else skipping to it while paused
1408 and back again will cause accumulation of silent rewinds - that's not
1409 our job to track directly nor could it be in any reasonable way
1411 cur_id3->offset = resume_rewind_adjusted_offset(cur_id3);
1413 /* Update the codec API with the metadata and track info */
1414 id3_write(CODEC_ID3, cur_id3);
1416 ci.audio_hid = info->audio_hid;
1417 ci.filesize = info->filesize;
1418 buf_set_base_handle(info->audio_hid);
1420 /* All required data is now available for the codec */
1421 codec_go();
1423 #ifdef HAVE_TAGCACHE
1424 if (!autoresume_enable || cur_id3->offset)
1425 #endif
1427 /* Send the "buffer" event now */
1428 send_event(PLAYBACK_EVENT_TRACK_BUFFER, cur_id3);
1431 buf_pin_handle(info->id3_hid, false);
1432 return true;
1434 (void)auto_skip; /* ifndef HAVE_TAGCACHE */
1438 /** --- Audio thread --- **/
1440 /* Load and parse a cuesheet for the file - returns false if the buffer
1441 is full */
1442 static bool audio_load_cuesheet(struct track_info *info,
1443 struct mp3entry *track_id3)
1445 struct cuesheet *cue = get_current_cuesheet();
1446 track_id3->cuesheet = NULL;
1448 if (cue && info->cuesheet_hid == ERR_HANDLE_NOT_FOUND)
1450 /* If error other than a full buffer, then mark it "unsupported" to
1451 avoid reloading attempt */
1452 int hid = ERR_UNSUPPORTED_TYPE;
1453 char cuepath[MAX_PATH];
1455 #ifdef HAVE_IO_PRIORITY
1456 buf_back_off_storage(true);
1457 #endif
1458 if (look_for_cuesheet_file(track_id3->path, cuepath))
1460 hid = bufalloc(NULL, sizeof (struct cuesheet), TYPE_CUESHEET);
1462 if (hid >= 0)
1464 void *cuesheet = NULL;
1465 bufgetdata(hid, sizeof (struct cuesheet), &cuesheet);
1467 if (parse_cuesheet(cuepath, (struct cuesheet *)cuesheet))
1469 /* Indicate cuesheet is present (while track remains
1470 buffered) */
1471 track_id3->cuesheet = cue;
1473 else
1475 bufclose(hid);
1476 hid = ERR_UNSUPPORTED_TYPE;
1481 #ifdef HAVE_IO_PRIORITY
1482 buf_back_off_storage(false);
1483 #endif
1484 if (hid == ERR_BUFFER_FULL)
1486 logf("buffer is full for now (%s)", __func__);
1487 return false;
1489 else
1491 if (hid < 0)
1492 logf("Cuesheet loading failed");
1494 info->cuesheet_hid = hid;
1498 return true;
1501 #ifdef HAVE_ALBUMART
1502 /* Load any album art for the file - returns false if the buffer is full */
1503 static bool audio_load_albumart(struct track_info *info,
1504 struct mp3entry *track_id3)
1506 int i;
1507 FOREACH_ALBUMART(i)
1509 struct bufopen_bitmap_data user_data;
1510 int *aa_hid = &info->aa_hid[i];
1511 int hid = ERR_UNSUPPORTED_TYPE;
1513 /* albumart_slots may change during a yield of bufopen,
1514 * but that's no problem */
1515 if (*aa_hid >= 0 || *aa_hid == ERR_UNSUPPORTED_TYPE ||
1516 !albumart_slots[i].used)
1517 continue;
1519 memset(&user_data, 0, sizeof(user_data));
1520 user_data.dim = &albumart_slots[i].dim;
1522 #ifdef HAVE_IO_PRIORITY
1523 buf_back_off_storage(true);
1524 #endif
1526 /* We can only decode jpeg for embedded AA */
1527 if (track_id3->embed_albumart && track_id3->albumart.type == AA_TYPE_JPG)
1529 user_data.embedded_albumart = &track_id3->albumart;
1530 hid = bufopen(track_id3->path, 0, TYPE_BITMAP, &user_data);
1533 if (hid < 0 && hid != ERR_BUFFER_FULL)
1535 /* No embedded AA or it couldn't be loaded - try other sources */
1536 char path[MAX_PATH];
1538 if (find_albumart(track_id3, path, sizeof(path),
1539 &albumart_slots[i].dim))
1541 user_data.embedded_albumart = NULL;
1542 hid = bufopen(path, 0, TYPE_BITMAP, &user_data);
1546 #ifdef HAVE_IO_PRIORITY
1547 buf_back_off_storage(false);
1548 #endif
1549 if (hid == ERR_BUFFER_FULL)
1551 logf("buffer is full for now (%s)", __func__);
1552 return false;
1554 else
1556 /* If error other than a full buffer, then mark it "unsupported"
1557 to avoid reloading attempt */
1558 if (hid < 0)
1560 logf("Album art loading failed");
1561 hid = ERR_UNSUPPORTED_TYPE;
1564 *aa_hid = hid;
1568 return true;
1570 #endif /* HAVE_ALBUMART */
1572 #ifdef HAVE_CODEC_BUFFERING
1573 /* Load a codec for the file onto the buffer - assumes we're working from the
1574 currently loading track - not called for the current track */
1575 static bool audio_buffer_codec(struct track_info *track_info,
1576 struct mp3entry *track_id3)
1578 /* This will not be the current track -> it cannot be the first and the
1579 current track cannot be ahead of buffering -> there is a previous
1580 track entry which is either current or ahead of the current */
1581 struct track_info *prev_info = track_list_last(-1);
1582 struct mp3entry *prev_id3 = bufgetid3(prev_info->id3_hid);
1584 /* If the previous codec is the same as this one, there is no need to
1585 put another copy of it on the file buffer (in other words, only
1586 buffer codecs at format transitions) */
1587 if (prev_id3)
1589 int codt = get_audio_base_codec_type(track_id3->codectype);
1590 int prev_codt = get_audio_base_codec_type(prev_id3->codectype);
1592 if (codt == prev_codt)
1594 logf("Reusing prev. codec: %d", prev_id3->codectype);
1595 return true;
1598 /* else just load it (harmless) */
1600 /* Load the codec onto the buffer if possible */
1601 const char *codec_fn = get_codec_filename(track_id3->codectype);
1602 if (!codec_fn)
1603 return false;
1605 char codec_path[MAX_PATH+1]; /* Full path to codec */
1606 codec_get_full_path(codec_path, codec_fn);
1608 track_info->codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1610 if (track_info->codec_hid >= 0)
1612 logf("Buffered codec: %d", afmt);
1613 return true;
1616 return false;
1618 #endif /* HAVE_CODEC_BUFFERING */
1620 /* Load metadata for the next track (with bufopen). The rest of the track
1621 loading will be handled by audio_finish_load_track once the metadata has
1622 been actually loaded by the buffering thread.
1624 Each track is arranged in the buffer as follows:
1625 <id3|[cuesheet|][album art|][codec|]audio>
1627 The next will not be loaded until the previous succeeds if the buffer was
1628 full at the time. To put any metadata after audio would make those handles
1629 unmovable.
1631 static int audio_load_track(void)
1633 if (in_progress_id3_hid >= 0)
1635 /* There must be an info pointer if the in-progress id3 is even there */
1636 struct track_info *info = track_list_last(0);
1638 if (info->id3_hid == in_progress_id3_hid)
1640 if (filling == STATE_FILLING)
1642 /* Haven't finished the metadata but the notification is
1643 anticipated to come soon */
1644 logf("%s(): in progress ok: %d". __func__, info->id3_hid);
1645 return LOAD_TRACK_OK;
1647 else if (filling == STATE_FULL)
1649 /* Buffer was full trying to complete the load after the
1650 metadata finished, so attempt to continue - older handles
1651 should have been cleared already */
1652 logf("%s(): finishing load: %d". __func__, info->id3_hid);
1653 filling = STATE_FILLING;
1654 buffer_event_finished_callback(&info->id3_hid);
1655 return LOAD_TRACK_OK;
1659 /* Some old, stray buffering message */
1660 logf("%s(): already in progress: %d". __func__, info->id3_hid);
1661 return LOAD_TRACK_ERR_BUSY;
1664 filling = STATE_FILLING;
1666 struct track_info *info = track_list_alloc_track();
1667 if (info == NULL)
1669 /* List is full so stop buffering tracks - however, attempt to obtain
1670 metadata as the unbuffered id3 */
1671 logf("No free tracks");
1672 filling = STATE_FULL;
1675 playlist_peek_offset++;
1677 logf("Buffering track: s%u/c%u/e%u/p%d",
1678 track_list.start, track_list.current, track_list.end,
1679 playlist_peek_offset);
1681 /* Get track name from current playlist read position */
1682 int fd = -1;
1683 char name_buf[MAX_PATH + 1];
1684 const char *trackname;
1686 while (1)
1689 trackname = playlist_peek(playlist_peek_offset, name_buf,
1690 sizeof (name_buf));
1692 if (!trackname)
1693 break;
1695 /* Test for broken playlists by probing for the files */
1696 fd = open(trackname, O_RDONLY);
1697 if (fd >= 0)
1698 break;
1700 logf("Open failed");
1701 /* Skip invalid entry from playlist */
1702 playlist_skip_entry(NULL, playlist_peek_offset);
1704 /* Sync the playlist if it isn't finished */
1705 if (playlist_peek(playlist_peek_offset, NULL, 0))
1706 playlist_next(0);
1709 if (!trackname)
1711 /* No track - exhausted the playlist entries */
1712 logf("End-of-playlist");
1713 id3_write_locked(UNBUFFERED_ID3, NULL);
1715 if (filling != STATE_FULL)
1716 track_list_unalloc_track(); /* Free this entry */
1718 playlist_peek_offset--; /* Maintain at last index */
1720 /* We can end up here after the real last track signals its completion
1721 and miss the transition to STATE_FINISHED esp. if dropping the last
1722 songs of a playlist late in their load (2nd stage) */
1723 info = track_list_last(0);
1725 if (info && buf_handle_remaining(info->audio_hid) == 0)
1726 filling_is_finished();
1727 else
1728 filling = STATE_END_OF_PLAYLIST;
1730 return LOAD_TRACK_ERR_NO_MORE;
1733 /* Successfully opened the file - get track metadata */
1734 if (filling == STATE_FULL ||
1735 (info->id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL)) < 0)
1737 /* Buffer or track list is full */
1738 struct mp3entry *ub_id3;
1740 playlist_peek_offset--;
1742 /* Load the metadata for the first unbuffered track */
1743 ub_id3 = id3_get(UNBUFFERED_ID3);
1744 id3_mutex_lock();
1745 get_metadata(ub_id3, fd, trackname);
1746 id3_mutex_unlock();
1748 if (filling != STATE_FULL)
1750 track_list_unalloc_track();
1751 filling = STATE_FULL;
1754 logf("%s: buffer is full for now (%u tracks)", __func__,
1755 track_list_count());
1757 else
1759 /* Successful load initiation */
1760 info->filesize = filesize(fd);
1761 in_progress_id3_hid = info->id3_hid; /* Remember what's in-progress */
1764 close(fd);
1765 return LOAD_TRACK_OK;
1768 /* Second part of the track loading: We now have the metadata available, so we
1769 can load the codec, the album art and finally the audio data.
1770 This is called on the audio thread after the buffering thread calls the
1771 buffering_handle_finished_callback callback. */
1772 static int audio_finish_load_track(struct track_info *info)
1774 int trackstat = LOAD_TRACK_OK;
1776 if (info->id3_hid != in_progress_id3_hid)
1778 /* We must not be here if not! */
1779 logf("%s: wrong track %d/%d", __func__, info->id3_hid,
1780 in_progress_id3_hid);
1781 return LOAD_TRACK_ERR_BUSY;
1784 /* The current track for decoding (there is always one if the list is
1785 populated) */
1786 struct track_info *cur_info = track_list_current(0);
1787 struct mp3entry *track_id3 = valid_mp3entry(bufgetid3(info->id3_hid));
1789 if (!track_id3)
1791 /* This is an error condition. Track cannot be played without valid
1792 metadata; skip the track. */
1793 logf("No metadata for: %s", track_id3->path);
1794 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1795 goto audio_finish_load_track_exit;
1798 /* Try to load a cuesheet for the track */
1799 if (!audio_load_cuesheet(info, track_id3))
1801 /* No space for cuesheet on buffer, not an error */
1802 filling = STATE_FULL;
1803 goto audio_finish_load_track_exit;
1806 #ifdef HAVE_ALBUMART
1807 /* Try to load album art for the track */
1808 if (!audio_load_albumart(info, track_id3))
1810 /* No space for album art on buffer, not an error */
1811 filling = STATE_FULL;
1812 goto audio_finish_load_track_exit;
1814 #endif
1816 /* All handles available to external routines are ready - audio and codec
1817 information is private */
1819 if (info == track_list_user_current(0))
1821 /* Send only when the track handles could not all be opened ahead of
1822 time for the user's current track - otherwise everything is ready
1823 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1824 send_event(PLAYBACK_EVENT_CUR_TRACK_READY, id3_get(PLAYING_ID3));
1827 #ifdef HAVE_CODEC_BUFFERING
1828 /* Try to buffer a codec for the track */
1829 if (info != cur_info && !audio_buffer_codec(info, track_id3))
1831 if (info->codec_hid == ERR_BUFFER_FULL)
1833 /* No space for codec on buffer, not an error */
1834 filling = STATE_FULL;
1835 logf("buffer is full for now (%s)", __func__);
1837 else
1839 /* This is an error condition, either no codec was found, or
1840 reading the codec file failed part way through, either way,
1841 skip the track */
1842 logf("No codec for: %s", track_id3->path);
1843 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1846 goto audio_finish_load_track_exit;
1848 #endif /* HAVE_CODEC_BUFFERING */
1850 /** Finally, load the audio **/
1851 size_t file_offset = 0;
1852 track_id3->elapsed = 0;
1854 if (track_id3->offset >= info->filesize)
1855 track_id3->offset = 0;
1857 logf("%s: set offset for %s to %lu\n", __func__,
1858 id3->title, (unsigned long)offset);
1860 /* Adjust for resume rewind so we know what to buffer - starting the codec
1861 calls it again, so we don't save it (and they shouldn't accumulate) */
1862 size_t offset = resume_rewind_adjusted_offset(track_id3);
1864 enum data_type audiotype = get_audio_base_data_type(track_id3->codectype);
1866 if (audiotype == TYPE_ATOMIC_AUDIO)
1867 logf("Loading atomic %d", track_id3->codectype);
1869 if (format_buffers_with_offset(track_id3->codectype))
1871 /* This format can begin buffering from any point */
1872 file_offset = offset;
1875 logf("load track: %s", track_id3->path);
1877 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1879 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1880 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1882 else
1884 /* No offset given or it is very minimal - begin at the first frame
1885 according to the metadata */
1886 file_offset = track_id3->first_frame_offset;
1889 int hid = bufopen(track_id3->path, file_offset, audiotype, NULL);
1891 if (hid >= 0)
1893 info->audio_hid = hid;
1895 if (info == cur_info)
1897 /* This is the current track to decode - should be started now */
1898 trackstat = LOAD_TRACK_READY;
1901 else
1903 /* Buffer could be full but not properly so if this is the only
1904 track! */
1905 if (hid == ERR_BUFFER_FULL && audio_track_count() > 1)
1907 filling = STATE_FULL;
1908 logf("Buffer is full for now (%s)", __func__);
1910 else
1912 /* Nothing to play if no audio handle - skip this */
1913 logf("Could not add audio data handle");
1914 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1918 audio_finish_load_track_exit:
1919 if (trackstat < LOAD_TRACK_OK)
1921 playlist_skip_entry(NULL, playlist_peek_offset);
1922 track_info_close(info);
1923 track_list_unalloc_track();
1925 if (playlist_peek(playlist_peek_offset, NULL, 0))
1926 playlist_next(0);
1928 playlist_peek_offset--;
1931 if (filling != STATE_FULL)
1933 /* Load next track - error or not */
1934 in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
1935 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1936 audio_queue_post(Q_AUDIO_FILL_BUFFER, 0);
1938 else
1940 /* Full */
1941 trackstat = LOAD_TRACK_ERR_FINISH_FULL;
1944 return trackstat;
1947 /* Start a new track load */
1948 static int audio_fill_file_buffer(void)
1950 if (play_status == PLAY_STOPPED)
1951 return LOAD_TRACK_ERR_FAILED;
1953 trigger_cpu_boost();
1955 /* Must reset the buffer before use if trashed or voice only - voice
1956 file size shouldn't have changed so we can go straight from
1957 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1958 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1959 audio_reset_buffer();
1961 logf("Starting buffer fill");
1963 int trackstat = audio_load_track();
1965 if (trackstat >= LOAD_TRACK_OK)
1967 if (track_list_current(0) == track_list_user_current(0))
1968 playlist_next(0);
1970 if (filling == STATE_FULL && !track_list_user_current(1))
1972 /* There are no user tracks on the buffer after this therefore
1973 this is the next track */
1974 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3));
1978 return trackstat;
1981 /* Discard unwanted tracks and start refill from after the specified playlist
1982 offset */
1983 static int audio_reset_and_rebuffer(
1984 enum track_clear_action action, int peek_offset)
1986 logf("Forcing rebuffer: 0x%X, %d", flags, peek_offset);
1988 id3_write_locked(UNBUFFERED_ID3, NULL);
1990 /* Remove unwanted tracks - caller must have ensured codec isn't using
1991 any */
1992 track_list_clear(action);
1994 /* Refill at specified position (-1 starts at index offset 0) */
1995 playlist_peek_offset = peek_offset;
1997 /* Fill the buffer */
1998 return audio_fill_file_buffer();
2001 /* Handle buffering events
2002 (Q_AUDIO_BUFFERING) */
2003 static void audio_on_buffering(int event)
2005 enum track_clear_action action;
2006 int peek_offset;
2008 if (track_list_empty())
2009 return;
2011 switch (event)
2013 case BUFFER_EVENT_BUFFER_LOW:
2014 if (filling != STATE_FULL && filling != STATE_END_OF_PLAYLIST)
2015 return; /* Should be nothing left to fill */
2017 /* Clear old tracks and continue buffering where it left off */
2018 action = TRACK_LIST_KEEP_NEW;
2019 peek_offset = playlist_peek_offset;
2020 break;
2022 case BUFFER_EVENT_REBUFFER:
2023 /* Remove all but the currently decoding track and redo buffering
2024 after that */
2025 action = TRACK_LIST_KEEP_CURRENT;
2026 peek_offset = (skip_pending == TRACK_SKIP_AUTO) ? 1 : 0;
2027 break;
2029 default:
2030 return;
2033 switch (skip_pending)
2035 case TRACK_SKIP_NONE:
2036 case TRACK_SKIP_AUTO:
2037 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2038 audio_reset_and_rebuffer(action, peek_offset);
2039 break;
2041 case TRACK_SKIP_AUTO_END_PLAYLIST:
2042 /* Already finished */
2043 break;
2045 default:
2046 /* Invalid */
2047 logf("Buffering call, inv. state: %d", (int)skip_pending);
2051 /* Handle starting the next track load
2052 (Q_AUDIO_FILL_BUFFER) */
2053 static void audio_on_fill_buffer(void)
2055 audio_handle_track_load_status(audio_fill_file_buffer());
2058 /* Handle posted load track finish event
2059 (Q_AUDIO_FINISH_LOAD_TRACK) */
2060 static void audio_on_finish_load_track(int id3_hid)
2062 struct track_info *info = track_list_last(0);
2064 if (!info || !buf_is_handle(id3_hid))
2065 return;
2067 if (info == track_list_user_current(1))
2069 /* Just loaded the metadata right after the current position */
2070 audio_update_and_announce_next_track(bufgetid3(info->id3_hid));
2073 if (audio_finish_load_track(info) != LOAD_TRACK_READY)
2074 return; /* Not current track */
2076 bool is_user_current = info == track_list_user_current(0);
2078 if (is_user_current)
2080 /* Copy cuesheet */
2081 buf_read_cuesheet(info->cuesheet_hid);
2084 if (audio_start_codec(automatic_skip))
2086 if (is_user_current)
2088 /* Be sure all tagtree info is synchronized; it will be needed for the
2089 track finish event - the sync will happen when finalizing a track
2090 change otherwise */
2091 bool was_valid = valid_mp3entry(id3_get(PLAYING_ID3));
2093 playing_id3_sync(info, -1);
2095 if (!was_valid)
2097 /* Playing id3 hadn't been updated yet because no valid track
2098 was yet available - treat like the first track */
2099 audio_playlist_track_change();
2103 else
2105 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2109 /* Called when handles other than metadata handles have finished buffering
2110 (Q_AUDIO_HANDLE_FINISHED) */
2111 static void audio_on_handle_finished(int hid)
2113 /* Right now, only audio handles should end up calling this */
2114 if (filling == STATE_END_OF_PLAYLIST)
2116 struct track_info *info = track_list_last(0);
2118 /* Really we don't know which order the handles will actually complete
2119 to zero bytes remaining since another thread is doing it - be sure
2120 it's the right one */
2121 if (info && info->audio_hid == hid)
2123 /* This was the last track in the playlist and we now have all the
2124 data we need */
2125 filling_is_finished();
2130 /* Called to make an outstanding track skip the current track and to send the
2131 transition events */
2132 static void audio_finalise_track_change(bool delayed)
2134 switch (skip_pending)
2136 case TRACK_SKIP_NONE: /* Manual skip */
2137 break;
2139 case TRACK_SKIP_AUTO:
2140 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2142 int playlist_delta = skip_pending == TRACK_SKIP_AUTO ? 1 : 0;
2143 audio_playlist_track_finish();
2145 if (!playlist_peek(playlist_delta, NULL, 0))
2147 /* Track ended up rejected - push things ahead like the codec blew
2148 it (because it was never started and now we're here where it
2149 should have been decoding the next track by now) - next, a
2150 directory change or end of playback will most likely happen */
2151 skip_pending = TRACK_SKIP_NONE;
2152 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2153 return;
2156 if (!playlist_delta)
2157 break;
2159 playlist_peek_offset -= playlist_delta;
2160 if (playlist_next(playlist_delta) >= 0)
2161 break;
2162 /* What!? Disappear? Hopeless bleak despair */
2164 /* Fallthrough */
2165 case TRACK_SKIP_AUTO_END_PLAYLIST:
2166 default: /* Invalid */
2167 filling = STATE_ENDED;
2168 audio_stop_playback();
2169 return;
2172 struct track_info *info = track_list_current(0);
2173 struct mp3entry *track_id3 = NULL;
2175 id3_mutex_lock();
2177 /* Update the current cuesheet if any and enabled */
2178 if (info)
2180 buf_read_cuesheet(info->cuesheet_hid);
2181 track_id3 = bufgetid3(info->id3_hid);
2184 id3_write(PLAYING_ID3, track_id3);
2186 if (delayed)
2188 /* Delayed skip where codec is ahead of user's current track */
2189 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
2190 struct mp3entry *ply_id3 = id3_get(PLAYING_ID3);
2191 ply_id3->elapsed = ci_id3->elapsed;
2192 ply_id3->offset = ci_id3->offset;
2195 /* The skip is technically over */
2196 skip_pending = TRACK_SKIP_NONE;
2198 /* Sync the next track information */
2199 info = track_list_current(1);
2201 id3_write(NEXTTRACK_ID3, info ? bufgetid3(info->id3_hid) :
2202 id3_get(UNBUFFERED_ID3));
2204 id3_mutex_unlock();
2206 audio_playlist_track_change();
2209 /* Actually begin a transition and take care of the codec change - may complete
2210 it now or ask pcmbuf for notification depending on the type and what pcmbuf
2211 has to say */
2212 static void audio_begin_track_change(bool auto_skip, int trackstat)
2214 /* Even if the new track is bad, the old track must be finished off */
2215 bool finalised = pcmbuf_start_track_change(auto_skip);
2217 if (finalised)
2219 /* pcmbuf says that the transition happens now - complete it */
2220 audio_finalise_track_change(false);
2222 if (play_status == PLAY_STOPPED)
2223 return; /* Stopped us */
2226 if (!auto_skip)
2227 audio_clear_paused_pcm();
2229 if (trackstat >= LOAD_TRACK_OK)
2231 struct track_info *info = track_list_current(0);
2233 if (info->audio_hid < 0)
2234 return;
2236 /* Everything needed for the codec is ready - start it */
2237 if (audio_start_codec(auto_skip))
2239 if (finalised)
2240 playing_id3_sync(info, -1);
2241 return;
2244 trackstat = LOAD_TRACK_ERR_START_CODEC;
2247 audio_handle_track_load_status(trackstat);
2250 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2251 static void audio_monitor_end_of_playlist(void)
2253 skip_pending = TRACK_SKIP_AUTO_END_PLAYLIST;
2254 filling = STATE_ENDING;
2255 pcmbuf_monitor_track_change(true);
2258 /* Codec has completed decoding the track
2259 (usually Q_AUDIO_CODEC_COMPLETE) */
2260 static void audio_on_codec_complete(int status)
2262 logf("%s(%d)", __func__, status);
2264 if (play_status == PLAY_STOPPED)
2265 return;
2267 /* If it didn't notify us first, don't expect "seek complete" message
2268 since the codec can't post it now - do things like it would have
2269 done */
2270 audio_complete_codec_seek();
2272 if (play_status == PLAY_PAUSED || skip_pending != TRACK_SKIP_NONE)
2274 /* Old-hay on the ip-skay - codec has completed decoding
2276 Paused: We're not sounding it, so just remember that it happened
2277 and the resume will begin the transition
2279 Skipping: There was already a skip in progress, remember it and
2280 allow no further progress until the PCM from the previous
2281 song has finished
2283 codec_skip_pending = true;
2284 codec_skip_status = status;
2285 return;
2288 codec_skip_pending = false;
2290 #ifdef AB_REPEAT_ENABLE
2291 if (status >= 0)
2293 /* Normal automatic skip */
2294 ab_end_of_track_report();
2296 #endif
2298 int trackstat = LOAD_TRACK_OK;
2300 automatic_skip = true;
2301 skip_pending = TRACK_SKIP_AUTO;
2303 /* Does this track have an entry allocated? */
2304 struct track_info *info = track_list_advance_current(1);
2306 if (!info || info->audio_hid < 0)
2308 bool end_of_playlist = false;
2310 if (info)
2312 /* Track load is not complete - it might have stopped on a
2313 full buffer without reaching the audio handle or we just
2314 arrived at it early
2316 If this type is atomic and we couldn't get the audio,
2317 perhaps it would need to wrap to make the allocation and
2318 handles are in the way - to maximize the liklihood it can
2319 be allocated, clear all handles to reset the buffer and
2320 its indexes to 0 - for packet audio, this should not be an
2321 issue and a pointless full reload of all the track's
2322 metadata may be avoided */
2324 struct mp3entry *track_id3 = bufgetid3(info->id3_hid);
2326 if (track_id3 &&
2327 get_audio_base_data_type(track_id3->codectype)
2328 == TYPE_PACKET_AUDIO)
2330 /* Continue filling after this track */
2331 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT, 1);
2332 audio_begin_track_change(true, trackstat);
2333 return;
2335 /* else rebuffer at this track; status applies to the track we
2336 want */
2338 else if (!playlist_peek(1, NULL, 0))
2340 /* Play sequence is complete - directory change or other playlist
2341 resequencing - the playlist must now be advanced in order to
2342 continue since a peek ahead to the next track is not possible */
2343 skip_pending = TRACK_SKIP_AUTO_NEW_PLAYLIST;
2344 end_of_playlist = playlist_next(1) < 0;
2347 if (!end_of_playlist)
2349 trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL,
2350 skip_pending == TRACK_SKIP_AUTO ? 0 : -1);
2352 if (trackstat == LOAD_TRACK_ERR_NO_MORE)
2354 /* Failed to find anything after all - do playlist switchover
2355 instead */
2356 skip_pending = TRACK_SKIP_AUTO_NEW_PLAYLIST;
2357 end_of_playlist = playlist_next(1) < 0;
2361 if (end_of_playlist)
2363 audio_monitor_end_of_playlist();
2364 return;
2368 audio_begin_track_change(true, trackstat);
2371 /* Called when codec completes seek operation
2372 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2373 static void audio_on_codec_seek_complete(void)
2375 logf("%s()", __func__);
2376 audio_complete_codec_seek();
2377 codec_go();
2380 /* Called when PCM track change has completed
2381 (Q_AUDIO_TRACK_CHANGED) */
2382 static void audio_on_track_changed(void)
2384 /* Finish whatever is pending so that the WPS is in sync */
2385 audio_finalise_track_change(true);
2387 if (codec_skip_pending)
2389 /* Codec got ahead completing a short track - complete the
2390 codec's skip and begin the next */
2391 codec_skip_pending = false;
2392 audio_on_codec_complete(codec_skip_status);
2396 /* Begin playback from an idle state, transition to a new playlist or
2397 invalidate the buffer and resume (if playing).
2398 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2399 static void audio_start_playback(size_t offset, unsigned int flags)
2401 enum play_status old_status = play_status;
2403 if (flags & AUDIO_START_NEWBUF)
2405 /* Mark the buffer dirty - if not playing, it will be reset next
2406 time */
2407 if (buffer_state == AUDIOBUF_STATE_INITIALIZED)
2408 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
2411 if (old_status != PLAY_STOPPED)
2413 logf("%s(%lu): skipping", __func__, (unsigned long)offset);
2415 halt_decoding_track(true);
2417 automatic_skip = false;
2418 ff_rw_mode = false;
2420 if (flags & AUDIO_START_RESTART)
2422 /* Clear out some stuff to resume the current track where it
2423 left off */
2424 pcmbuf_play_stop();
2425 offset = id3_get(PLAYING_ID3)->offset;
2426 track_list_clear(TRACK_LIST_CLEAR_ALL);
2428 else
2430 /* This is more-or-less treated as manual track transition */
2431 /* Save resume information for current track */
2432 audio_playlist_track_finish();
2433 track_list_clear(TRACK_LIST_CLEAR_ALL);
2435 /* Indicate manual track change */
2436 pcmbuf_start_track_change(false);
2437 audio_clear_paused_pcm();
2438 wipe_track_metadata(true);
2441 /* Set after track finish event in case skip was in progress */
2442 skip_pending = TRACK_SKIP_NONE;
2444 else
2446 if (flags & AUDIO_START_RESTART)
2447 return; /* Must already be playing */
2449 /* Cold playback start from a stopped state */
2450 logf("%s(%lu): starting", __func__, offset);
2452 /* Set audio parameters */
2453 #if INPUT_SRC_CAPS != 0
2454 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2455 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2456 #endif
2457 #ifndef PLATFORM_HAS_VOLUME_CHANGE
2458 sound_set_volume(global_settings.volume);
2459 #endif
2460 /* Be sure channel is audible */
2461 pcmbuf_fade(false, true);
2463 /* Update our state */
2464 play_status = PLAY_PLAYING;
2467 /* Start fill from beginning of playlist */
2468 playlist_peek_offset = -1;
2469 buf_set_base_handle(-1);
2471 /* Officially playing */
2472 queue_reply(&audio_queue, 1);
2474 /* Add these now - finish event for the first id3 will most likely be sent
2475 immediately */
2476 add_event(BUFFER_EVENT_REBUFFER, false, buffer_event_rebuffer_callback);
2477 add_event(BUFFER_EVENT_FINISHED, false, buffer_event_finished_callback);
2479 if (old_status == PLAY_STOPPED)
2481 /* Send coldstart event */
2482 send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL);
2485 /* Fill the buffer */
2486 int trackstat = audio_fill_file_buffer();
2488 if (trackstat >= LOAD_TRACK_OK)
2490 /* This is the currently playing track - get metadata, stat */
2491 playing_id3_sync(track_list_current(0), offset);
2493 if (valid_mp3entry(id3_get(PLAYING_ID3)))
2495 /* Only if actually changing tracks... */
2496 if (!(flags & AUDIO_START_RESTART))
2497 audio_playlist_track_change();
2500 else
2502 /* Found nothing playable */
2503 audio_handle_track_load_status(trackstat);
2507 /* Stop playback and enter an idle state
2508 (usually Q_AUDIO_STOP) */
2509 static void audio_stop_playback(void)
2511 logf("%s()", __func__);
2513 if (play_status == PLAY_STOPPED)
2514 return;
2516 pcmbuf_fade(global_settings.fade_on_stop, false);
2518 /* Stop the codec and unload it */
2519 halt_decoding_track(true);
2520 pcmbuf_play_stop();
2521 codec_unload();
2523 /* Save resume information - "filling" might have been set to
2524 "STATE_ENDED" by caller in order to facilitate end of playlist */
2525 audio_playlist_track_finish();
2527 skip_pending = TRACK_SKIP_NONE;
2528 automatic_skip = false;
2530 /* Close all tracks and mark them NULL */
2531 remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
2532 remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
2533 remove_event(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback);
2535 track_list_clear(TRACK_LIST_CLEAR_ALL);
2537 /* Update our state */
2538 ff_rw_mode = false;
2539 play_status = PLAY_STOPPED;
2541 wipe_track_metadata(true);
2543 /* Go idle */
2544 filling = STATE_IDLE;
2545 cancel_cpu_boost();
2548 /* Pause the playback of the current track
2549 (Q_AUDIO_PAUSE) */
2550 static void audio_on_pause(bool pause)
2552 logf("%s(%s)", __func__, pause ? "true" : "false");
2554 if (play_status == PLAY_STOPPED || pause == (play_status == PLAY_PAUSED))
2555 return;
2557 bool const do_fade = global_settings.fade_on_stop;
2559 if (pause)
2560 pcmbuf_fade(do_fade, false);
2562 if (!ff_rw_mode)
2564 /* Not in ff/rw mode - may set the state (otherwise this could make
2565 old data play because seek hasn't completed and cleared it) */
2566 pcmbuf_pause(pause);
2569 if (!pause)
2570 pcmbuf_fade(do_fade, true);
2572 play_status = pause ? PLAY_PAUSED : PLAY_PLAYING;
2574 if (!pause && codec_skip_pending)
2576 /* Actually do the skip that is due - resets the status flag */
2577 audio_on_codec_complete(codec_skip_status);
2581 /* Skip a certain number of tracks forwards or backwards
2582 (Q_AUDIO_SKIP) */
2583 static void audio_on_skip(void)
2585 id3_mutex_lock();
2587 /* Eat the delta to keep it synced, even if not playing */
2588 int toskip = skip_offset;
2589 skip_offset = 0;
2591 logf("%s(): %d", __func__, toskip);
2593 id3_mutex_unlock();
2595 if (play_status == PLAY_STOPPED)
2596 return;
2598 /* Force codec to abort this track */
2599 halt_decoding_track(true);
2601 /* Kill the ff/rw halt */
2602 ff_rw_mode = false;
2604 /* Manual skip */
2605 automatic_skip = false;
2607 /* If there was an auto skip in progress, there will be residual
2608 advancement of the playlist and/or track list so compensation will be
2609 required in order to end up in the right spot */
2610 int track_list_delta = toskip;
2611 int playlist_delta = toskip;
2613 if (skip_pending != TRACK_SKIP_NONE)
2615 if (skip_pending != TRACK_SKIP_AUTO_END_PLAYLIST)
2616 track_list_delta--;
2618 if (skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)
2619 playlist_delta--;
2622 audio_playlist_track_finish();
2623 skip_pending = TRACK_SKIP_NONE;
2625 /* Update the playlist current track now */
2626 while (playlist_next(playlist_delta) < 0)
2628 /* Manual skip out of range (because the playlist wasn't updated
2629 yet by us and so the check in audio_skip returned 'ok') - bring
2630 back into range */
2631 int d = toskip < 0 ? 1 : -1;
2633 while (!playlist_check(playlist_delta))
2635 if (playlist_delta == d)
2637 /* Had to move the opposite direction to correct, which is
2638 wrong - this is the end */
2639 filling = STATE_ENDED;
2640 audio_stop_playback();
2641 return;
2644 playlist_delta += d;
2645 track_list_delta += d;
2649 /* Adjust things by how much the playlist was manually moved */
2650 playlist_peek_offset -= playlist_delta;
2652 struct track_info *info = track_list_advance_current(track_list_delta);
2653 int trackstat = LOAD_TRACK_OK;
2655 if (!info || info->audio_hid < 0)
2657 /* We don't know the next track thus we know we don't have it */
2658 trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1);
2661 audio_begin_track_change(false, trackstat);
2664 /* Skip to the next/previous directory
2665 (Q_AUDIO_DIR_SKIP) */
2666 static void audio_on_dir_skip(int direction)
2668 logf("%s(%d)", __func__, direction);
2670 id3_mutex_lock();
2671 skip_offset = 0;
2672 id3_mutex_unlock();
2674 if (play_status == PLAY_STOPPED)
2675 return;
2677 /* Force codec to abort this track */
2678 halt_decoding_track(true);
2680 /* Kill the ff/rw halt */
2681 ff_rw_mode = false;
2683 /* Manual skip */
2684 automatic_skip = false;
2686 audio_playlist_track_finish();
2688 /* Unless automatic and gapless, skips do not pend */
2689 skip_pending = TRACK_SKIP_NONE;
2691 /* Regardless of the return value we need to rebuffer. If it fails the old
2692 playlist will resume, else the next dir will start playing. */
2693 playlist_next_dir(direction);
2695 wipe_track_metadata(false);
2697 int trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1);
2699 if (trackstat == LOAD_TRACK_ERR_NO_MORE)
2701 /* The day the music died - finish-off whatever is playing and call it
2702 quits */
2703 audio_monitor_end_of_playlist();
2704 return;
2707 audio_begin_track_change(false, trackstat);
2710 /* Enter seek mode in order to start a seek
2711 (Q_AUDIO_PRE_FF_REWIND) */
2712 static void audio_on_pre_ff_rewind(void)
2714 logf("%s()", __func__);
2716 if (play_status == PLAY_STOPPED || ff_rw_mode)
2717 return;
2719 ff_rw_mode = true;
2721 if (play_status == PLAY_PAUSED)
2722 return;
2724 pcmbuf_pause(true);
2727 /* Seek the playback of the current track to the specified time
2728 (Q_AUDIO_FF_REWIND) */
2729 static void audio_on_ff_rewind(long time)
2731 logf("%s(%ld)", __func__, time);
2733 if (play_status == PLAY_STOPPED)
2734 return;
2736 enum track_skip_type pending = skip_pending;
2738 switch (pending)
2740 case TRACK_SKIP_NONE: /* The usual case */
2741 case TRACK_SKIP_AUTO: /* Have to back it out (fun!) */
2742 case TRACK_SKIP_AUTO_END_PLAYLIST: /* Still have the last codec used */
2744 struct mp3entry *id3 = id3_get(PLAYING_ID3);
2745 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
2747 automatic_skip = false;
2749 /* Send event before clobbering the time */
2750 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2751 then skipping back to this track resumes properly. Something else
2752 should be sent. We're not _really_ finishing the track are we? */
2753 if (time == 0)
2754 send_event(PLAYBACK_EVENT_TRACK_FINISH, id3);
2756 /* Prevent user codec time update - coerce to something that is
2757 innocuous concerning lookaheads */
2758 if (pending == TRACK_SKIP_NONE)
2759 skip_pending = TRACK_SKIP_AUTO_END_PLAYLIST;
2761 id3->elapsed = time;
2762 queue_reply(&audio_queue, 1);
2764 bool haltres = halt_decoding_track(pending == TRACK_SKIP_AUTO);
2766 /* Need this set in case ff/rw mode + error but _after_ the codec
2767 halt that will reset it */
2768 codec_seeking = true;
2770 if (pending == TRACK_SKIP_AUTO)
2772 if (!track_list_advance_current(-1))
2774 /* Not in list - must rebuffer at the current playlist index */
2775 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1)
2776 < LOAD_TRACK_OK)
2778 /* Codec is stopped */
2779 break;
2784 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2785 rebuffer is needed */
2786 skip_pending = TRACK_SKIP_NONE;
2787 struct track_info *cur_info = track_list_current(0);
2789 /* Track must complete the loading _now_ since a codec and audio
2790 handle are needed in order to do the seek */
2791 if (cur_info->audio_hid < 0 &&
2792 audio_finish_load_track(cur_info) != LOAD_TRACK_READY)
2794 /* Call above should push any load sequence - no need for
2795 halt_decoding_track here if no skip was pending here because
2796 there would not be a codec started if no audio handle was yet
2797 opened */
2798 break;
2801 if (pending == TRACK_SKIP_AUTO)
2803 if (!bufreadid3(cur_info->id3_hid, ci_id3) ||
2804 !audio_init_codec(cur_info, ci_id3))
2806 /* We should have still been able to get it - skip it and move
2807 onto the next one - like it or not this track is broken */
2808 break;
2811 /* Set the codec API to the correct metadata and track info */
2812 ci.audio_hid = cur_info->audio_hid;
2813 ci.filesize = cur_info->filesize;
2814 buf_set_base_handle(cur_info->audio_hid);
2817 if (!haltres)
2819 /* If codec must be (re)started, reset the offset */
2820 ci_id3->offset = 0;
2823 codec_seek(time);
2824 return;
2827 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2829 /* We cannot do this because the playlist must be reversed by one
2830 and it doesn't always return the same song when going backwards
2831 across boundaries as forwards (either because of randomization
2832 or inconsistency in deciding what the previous track should be),
2833 therefore the whole operation would often end up as nonsense -
2834 lock out seeking for a couple seconds */
2836 /* Sure as heck cancel seek mode too! */
2837 audio_ff_rewind_end();
2838 return;
2841 default:
2842 /* Won't see this */
2843 return;
2846 if (play_status == PLAY_STOPPED)
2848 /* Playback ended because of an error completing a track load */
2849 return;
2852 /* Always fake it as a codec start error which will handle mode
2853 cancellations and skip to the next track */
2854 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2857 /* Invalidates all but currently playing track
2858 (Q_AUDIO_FLUSH) */
2859 static void audio_on_audio_flush(void)
2861 logf("%s", __func__);
2863 if (track_list_empty())
2864 return; /* Nothing to flush out */
2866 switch (skip_pending)
2868 case TRACK_SKIP_NONE:
2869 case TRACK_SKIP_AUTO_END_PLAYLIST:
2870 /* Remove all but the currently playing track from the list and
2871 refill after that */
2872 track_list_clear(TRACK_LIST_KEEP_CURRENT);
2873 playlist_peek_offset = 0;
2874 id3_write_locked(UNBUFFERED_ID3, NULL);
2875 audio_update_and_announce_next_track(NULL);
2877 /* Ignore return since it's about the next track, not this one */
2878 audio_fill_file_buffer();
2880 if (skip_pending == TRACK_SKIP_NONE)
2881 break;
2883 /* There's now a track after this one now - convert to auto skip -
2884 no skip should pend right now because multiple flush messages can
2885 be fired which would cause a restart in the below cases */
2886 skip_pending = TRACK_SKIP_NONE;
2887 audio_clear_track_notifications();
2888 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, CODEC_OK);
2889 break;
2891 case TRACK_SKIP_AUTO:
2892 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2893 /* Precisely removing what it already decoded for the next track is
2894 not possible so a restart is required in order to continue the
2895 currently playing track without the now invalid future track
2896 playing */
2897 audio_start_playback(0, AUDIO_START_RESTART);
2898 break;
2900 default: /* Nothing else is a state */
2901 break;
2905 #ifdef AUDIO_HAVE_RECORDING
2906 /* Load the requested encoder type
2907 (Q_AUDIO_LOAD_ENCODER) */
2908 static void audio_on_load_encoder(int afmt)
2910 bool res = true;
2912 if (play_status != PLAY_STOPPED)
2913 audio_stop_playback(); /* Can't load both types at once */
2914 else
2915 codec_unload(); /* Encoder still loaded, stop and unload it */
2917 if (afmt != AFMT_UNKNOWN)
2919 res = codec_load(-1, afmt | CODEC_TYPE_ENCODER);
2920 if (res)
2921 codec_go(); /* These are run immediately */
2924 queue_reply(&audio_queue, res);
2926 #endif /* AUDIO_HAVE_RECORDING */
2928 static void audio_thread(void)
2930 struct queue_event ev;
2932 pcm_postinit();
2934 filling = STATE_IDLE;
2936 while (1)
2938 switch (filling)
2940 /* Active states */
2941 case STATE_FULL:
2942 case STATE_END_OF_PLAYLIST:
2943 if (buf_get_watermark() == 0)
2945 /* End of buffering for now, let's calculate the watermark,
2946 register for a low buffer event and unboost */
2947 audio_update_filebuf_watermark(0);
2948 add_event(BUFFER_EVENT_BUFFER_LOW, true,
2949 buffer_event_buffer_low_callback);
2951 /* Fall-through */
2952 case STATE_FINISHED:
2953 /* All data was buffered */
2954 cancel_cpu_boost();
2955 /* Fall-through */
2956 case STATE_FILLING:
2957 case STATE_ENDING:
2958 if (audio_pcmbuf_track_change_scan())
2960 /* Transfer notification to audio queue event */
2961 ev.id = Q_AUDIO_TRACK_CHANGED;
2962 ev.data = 1;
2964 else
2966 /* If doing auto skip, poll pcmbuf track notifications a bit
2967 faster to promply detect the transition */
2968 queue_wait_w_tmo(&audio_queue, &ev,
2969 skip_pending == TRACK_SKIP_NONE ?
2970 HZ/2 : HZ/10);
2972 break;
2974 /* Idle states */
2975 default:
2976 queue_wait(&audio_queue, &ev);
2978 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2979 switch (ev.id)
2981 #ifdef AUDIO_HAVE_RECORDING
2982 /* Must monitor the encoder message for recording so it can remove
2983 it if we process the insertion before it does. It cannot simply
2984 be removed from under recording however. */
2985 case Q_AUDIO_LOAD_ENCODER:
2986 break;
2987 #endif
2988 case SYS_USB_DISCONNECTED:
2989 filling = STATE_IDLE;
2990 break;
2992 default:
2993 if (filling == STATE_USB)
2994 continue;
2996 #endif /* CONFIG_PLATFORM */
2999 switch (ev.id)
3001 /** Codec and track change messages **/
3002 case Q_AUDIO_CODEC_COMPLETE:
3003 /* Codec is done processing track and has gone idle */
3004 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev.data);
3005 audio_on_codec_complete(ev.data);
3006 break;
3008 case Q_AUDIO_CODEC_SEEK_COMPLETE:
3009 /* Codec is done seeking */
3010 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
3011 audio_on_codec_seek_complete();
3012 break;
3014 case Q_AUDIO_TRACK_CHANGED:
3015 /* PCM track change done */
3016 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3017 audio_on_track_changed();
3018 break;
3020 /** Control messages **/
3021 case Q_AUDIO_PLAY:
3022 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3023 audio_start_playback(ev.data, 0);
3024 break;
3026 case Q_AUDIO_STOP:
3027 LOGFQUEUE("audio < Q_AUDIO_STOP");
3028 audio_stop_playback();
3029 if (ev.data != 0)
3030 queue_clear(&audio_queue);
3031 break;
3033 case Q_AUDIO_PAUSE:
3034 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3035 audio_on_pause(ev.data);
3036 break;
3038 case Q_AUDIO_SKIP:
3039 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3040 audio_on_skip();
3041 break;
3043 case Q_AUDIO_DIR_SKIP:
3044 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3045 audio_on_dir_skip(ev.data);
3046 break;
3048 case Q_AUDIO_PRE_FF_REWIND:
3049 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3050 audio_on_pre_ff_rewind();
3051 break;
3053 case Q_AUDIO_FF_REWIND:
3054 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3055 audio_on_ff_rewind(ev.data);
3056 break;
3058 case Q_AUDIO_FLUSH:
3059 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev.data);
3060 audio_on_audio_flush();
3061 break;
3063 /** Buffering messages **/
3064 case Q_AUDIO_BUFFERING:
3065 /* some buffering event */
3066 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev.data);
3067 audio_on_buffering(ev.data);
3068 break;
3070 case Q_AUDIO_FILL_BUFFER:
3071 /* continue buffering next track */
3072 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3073 audio_on_fill_buffer();
3074 break;
3076 case Q_AUDIO_FINISH_LOAD_TRACK:
3077 /* metadata is buffered */
3078 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3079 audio_on_finish_load_track(ev.data);
3080 break;
3082 case Q_AUDIO_HANDLE_FINISHED:
3083 /* some other type is buffered */
3084 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3085 audio_on_handle_finished(ev.data);
3086 break;
3088 /** Miscellaneous messages **/
3089 case Q_AUDIO_REMAKE_AUDIO_BUFFER:
3090 /* buffer needs to be reinitialized */
3091 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3092 audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
3093 break;
3095 #ifdef HAVE_DISK_STORAGE
3096 case Q_AUDIO_UPDATE_WATERMARK:
3097 /* buffering watermark needs updating */
3098 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev.data);
3099 audio_update_filebuf_watermark(ev.data);
3100 break;
3101 #endif /* HAVE_DISK_STORAGE */
3103 #ifdef AUDIO_HAVE_RECORDING
3104 case Q_AUDIO_LOAD_ENCODER:
3105 /* load an encoder for recording */
3106 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev.data);
3107 audio_on_load_encoder(ev.data);
3108 break;
3109 #endif /* AUDIO_HAVE_RECORDING */
3111 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3112 case SYS_USB_CONNECTED:
3113 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3114 audio_stop_playback();
3115 #ifdef PLAYBACK_VOICE
3116 voice_stop();
3117 #endif
3118 filling = STATE_USB;
3119 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3120 break;
3121 #endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */
3123 case SYS_TIMEOUT:
3124 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3125 break;
3127 default:
3128 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3129 break;
3130 } /* end switch */
3131 } /* end while */
3135 /* --- Buffering callbacks --- */
3137 /* Called when fullness is below the watermark level */
3138 static void buffer_event_buffer_low_callback(void *data)
3140 logf("low buffer callback");
3141 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3142 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW);
3143 (void)data;
3146 /* Called when handles must be discarded in order to buffer new data */
3147 static void buffer_event_rebuffer_callback(void *data)
3149 logf("rebuffer callback");
3150 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3151 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER);
3152 (void)data;
3155 /* A handle has completed buffering and all required data is available */
3156 static void buffer_event_finished_callback(void *data)
3158 int hid = *(const int *)data;
3159 const enum data_type htype = buf_handle_data_type(hid);
3161 logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype);
3163 /* Limit queue traffic */
3164 switch (htype)
3166 case TYPE_ID3:
3167 /* The metadata handle for the last loaded track has been buffered.
3168 We can ask the audio thread to load the rest of the track's data. */
3169 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid);
3170 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK, hid);
3171 break;
3173 case TYPE_PACKET_AUDIO:
3174 /* Strip any useless trailing tags that are left. */
3175 strip_tags(hid);
3176 /* Fall-through */
3177 case TYPE_ATOMIC_AUDIO:
3178 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid);
3179 audio_queue_post(Q_AUDIO_HANDLE_FINISHED, hid);
3180 break;
3182 default:
3183 /* Don't care to know about these */
3184 break;
3189 /** -- Codec callbacks -- **/
3191 /* Update elapsed times with latency-adjusted values */
3192 void audio_codec_update_elapsed(unsigned long value)
3194 #ifdef AB_REPEAT_ENABLE
3195 ab_position_report(value);
3196 #endif
3198 unsigned long latency = pcmbuf_get_latency();
3200 if (LIKELY(value >= latency))
3202 unsigned long elapsed = value - latency;
3204 if (elapsed > value || elapsed < value - 2)
3205 value = elapsed;
3207 else
3209 value = 0;
3212 /* Track codec: used later when updating the playing at the user
3213 transition */
3214 id3_get(CODEC_ID3)->elapsed = value;
3216 /* If a skip is pending, the PCM buffer is updating the time on the
3217 previous song */
3218 if (LIKELY(skip_pending == TRACK_SKIP_NONE))
3219 id3_get(PLAYING_ID3)->elapsed = value;
3222 /* Update offsets with latency-adjusted values */
3223 void audio_codec_update_offset(size_t value)
3225 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
3226 unsigned long latency = pcmbuf_get_latency() * ci_id3->bitrate / 8;
3228 if (LIKELY(value >= latency))
3230 value -= latency;
3232 else
3234 value = 0;
3237 /* Track codec: used later when updating the playing id3 at the user
3238 transition */
3239 ci_id3->offset = value;
3241 /* If a skip is pending, the PCM buffer is updating the time on the
3242 previous song */
3243 if (LIKELY(skip_pending == TRACK_SKIP_NONE))
3244 id3_get(PLAYING_ID3)->offset = value;
3248 /** --- Pcmbuf callbacks --- **/
3250 /* Between the codec and PCM track change, we need to keep updating the
3251 * "elapsed" value of the previous (to the codec, but current to the
3252 * user/PCM/WPS) track, so that the progressbar reaches the end. */
3253 void audio_pcmbuf_position_callback(unsigned int time)
3255 struct mp3entry *id3 = id3_get(PLAYING_ID3);
3257 time += id3->elapsed;
3259 id3->elapsed = MIN(time, id3->length);
3262 /* Post message from pcmbuf that the end of the previous track has just
3263 * been played */
3264 void audio_pcmbuf_track_change(bool pcmbuf)
3266 if (pcmbuf)
3268 /* Notify of the change in special-purpose semaphore object */
3269 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3270 audio_pcmbuf_track_change_post();
3272 else
3274 /* Safe to post directly to the queue */
3275 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3276 audio_queue_post(Q_AUDIO_TRACK_CHANGED, 0);
3280 /* May pcmbuf start PCM playback when the buffer is full enough? */
3281 bool audio_pcmbuf_may_play(void)
3283 return play_status == PLAY_PLAYING && !ff_rw_mode;
3287 /** -- External interfaces -- **/
3289 /* Return the playback and recording status */
3290 int audio_status(void)
3292 unsigned int ret = play_status;
3294 #ifdef AUDIO_HAVE_RECORDING
3295 /* Do this here for constitency with mpeg.c version */
3296 ret |= pcm_rec_status();
3297 #endif
3299 return (int)ret;
3302 /* Clear all accumulated audio errors for playback and recording */
3303 void audio_error_clear(void)
3305 #ifdef AUDIO_HAVE_RECORDING
3306 pcm_rec_error_clear();
3307 #endif
3310 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3311 bool audio_peek_track(struct mp3entry *id3, int offset)
3313 bool retval = false;
3315 id3_mutex_lock();
3317 if (play_status != PLAY_STOPPED)
3319 id3->path[0] = '\0'; /* Null path means it should be filled now */
3320 retval = audio_get_track_metadata(offset + skip_offset, id3) &&
3321 id3->path[0] != '\0';
3324 id3_mutex_unlock();
3326 return retval;
3329 /* Return the mp3entry for the currently playing track */
3330 struct mp3entry * audio_current_track(void)
3332 struct mp3entry *id3;
3334 id3_mutex_lock();
3336 #ifdef AUDIO_FAST_SKIP_PREVIEW
3337 if (skip_offset != 0)
3339 /* This is a peekahead */
3340 id3 = id3_get(PLAYING_PEEK_ID3);
3341 audio_peek_track(id3, 0);
3343 else
3344 #endif
3346 /* Normal case */
3347 id3 = id3_get(PLAYING_ID3);
3348 audio_get_track_metadata(0, id3);
3351 id3_mutex_unlock();
3353 return id3;
3356 /* Obtains the mp3entry for the next track from the current */
3357 struct mp3entry * audio_next_track(void)
3359 struct mp3entry *id3 = id3_get(NEXTTRACK_ID3);
3361 id3_mutex_lock();
3363 #ifdef AUDIO_FAST_SKIP_PREVIEW
3364 if (skip_offset != 0)
3366 /* This is a peekahead */
3367 if (!audio_peek_track(id3, 1))
3368 id3 = NULL;
3370 else
3371 #endif
3373 /* Normal case */
3374 if (!audio_get_track_metadata(1, id3))
3375 id3 = NULL;
3378 id3_mutex_unlock();
3380 return id3;
3383 /* Start playback at the specified offset */
3384 void audio_play(long offset)
3386 logf("audio_play");
3388 #ifdef PLAYBACK_VOICE
3389 /* Truncate any existing voice output so we don't have spelling
3390 * etc. over the first part of the played track */
3391 talk_force_shutup();
3392 #endif
3394 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
3395 audio_queue_send(Q_AUDIO_PLAY, offset);
3398 /* Stop playback if playing */
3399 void audio_stop(void)
3401 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3402 audio_queue_send(Q_AUDIO_STOP, 0);
3405 /* Pause playback if playing */
3406 void audio_pause(void)
3408 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3409 audio_queue_send(Q_AUDIO_PAUSE, true);
3412 /* This sends a stop message and the audio thread will dump all its
3413 subsequent messages */
3414 void audio_hard_stop(void)
3416 /* Stop playback */
3417 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3418 audio_queue_send(Q_AUDIO_STOP, 1);
3419 #ifdef PLAYBACK_VOICE
3420 voice_stop();
3421 #endif
3422 if (audiobuf_handle > 0)
3424 core_free(audiobuf_handle);
3425 audiobuf_handle = 0;
3429 /* Resume playback if paused */
3430 void audio_resume(void)
3432 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3433 audio_queue_send(Q_AUDIO_PAUSE, false);
3436 /* Skip the specified number of tracks forward or backward from the current */
3437 void audio_skip(int offset)
3439 id3_mutex_lock();
3441 /* If offset has to be backed-out to stay in range, no skip is done */
3442 int accum = skip_offset + offset;
3444 while (offset != 0 && !playlist_check(accum))
3446 offset += offset < 0 ? 1 : -1;
3447 accum = skip_offset + offset;
3450 if (offset != 0)
3452 /* Accumulate net manual skip count since the audio thread last
3453 processed one */
3454 skip_offset = accum;
3456 system_sound_play(SOUND_TRACK_SKIP);
3458 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset);
3460 #ifdef AUDIO_FAST_SKIP_PREVIEW
3461 /* Do this before posting so that the audio thread can correct us
3462 when things settle down - additionally, if audio gets a message
3463 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3464 handler a skip event with the correct info but doesn't skip */
3465 send_event(PLAYBACK_EVENT_TRACK_SKIP, NULL);
3466 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3468 /* Playback only needs the final state even if more than one is
3469 processed because it wasn't removed in time */
3470 queue_remove_from_head(&audio_queue, Q_AUDIO_SKIP);
3471 audio_queue_post(Q_AUDIO_SKIP, 0);
3473 else
3475 /* No more tracks */
3476 system_sound_play(SOUND_TRACK_NO_MORE);
3479 id3_mutex_unlock();
3482 /* Skip one track forward from the current */
3483 void audio_next(void)
3485 audio_skip(1);
3488 /* Skip one track backward from the current */
3489 void audio_prev(void)
3491 audio_skip(-1);
3494 /* Move one directory forward */
3495 void audio_next_dir(void)
3497 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3498 audio_queue_post(Q_AUDIO_DIR_SKIP, 1);
3501 /* Move one directory backward */
3502 void audio_prev_dir(void)
3504 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3505 audio_queue_post(Q_AUDIO_DIR_SKIP, -1);
3508 /* Pause playback in order to start a seek that flushes the old audio */
3509 void audio_pre_ff_rewind(void)
3511 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3512 audio_queue_post(Q_AUDIO_PRE_FF_REWIND, 0);
3515 /* Seek to the new time in the current track */
3516 void audio_ff_rewind(long time)
3518 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3519 audio_queue_post(Q_AUDIO_FF_REWIND, time);
3522 /* Clear all but the currently playing track then rebuffer */
3523 void audio_flush_and_reload_tracks(void)
3525 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3526 audio_queue_post(Q_AUDIO_FLUSH, 0);
3529 /* Return the pointer to the main audio buffer, optionally preserving
3530 voicing */
3531 unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3533 unsigned char *buf;
3535 if (audio_is_initialized)
3537 audio_hard_stop();
3539 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3541 if (buffer_size == NULL)
3543 /* Special case for talk_init to use since it already knows it's
3544 trashed */
3545 buffer_state = AUDIOBUF_STATE_TRASHED;
3546 return NULL;
3549 /* make sure buffer is freed and re-allocated to simplify code below
3550 * (audio_hard_stop() likely has done that already) */
3551 if (audiobuf_handle > 0)
3553 core_free(audiobuf_handle);
3554 audiobuf_handle = 0;
3557 audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops);
3558 buf = core_get_data(audiobuf_handle);
3560 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
3561 || !talk_voice_required())
3563 logf("get buffer: talk, audio");
3564 /* Ok to use everything from audiobuf - voice is loaded,
3565 the talk buffer is not needed because voice isn't being used, or
3566 could be AUDIOBUF_STATE_TRASHED already. If state is
3567 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3568 written without the caller knowing what's going on. Changing certain
3569 settings may move it to a worse condition but the memory in use by
3570 something else will remain undisturbed.
3572 if (buffer_state != AUDIOBUF_STATE_TRASHED)
3574 talk_buffer_steal();
3575 buffer_state = AUDIOBUF_STATE_TRASHED;
3578 else
3580 logf("get buffer: audio");
3581 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3582 still AUDIOBUF_STATE_INITIALIZED */
3583 /* Skip talk buffer and move pcm buffer to end to maximize available
3584 contiguous memory - no audio running means voice will not need the
3585 swap space */
3586 size_t talkbuf_size;
3587 buf += talkbuf_size = talkbuf_init(buf);
3588 filebuflen -= talkbuf_size;
3589 filebuflen -= voicebuf_init(buf + filebuflen);
3591 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
3594 *buffer_size = filebuflen;
3595 return buf;
3598 #ifdef HAVE_RECORDING
3599 /* Stop audio, voice and obtain all available buffer space */
3600 unsigned char * audio_get_recording_buffer(size_t *buffer_size)
3602 audio_hard_stop();
3603 return audio_get_buffer(true, buffer_size);
3605 #endif /* HAVE_RECORDING */
3607 /* Restore audio buffer to a particular state (one more valid than the current
3608 state) */
3609 bool audio_restore_playback(int type)
3611 switch (type)
3613 case AUDIO_WANT_PLAYBACK:
3614 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
3615 audio_reset_buffer();
3616 return true;
3617 case AUDIO_WANT_VOICE:
3618 if (buffer_state == AUDIOBUF_STATE_TRASHED)
3619 audio_reset_buffer();
3620 return true;
3621 default:
3622 return false;
3626 /* Has the playback buffer been completely claimed? */
3627 bool audio_buffer_state_trashed(void)
3629 return buffer_state == AUDIOBUF_STATE_TRASHED;
3633 /** --- Miscellaneous public interfaces --- **/
3635 #ifdef HAVE_ALBUMART
3636 /* Return which album art handle is current for the user in the given slot */
3637 int playback_current_aa_hid(int slot)
3639 if ((unsigned)slot < MAX_MULTIPLE_AA)
3641 struct track_info *info = track_list_user_current(skip_offset);
3643 if (!info && abs(skip_offset) <= 1)
3645 /* Give the actual position a go */
3646 info = track_list_user_current(0);
3649 if (info)
3650 return info->aa_hid[slot];
3653 return ERR_HANDLE_NOT_FOUND;
3656 /* Find an album art slot that doesn't match the dimensions of another that
3657 is already claimed - increment the use count if it is */
3658 int playback_claim_aa_slot(struct dim *dim)
3660 int i;
3662 /* First try to find a slot already having the size to reuse it since we
3663 don't want albumart of the same size buffered multiple times */
3664 FOREACH_ALBUMART(i)
3666 struct albumart_slot *slot = &albumart_slots[i];
3668 if (slot->dim.width == dim->width &&
3669 slot->dim.height == dim->height)
3671 slot->used++;
3672 return i;
3676 /* Size is new, find a free slot */
3677 FOREACH_ALBUMART(i)
3679 if (!albumart_slots[i].used)
3681 albumart_slots[i].used++;
3682 albumart_slots[i].dim = *dim;
3683 return i;
3687 /* Sorry, no free slot */
3688 return -1;
3691 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3692 void playback_release_aa_slot(int slot)
3694 if ((unsigned)slot < MAX_MULTIPLE_AA)
3696 struct albumart_slot *aa_slot = &albumart_slots[slot];
3698 if (aa_slot->used > 0)
3699 aa_slot->used--;
3702 #endif /* HAVE_ALBUMART */
3705 #ifdef HAVE_RECORDING
3706 /* Load an encoder and run it */
3707 bool audio_load_encoder(int afmt)
3709 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3710 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt);
3711 return audio_queue_send(Q_AUDIO_LOAD_ENCODER, afmt) != 0;
3712 #else
3713 (void)afmt;
3714 return true;
3715 #endif
3718 /* Stop an encoder and unload it */
3719 void audio_remove_encoder(void)
3721 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3722 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3723 audio_queue_send(Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN);
3724 #endif
3726 #endif /* HAVE_RECORDING */
3728 /* Is an automatic skip in progress? If called outside transition callbacks,
3729 indicates the last skip type at the time it was processed and isn't very
3730 meaningful. */
3731 bool audio_automatic_skip(void)
3733 return automatic_skip;
3736 /* Would normally calculate byte offset from an elapsed time but is not
3737 used on SWCODEC */
3738 int audio_get_file_pos(void)
3740 return 0;
3743 /* Return the elapsed time of the track previous to the current */
3744 unsigned long audio_prev_elapsed(void)
3746 return prev_track_elapsed;
3749 /* Is the audio thread ready to accept commands? */
3750 bool audio_is_thread_ready(void)
3752 return filling != STATE_BOOT;
3755 /* Return total file buffer length after accounting for the talk buf */
3756 size_t audio_get_filebuflen(void)
3758 return buf_length();
3761 /* How many tracks exist on the buffer - full or partial */
3762 int audio_track_count(void)
3763 __attribute__((alias("track_list_count")));
3765 /* Return total ringbuffer space occupied - ridx to widx */
3766 long audio_filebufused(void)
3768 return buf_used();
3772 /** -- Settings -- **/
3774 /* Enable or disable cuesheet support and allocate/don't allocate the
3775 extra associated resources */
3776 void audio_set_cuesheet(int enable)
3778 if (play_status == PLAY_STOPPED || !enable != !get_current_cuesheet())
3780 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3781 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
3785 #ifdef HAVE_DISK_STORAGE
3786 /* Set the audio antiskip buffer margin by index */
3787 void audio_set_buffer_margin(int setting)
3789 static const unsigned short lookup[] =
3790 { 5, 15, 30, 60, 120, 180, 300, 600 };
3792 if ((unsigned)setting >= ARRAYLEN(lookup))
3793 setting = 0;
3795 logf("buffer margin: %u", (unsigned)lookup[setting]);
3797 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3798 (unsigned)lookup[setting]);
3799 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK, lookup[setting]);
3801 #endif /* HAVE_DISK_STORAGE */
3803 #ifdef HAVE_CROSSFADE
3804 /* Take necessary steps to enable or disable the crossfade setting */
3805 void audio_set_crossfade(int enable)
3807 /* Tell it the next setting to use */
3808 pcmbuf_request_crossfade_enable(enable);
3810 /* Return if size hasn't changed or this is too early to determine
3811 which in the second case there's no way we could be playing
3812 anything at all */
3813 if (!pcmbuf_is_same_size())
3815 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3816 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
3819 #endif /* HAVE_CROSSFADE */
3822 /** -- Startup -- **/
3824 /* Initialize the audio system - called from init() in main.c */
3825 void audio_init(void)
3827 /* Can never do this twice */
3828 if (audio_is_initialized)
3830 logf("audio: already initialized");
3831 return;
3834 logf("audio: initializing");
3836 /* Initialize queues before giving control elsewhere in case it likes
3837 to send messages. Thread creation will be delayed however so nothing
3838 starts running until ready if something yields such as talk_init. */
3839 queue_init(&audio_queue, true);
3841 mutex_init(&id3_mutex);
3843 pcm_init();
3845 codec_init_codec_api();
3847 make_codec_thread();
3849 /* This thread does buffer, so match its priority */
3850 audio_thread_id = create_thread(audio_thread, audio_stack,
3851 sizeof(audio_stack), CREATE_THREAD_FROZEN,
3852 audio_thread_name
3853 IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE))
3854 IF_COP(, CPU));
3856 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
3857 audio_thread_id);
3859 #ifdef PLAYBACK_VOICE
3860 voice_thread_init();
3861 #endif
3863 /* audio_reset_buffer must know the size of voice buffer so init
3864 talk first */
3865 talk_init();
3867 #ifdef HAVE_CROSSFADE
3868 /* Set crossfade setting for next buffer init which should be about... */
3869 pcmbuf_request_crossfade_enable(global_settings.crossfade);
3870 #endif
3872 /* Initialize the buffering system */
3873 track_list_init();
3874 buffering_init();
3875 /* ...now! Set up the buffers */
3876 audio_reset_buffer();
3878 /* Probably safe to say */
3879 audio_is_initialized = true;
3881 sound_settings_apply();
3882 #ifdef HAVE_DISK_STORAGE
3883 audio_set_buffer_margin(global_settings.buffer_margin);
3884 #endif
3886 /* It's safe to let the threads run now */
3887 #ifdef PLAYBACK_VOICE
3888 voice_thread_resume();
3889 #endif
3890 codec_thread_resume();
3891 thread_thaw(audio_thread_id);