Manual: Small English improvement
[maemo-rb.git] / apps / playback.c
blobdbe28dd1c4047dfe43bc1bd2e72974777ec01458
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"
43 #include "settings.h"
45 #ifdef HAVE_TAGCACHE
46 #include "tagcache.h"
47 #endif
49 #ifdef AUDIO_HAVE_RECORDING
50 #include "pcm_record.h"
51 #endif
53 #ifdef HAVE_LCD_BITMAP
54 #ifdef HAVE_ALBUMART
55 #include "albumart.h"
56 #endif
57 #endif
59 /* TODO: The audio thread really is doing multitasking of acting like a
60 consumer and producer of tracks. It may be advantageous to better
61 logically separate the two functions. I won't go that far just yet. */
63 /* Internal support for voice playback */
64 #define PLAYBACK_VOICE
66 #if CONFIG_PLATFORM & PLATFORM_NATIVE
67 /* Application builds don't support direct code loading */
68 #define HAVE_CODEC_BUFFERING
69 #endif
71 /* Amount of guess-space to allow for codecs that must hunt and peck
72 * for their correct seek target, 32k seems a good size */
73 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
75 /* Define LOGF_ENABLE to enable logf output in this file */
76 /* #define LOGF_ENABLE */
77 #include "logf.h"
79 /* Macros to enable logf for queues
80 logging on SYS_TIMEOUT can be disabled */
81 #ifdef SIMULATOR
82 /* Define this for logf output of all queuing except SYS_TIMEOUT */
83 #define PLAYBACK_LOGQUEUES
84 /* Define this to logf SYS_TIMEOUT messages */
85 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
86 #endif
88 #ifdef PLAYBACK_LOGQUEUES
89 #define LOGFQUEUE logf
90 #else
91 #define LOGFQUEUE(...)
92 #endif
94 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
95 #define LOGFQUEUE_SYS_TIMEOUT logf
96 #else
97 #define LOGFQUEUE_SYS_TIMEOUT(...)
98 #endif
100 /* Variables are commented with the threads that use them:
101 * A=audio, C=codec, O=other. A suffix of "-" indicates that the variable is
102 * read but not updated on that thread. Audio is the only user unless otherwise
103 * specified.
106 /** Miscellaneous **/
107 bool audio_is_initialized = false; /* (A,O-) */
108 extern struct codec_api ci; /* (A,C) */
110 /** Possible arrangements of the main buffer **/
111 static enum audio_buffer_state
113 AUDIOBUF_STATE_TRASHED = -1, /* trashed; must be reset */
114 AUDIOBUF_STATE_INITIALIZED = 0, /* voice+audio OR audio-only */
115 AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
116 } buffer_state = AUDIOBUF_STATE_TRASHED; /* (A,O) */
118 /** Main state control **/
119 static bool ff_rw_mode SHAREDBSS_ATTR = false; /* Pre-ff-rewind mode (A,O-) */
121 enum play_status
123 PLAY_STOPPED = 0,
124 PLAY_PLAYING = AUDIO_STATUS_PLAY,
125 PLAY_PAUSED = AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE,
126 } play_status = PLAY_STOPPED;
128 /* Sizeable things that only need exist during playback and not when stopped */
129 static struct audio_scratch_memory
131 struct mp3entry codec_id3; /* (A,C) */
132 struct mp3entry unbuffered_id3;
133 struct cuesheet *curr_cue; /* Will follow this structure */
134 } * audio_scratch_memory = NULL;
136 /* These are used to store the current, next and optionally the peek-ahead
137 * mp3entry's - this guarantees that the pointer returned by audio_current/
138 * next_track will be valid for the full duration of the currently playing
139 * track */
140 enum audio_id3_types
142 /* These are allocated statically */
143 PLAYING_ID3 = 0,
144 NEXTTRACK_ID3,
145 #ifdef AUDIO_FAST_SKIP_PREVIEW
146 /* The real playing metadata must has to be protected since it contains
147 critical info for other features */
148 PLAYING_PEEK_ID3,
149 #endif
150 ID3_TYPE_NUM_STATIC,
151 /* These go in the scratch memory */
152 UNBUFFERED_ID3 = ID3_TYPE_NUM_STATIC,
153 CODEC_ID3,
155 static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */
157 /* Peeking functions can yield and mess us up */
158 static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,O)*/
161 /** For Scrobbler support **/
163 /* Previous track elapsed time */
164 static unsigned long prev_track_elapsed = 0; /* (A,O-) */
167 /** For album art support **/
168 #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
169 #ifdef HAVE_ALBUMART
171 static struct albumart_slot
173 struct dim dim; /* Holds width, height of the albumart */
174 int used; /* Counter; increments if something uses it */
175 } albumart_slots[MAX_MULTIPLE_AA]; /* (A,O) */
177 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
178 #endif /* HAVE_ALBUMART */
181 /** Information used for tracking buffer fills **/
183 /* Buffer and thread state tracking */
184 static enum filling_state
186 STATE_IDLE = 0, /* 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_IDLE;
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? */
333 static unsigned int position_key = 0;
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);
356 void audio_pcmbuf_sync_position(void);
359 /**************************************/
361 /** --- audio_queue helpers --- **/
362 static void audio_queue_post(long id, intptr_t data)
364 queue_post(&audio_queue, id, data);
367 static intptr_t audio_queue_send(long id, intptr_t data)
369 return queue_send(&audio_queue, id, data);
373 /** --- MP3Entry --- **/
375 /* Does the mp3entry have enough info for us to use it? */
376 static struct mp3entry * valid_mp3entry(const struct mp3entry *id3)
378 return id3 && (id3->length != 0 || id3->filesize != 0) &&
379 id3->codectype != AFMT_UNKNOWN ? (struct mp3entry *)id3 : NULL;
382 /* Return a pointer to an mp3entry on the buffer, as it is */
383 static struct mp3entry * bufgetid3(int handle_id)
385 if (handle_id < 0)
386 return NULL;
388 struct mp3entry *id3;
389 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
391 if (ret != sizeof(struct mp3entry))
392 return NULL;
394 return id3;
397 /* Read an mp3entry from the buffer, adjusted */
398 static bool bufreadid3(int handle_id, struct mp3entry *id3out)
400 struct mp3entry *id3 = bufgetid3(handle_id);
402 if (id3)
404 copy_mp3entry(id3out, id3);
405 return true;
408 return false;
411 /* Lock the id3 mutex */
412 static void id3_mutex_lock(void)
414 mutex_lock(&id3_mutex);
417 /* Unlock the id3 mutex */
418 static void id3_mutex_unlock(void)
420 mutex_unlock(&id3_mutex);
423 /* Return one of the collection of mp3entry pointers - collect them all here */
424 static inline struct mp3entry * id3_get(enum audio_id3_types id3_num)
426 switch (id3_num)
428 case UNBUFFERED_ID3:
429 return &audio_scratch_memory->unbuffered_id3;
430 case CODEC_ID3:
431 return &audio_scratch_memory->codec_id3;
432 default:
433 return &static_id3_entries[id3_num];
437 /* Copy an mp3entry into one of the mp3 entries */
438 static void id3_write(enum audio_id3_types id3_num,
439 const struct mp3entry *id3_src)
441 struct mp3entry *dest_id3 = id3_get(id3_num);
443 if (id3_src)
444 copy_mp3entry(dest_id3, id3_src);
445 else
446 wipe_mp3entry(dest_id3);
449 /* Call id3_write "safely" because peek aheads can yield, even if the fast
450 preview isn't enabled */
451 static void id3_write_locked(enum audio_id3_types id3_num,
452 const struct mp3entry *id3_src)
454 id3_mutex_lock();
455 id3_write(id3_num, id3_src);
456 id3_mutex_unlock();
460 /** --- Track info --- **/
462 /* Close a handle and mark it invalid */
463 static void track_info_close_handle(int *hid_p)
465 int hid = *hid_p;
467 /* bufclose returns true if the handle is not found, or if it is closed
468 * successfully, so these checks are safe on non-existant handles */
469 if (hid >= 0)
470 bufclose(hid);
472 /* Always reset to "no handle" in case it was something else */
473 *hid_p = ERR_HANDLE_NOT_FOUND;
476 /* Close all handles in a struct track_info and clear it */
477 static void track_info_close(struct track_info *info)
479 /* Close them in the order they are allocated on the buffer to speed up
480 the handle searching */
481 track_info_close_handle(&info->id3_hid);
482 track_info_close_handle(&info->cuesheet_hid);
483 #ifdef HAVE_ALBUMART
484 int i;
485 FOREACH_ALBUMART(i)
486 track_info_close_handle(&info->aa_hid[i]);
487 #endif
488 #ifdef HAVE_CODEC_BUFFERING
489 track_info_close_handle(&info->codec_hid);
490 #endif
491 track_info_close_handle(&info->audio_hid);
492 info->filesize = 0;
495 /* Invalidate all members to initial values - does not close handles */
496 static void track_info_wipe(struct track_info * info)
498 info->id3_hid = ERR_HANDLE_NOT_FOUND;
499 info->cuesheet_hid = ERR_HANDLE_NOT_FOUND;
500 #ifdef HAVE_ALBUMART
501 int i;
502 FOREACH_ALBUMART(i)
503 info->aa_hid[i] = ERR_HANDLE_NOT_FOUND;
504 #endif
505 #ifdef HAVE_CODEC_BUFFERING
506 info->codec_hid = ERR_HANDLE_NOT_FOUND;
507 #endif
508 info->audio_hid = ERR_HANDLE_NOT_FOUND;
509 info->filesize = 0;
513 /** --- Track list --- **/
515 /* Initialize the track list */
516 static void track_list_init(void)
518 int i;
519 for (i = 0; i < TRACK_LIST_LEN; i++)
520 track_info_wipe(&track_list.tracks[i]);
522 track_list.start = track_list.end = track_list.current;
525 /* Return number of items allocated in the list */
526 static unsigned int track_list_count(void)
528 return track_list.end - track_list.start;
531 /* Return true if the list is empty */
532 static inline bool track_list_empty(void)
534 return track_list.end == track_list.start;
537 /* Returns true if the list is holding the maximum number of items */
538 static bool track_list_full(void)
540 return track_list.end - track_list.start >= TRACK_LIST_LEN;
543 /* Test if the index is within the allocated range */
544 static bool track_list_in_range(int pos)
546 return (int)(pos - track_list.start) >= 0 &&
547 (int)(pos - track_list.end) < 0;
550 static struct track_info * track_list_entry(int pos)
552 return &track_list.tracks[pos & TRACK_LIST_MASK];
555 /* Return the info of the last allocation plus an offset, NULL if result is
556 out of bounds */
557 static struct track_info * track_list_last(int offset)
559 /* Last is before the end since the end isn't inclusive */
560 unsigned int pos = track_list.end + offset - 1;
562 if (!track_list_in_range(pos))
563 return NULL;
565 return track_list_entry(pos);
568 /* Allocate space at the end for another track if not full */
569 static struct track_info * track_list_alloc_track(void)
571 if (track_list_full())
572 return NULL;
574 return track_list_entry(track_list.end++);
577 /* Remove the last track entry allocated in order to support backing out
578 of a track load */
579 static void track_list_unalloc_track(void)
581 if (track_list_empty())
582 return;
584 track_list.end--;
586 if (track_list.current == track_list.end &&
587 track_list.current != track_list.start)
589 /* Current _must_ remain within bounds */
590 track_list.current--;
594 /* Return current track plus an offset, NULL if result is out of bounds */
595 static struct track_info * track_list_current(int offset)
597 unsigned int pos = track_list.current + offset;
599 if (!track_list_in_range(pos))
600 return NULL;
602 return track_list_entry(pos);
605 /* Return current based upon what's intended that the user sees - not
606 necessarily where decoding is taking place */
607 static struct track_info * track_list_user_current(int offset)
609 if (skip_pending == TRACK_SKIP_AUTO ||
610 skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)
612 offset--;
615 return track_list_current(offset);
618 /* Advance current track by an offset, return false if result is out of
619 bounds */
620 static struct track_info * track_list_advance_current(int offset)
622 unsigned int pos = track_list.current + offset;
624 if (!track_list_in_range(pos))
625 return NULL;
627 track_list.current = pos;
628 return track_list_entry(pos);
631 /* Clear tracks in the list, optionally preserving the current track -
632 returns 'false' if the operation was changed */
633 enum track_clear_action
635 TRACK_LIST_CLEAR_ALL = 0, /* Clear all tracks */
636 TRACK_LIST_KEEP_CURRENT, /* Keep current only; clear before + after */
637 TRACK_LIST_KEEP_NEW /* Keep current and those that follow */
640 static void track_list_clear(enum track_clear_action action)
642 logf("%s(%d)", __func__, (int)action);
644 /* Don't care now since rebuffering is imminent */
645 buf_set_watermark(0);
647 if (action != TRACK_LIST_CLEAR_ALL)
649 struct track_info *cur = track_list_current(0);
651 if (!cur || cur->id3_hid < 0)
652 action = TRACK_LIST_CLEAR_ALL; /* Nothing worthwhile keeping */
655 /* Noone should see this progressing */
656 int start = track_list.start;
657 int current = track_list.current;
658 int end = track_list.end;
660 track_list.start = current;
662 switch (action)
664 case TRACK_LIST_CLEAR_ALL:
665 /* Result: .start = .current, .end = .current */
666 track_list.end = current;
667 break;
669 case TRACK_LIST_KEEP_CURRENT:
670 /* Result: .start = .current, .end = .current + 1 */
671 track_list.end = current + 1;
672 break;
674 case TRACK_LIST_KEEP_NEW:
675 /* Result: .start = .current, .end = .end */
676 end = current;
677 break;
680 /* Close all open handles in the range except the for the current track
681 if preserving that */
682 while (start != end)
684 if (action != TRACK_LIST_KEEP_CURRENT || start != current)
686 struct track_info *info =
687 &track_list.tracks[start & TRACK_LIST_MASK];
689 /* If this is the in-progress load, abort it */
690 if (in_progress_id3_hid >= 0 &&
691 info->id3_hid == in_progress_id3_hid)
693 in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
696 track_info_close(info);
699 start++;
704 /** --- Audio buffer -- **/
706 /* What size is needed for the scratch buffer? */
707 static size_t scratch_mem_size(void)
709 size_t size = sizeof (struct audio_scratch_memory);
711 if (global_settings.cuesheet)
712 size += sizeof (struct cuesheet);
714 return size;
717 /* Initialize the memory area where data is stored that is only used when
718 playing audio and anything depending upon it */
719 static void scratch_mem_init(void *mem)
721 audio_scratch_memory = (struct audio_scratch_memory *)mem;
722 id3_write_locked(UNBUFFERED_ID3, NULL);
723 id3_write(CODEC_ID3, NULL);
724 ci.id3 = id3_get(CODEC_ID3);
725 audio_scratch_memory->curr_cue = NULL;
727 if (global_settings.cuesheet)
729 audio_scratch_memory->curr_cue =
730 SKIPBYTES((struct cuesheet *)audio_scratch_memory,
731 sizeof (struct audio_scratch_memory));
735 static int audiobuf_handle;
736 static size_t filebuflen;
738 size_t audio_buffer_available(void)
740 if (audiobuf_handle > 0) /* if allocated return what we got */
741 return filebuflen;
742 return core_available();
745 /* Set up the audio buffer for playback
746 * filebuflen must be pre-initialized with the maximum size */
747 static void audio_reset_buffer_noalloc(void* filebuf)
750 * Layout audio buffer as follows:
751 * [[|TALK]|SCRATCH|BUFFERING|PCM|[VOICE|]]
754 /* see audio_get_recording_buffer if this is modified */
755 logf("%s()", __func__);
757 /* If the setup of anything allocated before the file buffer is
758 changed, do check the adjustments after the buffer_alloc call
759 as it will likely be affected and need sliding over */
761 /* Initially set up file buffer as all space available */
762 size_t allocsize;
764 /* Subtract whatever voice needs */
765 allocsize = talkbuf_init(filebuf);
766 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
767 if (allocsize > filebuflen)
768 goto bufpanic;
770 filebuf += allocsize;
771 filebuflen -= allocsize;
773 if (talk_voice_required())
775 /* Need a space for voice PCM output */
776 allocsize = voicebuf_init(filebuf + filebuflen);
778 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
779 if (allocsize > filebuflen)
780 goto bufpanic;
782 filebuflen -= allocsize;
785 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
786 allocsize = pcmbuf_init(filebuf + filebuflen);
788 /* Make sure filebuflen is a pointer sized multiple after adjustment */
789 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
790 if (allocsize > filebuflen)
791 goto bufpanic;
793 filebuflen -= allocsize;
795 /* Scratch memory */
796 allocsize = scratch_mem_size();
797 if (allocsize > filebuflen)
798 goto bufpanic;
800 scratch_mem_init(filebuf);
801 filebuf += allocsize;
802 filebuflen -= allocsize;
804 buffering_reset(filebuf, filebuflen);
806 /* Clear any references to the file buffer */
807 buffer_state = AUDIOBUF_STATE_INITIALIZED;
809 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
810 /* Make sure everything adds up - yes, some info is a bit redundant but
811 aids viewing and the summation of certain variables should add up to
812 the location of others. */
814 logf("fbuf: %08X", (unsigned)filebuf);
815 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
816 logf("sbuf: %08X", (unsigned)audio_scratch_memory);
817 logf("sbufe: %08X", (unsigned)(audio_scratch_memory + allocsize));
819 #endif
821 return;
823 bufpanic:
824 panicf("%s(): EOM (%zu > %zu)", __func__, allocsize, filebuflen);
828 /* Buffer must not move. */
829 static int shrink_callback(int handle, unsigned hints, void* start, size_t old_size)
831 long offset = audio_current_track()->offset;
832 int status = audio_status();
833 /* TODO: Do it without stopping playback, if possible */
834 /* don't call audio_hard_stop() as it frees this handle */
835 if (thread_self() == audio_thread_id)
836 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
837 * if we're in the audio thread */
838 audio_stop_playback();
839 queue_clear(&audio_queue);
841 else
842 audio_queue_send(Q_AUDIO_STOP, 1);
843 #ifdef PLAYBACK_VOICE
844 voice_stop();
845 #endif
846 /* we should be free to change the buffer now */
847 size_t wanted_size = (hints & BUFLIB_SHRINK_SIZE_MASK);
848 ssize_t size = (ssize_t)old_size - wanted_size;
849 /* set final buffer size before calling audio_reset_buffer_noalloc() */
850 filebuflen = size;
851 switch (hints & BUFLIB_SHRINK_POS_MASK)
853 case BUFLIB_SHRINK_POS_BACK:
854 core_shrink(handle, start, size);
855 audio_reset_buffer_noalloc(start);
856 break;
857 case BUFLIB_SHRINK_POS_FRONT:
858 core_shrink(handle, start + wanted_size, size);
859 audio_reset_buffer_noalloc(start + wanted_size);
860 break;
862 if ((status & AUDIO_STATUS_PLAY) == AUDIO_STATUS_PLAY)
864 if (thread_self() == audio_thread_id)
865 audio_start_playback(offset, 0); /* inline Q_AUDIO_PLAY */
866 else
867 audio_play(offset);
870 return BUFLIB_CB_OK;
873 static struct buflib_callbacks ops = {
874 .move_callback = NULL,
875 .shrink_callback = shrink_callback,
878 static void audio_reset_buffer(void)
880 if (audiobuf_handle > 0)
882 core_free(audiobuf_handle);
883 audiobuf_handle = 0;
885 audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops);
886 unsigned char *filebuf = core_get_data(audiobuf_handle);
888 audio_reset_buffer_noalloc(filebuf);
891 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
892 static void audio_update_filebuf_watermark(int seconds)
894 size_t bytes = 0;
896 #ifdef HAVE_DISK_STORAGE
897 int spinup = ata_spinup_time();
899 if (seconds == 0)
901 /* By current setting */
902 seconds = buffer_margin;
904 else
906 /* New setting */
907 buffer_margin = seconds;
909 if (buf_get_watermark() == 0)
911 /* Write a watermark only if the audio thread already did so for
912 itself or it will fail to set the event and the watermark - if
913 it hasn't yet, it will use the new setting when it does */
914 return;
918 if (spinup)
919 seconds += (spinup / HZ) + 1;
920 else
921 seconds += 5;
923 seconds += buffer_margin;
924 #else
925 /* flash storage */
926 seconds = 1;
927 #endif
929 /* Watermark is a function of the bitrate of the last track in the buffer */
930 struct mp3entry *id3 = NULL;
931 struct track_info *info = track_list_last(0);
933 if (info)
934 id3 = valid_mp3entry(bufgetid3(info->id3_hid));
936 if (id3)
938 if (get_audio_base_data_type(id3->codectype) == TYPE_PACKET_AUDIO)
940 bytes = id3->bitrate * (1000/8) * seconds;
942 else
944 /* Bitrate has no meaning to buffering margin for atomic audio -
945 rebuffer when it's the only track left unless it's the only
946 track that fits, in which case we should avoid constant buffer
947 low events */
948 if (track_list_count() > 1)
949 bytes = info->filesize + 1;
952 else
954 /* Then set the minimum - this should not occur anyway */
955 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
956 track_list.start, track_list.current, track_list.end);
959 /* Actually setting zero disables the notification and we use that
960 to detect that it has been reset */
961 buf_set_watermark(MAX(bytes, 1));
962 logf("fwmark: %lu", (unsigned long)bytes);
966 /** -- Track change notification -- **/
968 /* Check the pcmbuf track changes and return write the message into the event
969 if there are any */
970 static inline bool audio_pcmbuf_track_change_scan(void)
972 if (track_change.out != track_change.in)
974 track_change.out++;
975 return true;
978 return false;
981 /* Clear outstanding track change posts */
982 static inline void audio_pcmbuf_track_change_clear(void)
984 track_change.out = track_change.in;
987 /* Post a track change notification - called by audio ISR */
988 static inline void audio_pcmbuf_track_change_post(void)
990 track_change.in++;
994 /** --- Helper functions --- **/
996 /* Removes messages that might end up in the queue before or while processing
997 a manual track change. Responding to them would be harmful since they
998 belong to a previous track's playback period. Anything that would generate
999 the stale messages must first be put into a state where it will not do so.
1001 static void audio_clear_track_notifications(void)
1003 static const long filter_list[][2] =
1005 /* codec messages */
1006 { Q_AUDIO_CODEC_SEEK_COMPLETE, Q_AUDIO_CODEC_COMPLETE },
1007 /* track change messages */
1008 { Q_AUDIO_TRACK_CHANGED, Q_AUDIO_TRACK_CHANGED },
1011 const int filter_count = ARRAYLEN(filter_list) - 1;
1013 /* Remove any pcmbuf notifications */
1014 pcmbuf_monitor_track_change(false);
1015 audio_pcmbuf_track_change_clear();
1017 /* Scrub the audio queue of the old mold */
1018 while (queue_peek_ex(&audio_queue, NULL,
1019 filter_count | QPEEK_REMOVE_EVENTS,
1020 filter_list))
1022 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1026 /* Takes actions based upon track load status codes */
1027 static void audio_handle_track_load_status(int trackstat)
1029 switch (trackstat)
1031 case LOAD_TRACK_ERR_NO_MORE:
1032 if (track_list_count() > 0)
1033 break;
1035 case LOAD_TRACK_ERR_START_CODEC:
1036 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, CODEC_ERROR);
1037 break;
1039 default:
1040 break;
1044 /* Announce the end of playing the current track */
1045 static void audio_playlist_track_finish(void)
1047 struct mp3entry *ply_id3 = id3_get(PLAYING_ID3);
1048 struct mp3entry *id3 = valid_mp3entry(ply_id3);
1050 playlist_update_resume_info(filling == STATE_ENDED ? NULL : id3);
1052 if (id3)
1054 send_event(PLAYBACK_EVENT_TRACK_FINISH, id3);
1055 prev_track_elapsed = id3->elapsed;
1057 else
1059 prev_track_elapsed = 0;
1063 /* Announce the beginning of the new track */
1064 static void audio_playlist_track_change(void)
1066 struct mp3entry *id3 = valid_mp3entry(id3_get(PLAYING_ID3));
1068 if (id3)
1069 send_event(PLAYBACK_EVENT_TRACK_CHANGE, id3);
1071 position_key = pcmbuf_get_position_key();
1073 playlist_update_resume_info(id3);
1076 /* Change the data for the next track and send the event */
1077 static void audio_update_and_announce_next_track(const struct mp3entry *id3_next)
1079 id3_write_locked(NEXTTRACK_ID3, id3_next);
1080 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE,
1081 id3_get(NEXTTRACK_ID3));
1084 /* Bring the user current mp3entry up to date and set a new offset for the
1085 buffered metadata */
1086 static void playing_id3_sync(struct track_info *user_info, off_t offset)
1088 id3_mutex_lock();
1090 struct mp3entry *id3 = bufgetid3(user_info->id3_hid);
1091 struct mp3entry *playing_id3 = id3_get(PLAYING_ID3);
1093 pcm_play_lock();
1095 unsigned long e = playing_id3->elapsed;
1096 unsigned long o = playing_id3->offset;
1098 id3_write(PLAYING_ID3, id3);
1100 if (offset < 0)
1102 playing_id3->elapsed = e;
1103 playing_id3->offset = o;
1104 offset = 0;
1107 pcm_play_unlock();
1109 if (id3)
1110 id3->offset = offset;
1112 id3_mutex_unlock();
1115 /* Wipe-out track metadata - current is optional */
1116 static void wipe_track_metadata(bool current)
1118 id3_mutex_lock();
1120 if (current)
1121 id3_write(PLAYING_ID3, NULL);
1123 id3_write(NEXTTRACK_ID3, NULL);
1124 id3_write(UNBUFFERED_ID3, NULL);
1126 id3_mutex_unlock();
1129 /* Called when buffering is completed on the last track handle */
1130 static void filling_is_finished(void)
1132 logf("last track finished buffering");
1134 /* There's no more to load or watch for */
1135 buf_set_watermark(0);
1136 filling = STATE_FINISHED;
1139 /* Stop the codec decoding or waiting for its data to be ready - returns
1140 'false' if the codec ended up stopped */
1141 static bool halt_decoding_track(bool stop)
1143 /* If it was waiting for us to clear the buffer to make a rebuffer
1144 happen, it should cease otherwise codec_stop could deadlock waiting
1145 for the codec to go to its main loop - codec's request will now
1146 force-fail */
1147 bool retval = false;
1149 buf_signal_handle(ci.audio_hid, true);
1151 if (stop)
1152 codec_stop();
1153 else
1154 retval = codec_pause();
1156 audio_clear_track_notifications();
1158 /* We now know it's idle and not waiting for buffered data */
1159 buf_signal_handle(ci.audio_hid, false);
1161 codec_skip_pending = false;
1162 codec_seeking = false;
1164 return retval;
1167 /* Wait for any in-progress fade to complete */
1168 static void audio_wait_fade_complete(void)
1170 /* Just loop until it's done */
1171 while (pcmbuf_fading())
1172 sleep(0);
1175 /* End the ff/rw mode */
1176 static void audio_ff_rewind_end(void)
1178 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1179 section */
1180 if (ff_rw_mode)
1182 ff_rw_mode = false;
1184 if (codec_seeking)
1186 /* Clear the buffer */
1187 pcmbuf_play_stop();
1188 audio_pcmbuf_sync_position();
1191 if (play_status != PLAY_PAUSED)
1193 /* Seeking-while-playing, resume PCM playback */
1194 pcmbuf_pause(false);
1199 /* Complete the codec seek */
1200 static void audio_complete_codec_seek(void)
1202 /* If a seek completed while paused, 'paused' is true.
1203 * If seeking from seek mode, 'ff_rw_mode' is true. */
1204 if (codec_seeking)
1206 audio_ff_rewind_end();
1207 codec_seeking = false; /* set _after_ the call! */
1209 /* else it's waiting and we must repond */
1212 /* Get the current cuesheet pointer */
1213 static inline struct cuesheet * get_current_cuesheet(void)
1215 return audio_scratch_memory->curr_cue;
1218 /* Read the cuesheet from the buffer */
1219 static void buf_read_cuesheet(int handle_id)
1221 struct cuesheet *cue = get_current_cuesheet();
1223 if (!cue || handle_id < 0)
1224 return;
1226 bufread(handle_id, sizeof (struct cuesheet), cue);
1229 /* Backend to peek/current/next track metadata interface functions -
1230 fill in the mp3entry with as much information as we may obtain about
1231 the track at the specified offset from the user current track -
1232 returns false if no information exists with us */
1233 static bool audio_get_track_metadata(int offset, struct mp3entry *id3)
1235 if (play_status == PLAY_STOPPED)
1236 return false;
1238 if (id3->path[0] != '\0')
1239 return true; /* Already filled */
1241 struct track_info *info = track_list_user_current(offset);
1243 if (!info)
1245 struct mp3entry *ub_id3 = id3_get(UNBUFFERED_ID3);
1247 if (offset > 0 && track_list_user_current(offset - 1))
1249 /* Try the unbuffered id3 since we're moving forward */
1250 if (ub_id3->path[0] != '\0')
1252 copy_mp3entry(id3, ub_id3);
1253 return true;
1257 else if (bufreadid3(info->id3_hid, id3))
1259 id3->cuesheet = NULL;
1260 return true;
1263 /* We didn't find the ID3 metadata, so we fill it with the little info we
1264 have and return that */
1266 char path[MAX_PATH+1];
1267 if (playlist_peek(offset, path, sizeof (path)))
1269 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1270 /* Try to get it from the database */
1271 if (!tagcache_fill_tags(id3, path))
1272 #endif
1274 /* By now, filename is the only source of info */
1275 fill_metadata_from_path(id3, path);
1278 return true;
1281 wipe_mp3entry(id3);
1283 return false;
1286 /* Get a resume rewind adjusted offset from the ID3 */
1287 unsigned long resume_rewind_adjusted_offset(const struct mp3entry *id3)
1289 unsigned long offset = id3->offset;
1290 size_t resume_rewind = global_settings.resume_rewind *
1291 id3->bitrate * (1000/8);
1293 if (offset < resume_rewind)
1294 offset = 0;
1295 else
1296 offset -= resume_rewind;
1298 return offset;
1301 /* Get the codec into ram and initialize it - keep it if it's ready */
1302 static bool audio_init_codec(struct track_info *track_info,
1303 struct mp3entry *track_id3)
1305 int codt_loaded = get_audio_base_codec_type(codec_loaded());
1306 int hid = ERR_HANDLE_NOT_FOUND;
1308 if (codt_loaded != AFMT_UNKNOWN)
1310 int codt = get_audio_base_codec_type(track_id3->codectype);
1312 if (codt == codt_loaded)
1314 /* Codec is the same base type */
1315 logf("Reusing prev. codec: %d", track_id3->codectype);
1316 #ifdef HAVE_CODEC_BUFFERING
1317 /* Close any buffered codec (we could have skipped directly to a
1318 format transistion that is the same format as the current track
1319 and the buffered one is no longer needed) */
1320 track_info_close_handle(&track_info->codec_hid);
1321 #endif
1322 return true;
1324 else
1326 /* New codec - first make sure the old one's gone */
1327 logf("Removing prev. codec: %d", codt_loaded);
1328 codec_unload();
1332 logf("New codec: %d/%d", track_id3->codectype, codec_loaded());
1334 #ifdef HAVE_CODEC_BUFFERING
1335 /* Codec thread will close the handle even if it fails and will load from
1336 storage if hid is not valid or the buffer load fails */
1337 hid = track_info->codec_hid;
1338 track_info->codec_hid = ERR_HANDLE_NOT_FOUND;
1339 #endif
1341 return codec_load(hid, track_id3->codectype);
1342 (void)track_info; /* When codec buffering isn't supported */
1345 /* Start the codec for the current track scheduled to be decoded */
1346 static bool audio_start_codec(bool auto_skip)
1348 struct track_info *info = track_list_current(0);
1349 struct mp3entry *cur_id3 = valid_mp3entry(bufgetid3(info->id3_hid));
1351 if (!cur_id3)
1352 return false;
1354 buf_pin_handle(info->id3_hid, true);
1356 if (!audio_init_codec(info, cur_id3))
1358 buf_pin_handle(info->id3_hid, false);
1359 return false;
1362 #ifdef HAVE_TAGCACHE
1363 bool autoresume_enable = global_settings.autoresume_enable;
1365 if (autoresume_enable && !cur_id3->offset)
1367 /* Resume all manually selected tracks */
1368 bool resume = !auto_skip;
1370 /* Send the "buffer" event to obtain the resume position for the codec */
1371 send_event(PLAYBACK_EVENT_TRACK_BUFFER, cur_id3);
1373 if (!resume)
1375 /* Automatic skip - do further tests to see if we should just
1376 ignore any autoresume position */
1377 int autoresume_automatic = global_settings.autoresume_automatic;
1379 switch (autoresume_automatic)
1381 case AUTORESUME_NEXTTRACK_ALWAYS:
1382 /* Just resume unconditionally */
1383 resume = true;
1384 break;
1385 case AUTORESUME_NEXTTRACK_NEVER:
1386 /* Force-rewind it */
1387 break;
1388 default:
1389 /* Not "never resume" - pass resume filter? */
1390 resume = autoresumable(cur_id3);
1394 if (!resume)
1395 cur_id3->offset = 0;
1397 logf("%s: Set offset for %s to %lX\n", __func__,
1398 cur_id3->title, cur_id3->offset);
1400 #endif /* HAVE_TAGCACHE */
1402 /* Rewind the required amount - if an autoresume was done, this also rewinds
1403 that by the setting's amount
1405 It would be best to have bookkeeping about whether or not the track
1406 sounded or not since skipping to it or else skipping to it while paused
1407 and back again will cause accumulation of silent rewinds - that's not
1408 our job to track directly nor could it be in any reasonable way
1410 cur_id3->offset = resume_rewind_adjusted_offset(cur_id3);
1412 /* Update the codec API with the metadata and track info */
1413 id3_write(CODEC_ID3, cur_id3);
1415 ci.audio_hid = info->audio_hid;
1416 ci.filesize = info->filesize;
1417 buf_set_base_handle(info->audio_hid);
1419 /* All required data is now available for the codec */
1420 codec_go();
1422 #ifdef HAVE_TAGCACHE
1423 if (!autoresume_enable || cur_id3->offset)
1424 #endif
1426 /* Send the "buffer" event now */
1427 send_event(PLAYBACK_EVENT_TRACK_BUFFER, cur_id3);
1430 buf_pin_handle(info->id3_hid, false);
1431 return true;
1433 (void)auto_skip; /* ifndef HAVE_TAGCACHE */
1437 /** --- Audio thread --- **/
1439 /* Load and parse a cuesheet for the file - returns false if the buffer
1440 is full */
1441 static bool audio_load_cuesheet(struct track_info *info,
1442 struct mp3entry *track_id3)
1444 struct cuesheet *cue = get_current_cuesheet();
1445 track_id3->cuesheet = NULL;
1447 if (cue && info->cuesheet_hid == ERR_HANDLE_NOT_FOUND)
1449 /* If error other than a full buffer, then mark it "unsupported" to
1450 avoid reloading attempt */
1451 int hid = ERR_UNSUPPORTED_TYPE;
1452 char cuepath[MAX_PATH];
1454 #ifdef HAVE_IO_PRIORITY
1455 buf_back_off_storage(true);
1456 #endif
1457 if (look_for_cuesheet_file(track_id3->path, cuepath))
1459 hid = bufalloc(NULL, sizeof (struct cuesheet), TYPE_CUESHEET);
1461 if (hid >= 0)
1463 void *cuesheet = NULL;
1464 bufgetdata(hid, sizeof (struct cuesheet), &cuesheet);
1466 if (parse_cuesheet(cuepath, (struct cuesheet *)cuesheet))
1468 /* Indicate cuesheet is present (while track remains
1469 buffered) */
1470 track_id3->cuesheet = cue;
1472 else
1474 bufclose(hid);
1475 hid = ERR_UNSUPPORTED_TYPE;
1480 #ifdef HAVE_IO_PRIORITY
1481 buf_back_off_storage(false);
1482 #endif
1483 if (hid == ERR_BUFFER_FULL)
1485 logf("buffer is full for now (%s)", __func__);
1486 return false;
1488 else
1490 if (hid < 0)
1491 logf("Cuesheet loading failed");
1493 info->cuesheet_hid = hid;
1497 return true;
1500 #ifdef HAVE_ALBUMART
1501 /* Load any album art for the file - returns false if the buffer is full */
1502 static bool audio_load_albumart(struct track_info *info,
1503 struct mp3entry *track_id3)
1505 int i;
1506 FOREACH_ALBUMART(i)
1508 struct bufopen_bitmap_data user_data;
1509 int *aa_hid = &info->aa_hid[i];
1510 int hid = ERR_UNSUPPORTED_TYPE;
1512 /* albumart_slots may change during a yield of bufopen,
1513 * but that's no problem */
1514 if (*aa_hid >= 0 || *aa_hid == ERR_UNSUPPORTED_TYPE ||
1515 !albumart_slots[i].used)
1516 continue;
1518 memset(&user_data, 0, sizeof(user_data));
1519 user_data.dim = &albumart_slots[i].dim;
1521 #ifdef HAVE_IO_PRIORITY
1522 buf_back_off_storage(true);
1523 #endif
1525 /* We can only decode jpeg for embedded AA */
1526 if (track_id3->embed_albumart && track_id3->albumart.type == AA_TYPE_JPG)
1528 user_data.embedded_albumart = &track_id3->albumart;
1529 hid = bufopen(track_id3->path, 0, TYPE_BITMAP, &user_data);
1532 if (hid < 0 && hid != ERR_BUFFER_FULL)
1534 /* No embedded AA or it couldn't be loaded - try other sources */
1535 char path[MAX_PATH];
1537 if (find_albumart(track_id3, path, sizeof(path),
1538 &albumart_slots[i].dim))
1540 user_data.embedded_albumart = NULL;
1541 hid = bufopen(path, 0, TYPE_BITMAP, &user_data);
1545 #ifdef HAVE_IO_PRIORITY
1546 buf_back_off_storage(false);
1547 #endif
1548 if (hid == ERR_BUFFER_FULL)
1550 logf("buffer is full for now (%s)", __func__);
1551 return false;
1553 else
1555 /* If error other than a full buffer, then mark it "unsupported"
1556 to avoid reloading attempt */
1557 if (hid < 0)
1559 logf("Album art loading failed");
1560 hid = ERR_UNSUPPORTED_TYPE;
1563 *aa_hid = hid;
1567 return true;
1569 #endif /* HAVE_ALBUMART */
1571 #ifdef HAVE_CODEC_BUFFERING
1572 /* Load a codec for the file onto the buffer - assumes we're working from the
1573 currently loading track - not called for the current track */
1574 static bool audio_buffer_codec(struct track_info *track_info,
1575 struct mp3entry *track_id3)
1577 /* This will not be the current track -> it cannot be the first and the
1578 current track cannot be ahead of buffering -> there is a previous
1579 track entry which is either current or ahead of the current */
1580 struct track_info *prev_info = track_list_last(-1);
1581 struct mp3entry *prev_id3 = bufgetid3(prev_info->id3_hid);
1583 /* If the previous codec is the same as this one, there is no need to
1584 put another copy of it on the file buffer (in other words, only
1585 buffer codecs at format transitions) */
1586 if (prev_id3)
1588 int codt = get_audio_base_codec_type(track_id3->codectype);
1589 int prev_codt = get_audio_base_codec_type(prev_id3->codectype);
1591 if (codt == prev_codt)
1593 logf("Reusing prev. codec: %d", prev_id3->codectype);
1594 return true;
1597 /* else just load it (harmless) */
1599 /* Load the codec onto the buffer if possible */
1600 const char *codec_fn = get_codec_filename(track_id3->codectype);
1601 if (!codec_fn)
1602 return false;
1604 char codec_path[MAX_PATH+1]; /* Full path to codec */
1605 codec_get_full_path(codec_path, codec_fn);
1607 track_info->codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1609 if (track_info->codec_hid >= 0)
1611 logf("Buffered codec: %d", afmt);
1612 return true;
1615 return false;
1617 #endif /* HAVE_CODEC_BUFFERING */
1619 /* Load metadata for the next track (with bufopen). The rest of the track
1620 loading will be handled by audio_finish_load_track once the metadata has
1621 been actually loaded by the buffering thread.
1623 Each track is arranged in the buffer as follows:
1624 <id3|[cuesheet|][album art|][codec|]audio>
1626 The next will not be loaded until the previous succeeds if the buffer was
1627 full at the time. To put any metadata after audio would make those handles
1628 unmovable.
1630 static int audio_load_track(void)
1632 if (in_progress_id3_hid >= 0)
1634 /* There must be an info pointer if the in-progress id3 is even there */
1635 struct track_info *info = track_list_last(0);
1637 if (info->id3_hid == in_progress_id3_hid)
1639 if (filling == STATE_FILLING)
1641 /* Haven't finished the metadata but the notification is
1642 anticipated to come soon */
1643 logf("%s(): in progress ok: %d". __func__, info->id3_hid);
1644 return LOAD_TRACK_OK;
1646 else if (filling == STATE_FULL)
1648 /* Buffer was full trying to complete the load after the
1649 metadata finished, so attempt to continue - older handles
1650 should have been cleared already */
1651 logf("%s(): finishing load: %d". __func__, info->id3_hid);
1652 filling = STATE_FILLING;
1653 buffer_event_finished_callback(&info->id3_hid);
1654 return LOAD_TRACK_OK;
1658 /* Some old, stray buffering message */
1659 logf("%s(): already in progress: %d". __func__, info->id3_hid);
1660 return LOAD_TRACK_ERR_BUSY;
1663 filling = STATE_FILLING;
1665 struct track_info *info = track_list_alloc_track();
1666 if (info == NULL)
1668 /* List is full so stop buffering tracks - however, attempt to obtain
1669 metadata as the unbuffered id3 */
1670 logf("No free tracks");
1671 filling = STATE_FULL;
1674 playlist_peek_offset++;
1676 logf("Buffering track: s%u/c%u/e%u/p%d",
1677 track_list.start, track_list.current, track_list.end,
1678 playlist_peek_offset);
1680 /* Get track name from current playlist read position */
1681 int fd = -1;
1682 char name_buf[MAX_PATH + 1];
1683 const char *trackname;
1685 while (1)
1688 trackname = playlist_peek(playlist_peek_offset, name_buf,
1689 sizeof (name_buf));
1691 if (!trackname)
1692 break;
1694 /* Test for broken playlists by probing for the files */
1695 fd = open(trackname, O_RDONLY);
1696 if (fd >= 0)
1697 break;
1699 logf("Open failed");
1700 /* Skip invalid entry from playlist */
1701 playlist_skip_entry(NULL, playlist_peek_offset);
1703 /* Sync the playlist if it isn't finished */
1704 if (playlist_peek(playlist_peek_offset, NULL, 0))
1705 playlist_next(0);
1708 if (!trackname)
1710 /* No track - exhausted the playlist entries */
1711 logf("End-of-playlist");
1712 id3_write_locked(UNBUFFERED_ID3, NULL);
1714 if (filling != STATE_FULL)
1715 track_list_unalloc_track(); /* Free this entry */
1717 playlist_peek_offset--; /* Maintain at last index */
1719 /* We can end up here after the real last track signals its completion
1720 and miss the transition to STATE_FINISHED esp. if dropping the last
1721 songs of a playlist late in their load (2nd stage) */
1722 info = track_list_last(0);
1724 if (info && buf_handle_remaining(info->audio_hid) == 0)
1725 filling_is_finished();
1726 else
1727 filling = STATE_END_OF_PLAYLIST;
1729 return LOAD_TRACK_ERR_NO_MORE;
1732 /* Successfully opened the file - get track metadata */
1733 if (filling == STATE_FULL ||
1734 (info->id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL)) < 0)
1736 /* Buffer or track list is full */
1737 struct mp3entry *ub_id3;
1739 playlist_peek_offset--;
1741 /* Load the metadata for the first unbuffered track */
1742 ub_id3 = id3_get(UNBUFFERED_ID3);
1743 id3_mutex_lock();
1744 get_metadata(ub_id3, fd, trackname);
1745 id3_mutex_unlock();
1747 if (filling != STATE_FULL)
1749 track_list_unalloc_track();
1750 filling = STATE_FULL;
1753 logf("%s: buffer is full for now (%u tracks)", __func__,
1754 track_list_count());
1756 else
1758 /* Successful load initiation */
1759 info->filesize = filesize(fd);
1760 in_progress_id3_hid = info->id3_hid; /* Remember what's in-progress */
1763 close(fd);
1764 return LOAD_TRACK_OK;
1767 /* Second part of the track loading: We now have the metadata available, so we
1768 can load the codec, the album art and finally the audio data.
1769 This is called on the audio thread after the buffering thread calls the
1770 buffering_handle_finished_callback callback. */
1771 static int audio_finish_load_track(struct track_info *info)
1773 int trackstat = LOAD_TRACK_OK;
1775 if (info->id3_hid != in_progress_id3_hid)
1777 /* We must not be here if not! */
1778 logf("%s: wrong track %d/%d", __func__, info->id3_hid,
1779 in_progress_id3_hid);
1780 return LOAD_TRACK_ERR_BUSY;
1783 /* The current track for decoding (there is always one if the list is
1784 populated) */
1785 struct track_info *cur_info = track_list_current(0);
1786 struct mp3entry *track_id3 = valid_mp3entry(bufgetid3(info->id3_hid));
1788 if (!track_id3)
1790 /* This is an error condition. Track cannot be played without valid
1791 metadata; skip the track. */
1792 logf("No metadata");
1793 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1794 goto audio_finish_load_track_exit;
1797 /* Try to load a cuesheet for the track */
1798 if (!audio_load_cuesheet(info, track_id3))
1800 /* No space for cuesheet on buffer, not an error */
1801 filling = STATE_FULL;
1802 goto audio_finish_load_track_exit;
1805 #ifdef HAVE_ALBUMART
1806 /* Try to load album art for the track */
1807 if (!audio_load_albumart(info, track_id3))
1809 /* No space for album art on buffer, not an error */
1810 filling = STATE_FULL;
1811 goto audio_finish_load_track_exit;
1813 #endif
1815 /* All handles available to external routines are ready - audio and codec
1816 information is private */
1818 if (info == track_list_user_current(0))
1820 /* Send only when the track handles could not all be opened ahead of
1821 time for the user's current track - otherwise everything is ready
1822 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1823 send_event(PLAYBACK_EVENT_CUR_TRACK_READY, id3_get(PLAYING_ID3));
1826 #ifdef HAVE_CODEC_BUFFERING
1827 /* Try to buffer a codec for the track */
1828 if (info != cur_info && !audio_buffer_codec(info, track_id3))
1830 if (info->codec_hid == ERR_BUFFER_FULL)
1832 /* No space for codec on buffer, not an error */
1833 filling = STATE_FULL;
1834 logf("buffer is full for now (%s)", __func__);
1836 else
1838 /* This is an error condition, either no codec was found, or
1839 reading the codec file failed part way through, either way,
1840 skip the track */
1841 logf("No codec for: %s", track_id3->path);
1842 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1845 goto audio_finish_load_track_exit;
1847 #endif /* HAVE_CODEC_BUFFERING */
1849 /** Finally, load the audio **/
1850 size_t file_offset = 0;
1851 track_id3->elapsed = 0;
1853 if (track_id3->offset >= info->filesize)
1854 track_id3->offset = 0;
1856 logf("%s: set offset for %s to %lu\n", __func__,
1857 id3->title, (unsigned long)offset);
1859 /* Adjust for resume rewind so we know what to buffer - starting the codec
1860 calls it again, so we don't save it (and they shouldn't accumulate) */
1861 size_t offset = resume_rewind_adjusted_offset(track_id3);
1863 enum data_type audiotype = get_audio_base_data_type(track_id3->codectype);
1865 if (audiotype == TYPE_ATOMIC_AUDIO)
1866 logf("Loading atomic %d", track_id3->codectype);
1868 if (format_buffers_with_offset(track_id3->codectype))
1870 /* This format can begin buffering from any point */
1871 file_offset = offset;
1874 logf("load track: %s", track_id3->path);
1876 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1878 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1879 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1881 else
1883 /* No offset given or it is very minimal - begin at the first frame
1884 according to the metadata */
1885 file_offset = track_id3->first_frame_offset;
1888 int hid = bufopen(track_id3->path, file_offset, audiotype, NULL);
1890 if (hid >= 0)
1892 info->audio_hid = hid;
1894 if (info == cur_info)
1896 /* This is the current track to decode - should be started now */
1897 trackstat = LOAD_TRACK_READY;
1900 else
1902 /* Buffer could be full but not properly so if this is the only
1903 track! */
1904 if (hid == ERR_BUFFER_FULL && audio_track_count() > 1)
1906 filling = STATE_FULL;
1907 logf("Buffer is full for now (%s)", __func__);
1909 else
1911 /* Nothing to play if no audio handle - skip this */
1912 logf("Could not add audio data handle");
1913 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1917 audio_finish_load_track_exit:
1918 if (trackstat < LOAD_TRACK_OK)
1920 playlist_skip_entry(NULL, playlist_peek_offset);
1921 track_info_close(info);
1922 track_list_unalloc_track();
1924 if (playlist_peek(playlist_peek_offset, NULL, 0))
1925 playlist_next(0);
1927 playlist_peek_offset--;
1930 if (filling != STATE_FULL)
1932 /* Load next track - error or not */
1933 in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
1934 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1935 audio_queue_post(Q_AUDIO_FILL_BUFFER, 0);
1937 else
1939 /* Full */
1940 trackstat = LOAD_TRACK_ERR_FINISH_FULL;
1943 return trackstat;
1946 /* Start a new track load */
1947 static int audio_fill_file_buffer(void)
1949 if (play_status == PLAY_STOPPED)
1950 return LOAD_TRACK_ERR_FAILED;
1952 trigger_cpu_boost();
1954 /* Must reset the buffer before use if trashed or voice only - voice
1955 file size shouldn't have changed so we can go straight from
1956 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1957 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1958 audio_reset_buffer();
1960 logf("Starting buffer fill");
1962 int trackstat = audio_load_track();
1964 if (trackstat >= LOAD_TRACK_OK)
1966 if (track_list_current(0) == track_list_user_current(0))
1967 playlist_next(0);
1969 if (filling == STATE_FULL && !track_list_user_current(1))
1971 /* There are no user tracks on the buffer after this therefore
1972 this is the next track */
1973 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3));
1977 return trackstat;
1980 /* Discard unwanted tracks and start refill from after the specified playlist
1981 offset */
1982 static int audio_reset_and_rebuffer(
1983 enum track_clear_action action, int peek_offset)
1985 logf("Forcing rebuffer: 0x%X, %d", flags, peek_offset);
1987 id3_write_locked(UNBUFFERED_ID3, NULL);
1989 /* Remove unwanted tracks - caller must have ensured codec isn't using
1990 any */
1991 track_list_clear(action);
1993 /* Refill at specified position (-1 starts at index offset 0) */
1994 playlist_peek_offset = peek_offset;
1996 /* Fill the buffer */
1997 return audio_fill_file_buffer();
2000 /* Handle buffering events
2001 (Q_AUDIO_BUFFERING) */
2002 static void audio_on_buffering(int event)
2004 enum track_clear_action action;
2005 int peek_offset;
2007 if (track_list_empty())
2008 return;
2010 switch (event)
2012 case BUFFER_EVENT_BUFFER_LOW:
2013 if (filling != STATE_FULL && filling != STATE_END_OF_PLAYLIST)
2014 return; /* Should be nothing left to fill */
2016 /* Clear old tracks and continue buffering where it left off */
2017 action = TRACK_LIST_KEEP_NEW;
2018 peek_offset = playlist_peek_offset;
2019 break;
2021 case BUFFER_EVENT_REBUFFER:
2022 /* Remove all but the currently decoding track and redo buffering
2023 after that */
2024 action = TRACK_LIST_KEEP_CURRENT;
2025 peek_offset = (skip_pending == TRACK_SKIP_AUTO) ? 1 : 0;
2026 break;
2028 default:
2029 return;
2032 switch (skip_pending)
2034 case TRACK_SKIP_NONE:
2035 case TRACK_SKIP_AUTO:
2036 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2037 audio_reset_and_rebuffer(action, peek_offset);
2038 break;
2040 case TRACK_SKIP_AUTO_END_PLAYLIST:
2041 /* Already finished */
2042 break;
2044 default:
2045 /* Invalid */
2046 logf("Buffering call, inv. state: %d", (int)skip_pending);
2050 /* Handle starting the next track load
2051 (Q_AUDIO_FILL_BUFFER) */
2052 static void audio_on_fill_buffer(void)
2054 audio_handle_track_load_status(audio_fill_file_buffer());
2057 /* Handle posted load track finish event
2058 (Q_AUDIO_FINISH_LOAD_TRACK) */
2059 static void audio_on_finish_load_track(int id3_hid)
2061 struct track_info *info = track_list_last(0);
2063 if (!info || !buf_is_handle(id3_hid))
2064 return;
2066 if (info == track_list_user_current(1))
2068 /* Just loaded the metadata right after the current position */
2069 audio_update_and_announce_next_track(bufgetid3(info->id3_hid));
2072 if (audio_finish_load_track(info) != LOAD_TRACK_READY)
2073 return; /* Not current track */
2075 bool is_user_current = info == track_list_user_current(0);
2077 if (is_user_current)
2079 /* Copy cuesheet */
2080 buf_read_cuesheet(info->cuesheet_hid);
2083 if (audio_start_codec(automatic_skip))
2085 if (is_user_current)
2087 /* Be sure all tagtree info is synchronized; it will be needed for the
2088 track finish event - the sync will happen when finalizing a track
2089 change otherwise */
2090 bool was_valid = valid_mp3entry(id3_get(PLAYING_ID3));
2092 playing_id3_sync(info, -1);
2094 if (!was_valid)
2096 /* Playing id3 hadn't been updated yet because no valid track
2097 was yet available - treat like the first track */
2098 audio_playlist_track_change();
2102 else
2104 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2108 /* Called when handles other than metadata handles have finished buffering
2109 (Q_AUDIO_HANDLE_FINISHED) */
2110 static void audio_on_handle_finished(int hid)
2112 /* Right now, only audio handles should end up calling this */
2113 if (filling == STATE_END_OF_PLAYLIST)
2115 struct track_info *info = track_list_last(0);
2117 /* Really we don't know which order the handles will actually complete
2118 to zero bytes remaining since another thread is doing it - be sure
2119 it's the right one */
2120 if (info && info->audio_hid == hid)
2122 /* This was the last track in the playlist and we now have all the
2123 data we need */
2124 filling_is_finished();
2129 /* Called to make an outstanding track skip the current track and to send the
2130 transition events */
2131 static void audio_finalise_track_change(void)
2133 switch (skip_pending)
2135 case TRACK_SKIP_NONE: /* Manual skip */
2136 break;
2138 case TRACK_SKIP_AUTO:
2139 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2141 int playlist_delta = skip_pending == TRACK_SKIP_AUTO ? 1 : 0;
2142 audio_playlist_track_finish();
2144 if (!playlist_peek(playlist_delta, NULL, 0))
2146 /* Track ended up rejected - push things ahead like the codec blew
2147 it (because it was never started and now we're here where it
2148 should have been decoding the next track by now) - next, a
2149 directory change or end of playback will most likely happen */
2150 skip_pending = TRACK_SKIP_NONE;
2151 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2152 return;
2155 if (!playlist_delta)
2156 break;
2158 playlist_peek_offset -= playlist_delta;
2159 if (playlist_next(playlist_delta) >= 0)
2160 break;
2161 /* What!? Disappear? Hopeless bleak despair */
2163 /* Fallthrough */
2164 case TRACK_SKIP_AUTO_END_PLAYLIST:
2165 default: /* Invalid */
2166 filling = STATE_ENDED;
2167 audio_stop_playback();
2168 return;
2171 struct track_info *info = track_list_current(0);
2172 struct mp3entry *track_id3 = NULL;
2174 id3_mutex_lock();
2176 /* Update the current cuesheet if any and enabled */
2177 if (info)
2179 buf_read_cuesheet(info->cuesheet_hid);
2180 track_id3 = bufgetid3(info->id3_hid);
2183 id3_write(PLAYING_ID3, track_id3);
2185 /* The skip is technically over */
2186 skip_pending = TRACK_SKIP_NONE;
2188 /* Sync the next track information */
2189 info = track_list_current(1);
2191 id3_write(NEXTTRACK_ID3, info ? bufgetid3(info->id3_hid) :
2192 id3_get(UNBUFFERED_ID3));
2194 id3_mutex_unlock();
2196 audio_playlist_track_change();
2199 /* Actually begin a transition and take care of the codec change - may complete
2200 it now or ask pcmbuf for notification depending on the type */
2201 static void audio_begin_track_change(enum pcm_track_change_type type,
2202 int trackstat)
2204 /* Even if the new track is bad, the old track must be finished off */
2205 pcmbuf_start_track_change(type);
2207 bool auto_skip = type != TRACK_CHANGE_MANUAL;
2209 if (!auto_skip)
2211 /* Manual track change happens now */
2212 audio_finalise_track_change();
2213 pcmbuf_sync_position_update();
2215 if (play_status == PLAY_STOPPED)
2216 return; /* Stopped us */
2219 if (trackstat >= LOAD_TRACK_OK)
2221 struct track_info *info = track_list_current(0);
2223 if (info->audio_hid < 0)
2224 return;
2226 /* Everything needed for the codec is ready - start it */
2227 if (audio_start_codec(auto_skip))
2229 if (!auto_skip)
2230 playing_id3_sync(info, -1);
2231 return;
2234 trackstat = LOAD_TRACK_ERR_START_CODEC;
2237 audio_handle_track_load_status(trackstat);
2240 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2241 static void audio_monitor_end_of_playlist(void)
2243 skip_pending = TRACK_SKIP_AUTO_END_PLAYLIST;
2244 filling = STATE_ENDING;
2245 pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA);
2248 /* Codec has completed decoding the track
2249 (usually Q_AUDIO_CODEC_COMPLETE) */
2250 static void audio_on_codec_complete(int status)
2252 logf("%s(%d)", __func__, status);
2254 if (play_status == PLAY_STOPPED)
2255 return;
2257 /* If it didn't notify us first, don't expect "seek complete" message
2258 since the codec can't post it now - do things like it would have
2259 done */
2260 audio_complete_codec_seek();
2262 if (play_status == PLAY_PAUSED || skip_pending != TRACK_SKIP_NONE)
2264 /* Old-hay on the ip-skay - codec has completed decoding
2266 Paused: We're not sounding it, so just remember that it happened
2267 and the resume will begin the transition
2269 Skipping: There was already a skip in progress, remember it and
2270 allow no further progress until the PCM from the previous
2271 song has finished
2273 codec_skip_pending = true;
2274 codec_skip_status = status;
2275 return;
2278 codec_skip_pending = false;
2280 int trackstat = LOAD_TRACK_OK;
2282 automatic_skip = true;
2283 skip_pending = TRACK_SKIP_AUTO;
2285 /* Does this track have an entry allocated? */
2286 struct track_info *info = track_list_advance_current(1);
2288 if (!info || info->audio_hid < 0)
2290 bool end_of_playlist = false;
2292 if (info)
2294 /* Track load is not complete - it might have stopped on a
2295 full buffer without reaching the audio handle or we just
2296 arrived at it early
2298 If this type is atomic and we couldn't get the audio,
2299 perhaps it would need to wrap to make the allocation and
2300 handles are in the way - to maximize the liklihood it can
2301 be allocated, clear all handles to reset the buffer and
2302 its indexes to 0 - for packet audio, this should not be an
2303 issue and a pointless full reload of all the track's
2304 metadata may be avoided */
2306 struct mp3entry *track_id3 = bufgetid3(info->id3_hid);
2308 if (track_id3 &&
2309 get_audio_base_data_type(track_id3->codectype)
2310 == TYPE_PACKET_AUDIO)
2312 /* Continue filling after this track */
2313 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT, 1);
2314 audio_begin_track_change(TRACK_CHANGE_AUTO, trackstat);
2315 return;
2317 /* else rebuffer at this track; status applies to the track we
2318 want */
2320 else if (!playlist_peek(1, NULL, 0))
2322 /* Play sequence is complete - directory change or other playlist
2323 resequencing - the playlist must now be advanced in order to
2324 continue since a peek ahead to the next track is not possible */
2325 skip_pending = TRACK_SKIP_AUTO_NEW_PLAYLIST;
2326 end_of_playlist = playlist_next(1) < 0;
2329 if (!end_of_playlist)
2331 trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL,
2332 skip_pending == TRACK_SKIP_AUTO ? 0 : -1);
2334 if (trackstat == LOAD_TRACK_ERR_NO_MORE)
2336 /* Failed to find anything after all - do playlist switchover
2337 instead */
2338 skip_pending = TRACK_SKIP_AUTO_NEW_PLAYLIST;
2339 end_of_playlist = playlist_next(1) < 0;
2343 if (end_of_playlist)
2345 audio_monitor_end_of_playlist();
2346 return;
2350 audio_begin_track_change(TRACK_CHANGE_AUTO, trackstat);
2353 /* Called when codec completes seek operation
2354 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2355 static void audio_on_codec_seek_complete(void)
2357 logf("%s()", __func__);
2358 audio_complete_codec_seek();
2359 codec_go();
2362 /* Called when PCM track change has completed
2363 (Q_AUDIO_TRACK_CHANGED) */
2364 static void audio_on_track_changed(void)
2366 /* Finish whatever is pending so that the WPS is in sync */
2367 audio_finalise_track_change();
2369 if (codec_skip_pending)
2371 /* Codec got ahead completing a short track - complete the
2372 codec's skip and begin the next */
2373 codec_skip_pending = false;
2374 audio_on_codec_complete(codec_skip_status);
2378 /* Begin playback from an idle state, transition to a new playlist or
2379 invalidate the buffer and resume (if playing).
2380 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2381 static void audio_start_playback(size_t offset, unsigned int flags)
2383 enum play_status old_status = play_status;
2385 if (flags & AUDIO_START_NEWBUF)
2387 /* Mark the buffer dirty - if not playing, it will be reset next
2388 time */
2389 if (buffer_state == AUDIOBUF_STATE_INITIALIZED)
2390 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
2393 if (old_status != PLAY_STOPPED)
2395 logf("%s(%lu): skipping", __func__, (unsigned long)offset);
2397 halt_decoding_track(true);
2399 automatic_skip = false;
2400 ff_rw_mode = false;
2402 if (flags & AUDIO_START_RESTART)
2404 /* Clear out some stuff to resume the current track where it
2405 left off */
2406 pcmbuf_play_stop();
2407 offset = id3_get(PLAYING_ID3)->offset;
2408 track_list_clear(TRACK_LIST_CLEAR_ALL);
2410 else
2412 /* This is more-or-less treated as manual track transition */
2413 /* Save resume information for current track */
2414 audio_playlist_track_finish();
2415 track_list_clear(TRACK_LIST_CLEAR_ALL);
2417 /* Indicate manual track change */
2418 pcmbuf_start_track_change(TRACK_CHANGE_MANUAL);
2419 wipe_track_metadata(true);
2422 /* Set after track finish event in case skip was in progress */
2423 skip_pending = TRACK_SKIP_NONE;
2425 else
2427 if (flags & AUDIO_START_RESTART)
2428 return; /* Must already be playing */
2430 /* Cold playback start from a stopped state */
2431 logf("%s(%lu): starting", __func__, offset);
2433 /* Set audio parameters */
2434 #if INPUT_SRC_CAPS != 0
2435 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2436 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2437 #endif
2438 #ifndef PLATFORM_HAS_VOLUME_CHANGE
2439 sound_set_volume(global_settings.volume);
2440 #endif
2441 /* Be sure channel is audible */
2442 pcmbuf_fade(false, true);
2444 /* Update our state */
2445 play_status = PLAY_PLAYING;
2448 /* Codec's position should be available as soon as it knows it */
2449 position_key = pcmbuf_get_position_key();
2450 pcmbuf_sync_position_update();
2452 /* Start fill from beginning of playlist */
2453 playlist_peek_offset = -1;
2454 buf_set_base_handle(-1);
2456 /* Officially playing */
2457 queue_reply(&audio_queue, 1);
2459 /* Add these now - finish event for the first id3 will most likely be sent
2460 immediately */
2461 add_event(BUFFER_EVENT_REBUFFER, false, buffer_event_rebuffer_callback);
2462 add_event(BUFFER_EVENT_FINISHED, false, buffer_event_finished_callback);
2464 if (old_status == PLAY_STOPPED)
2466 /* Send coldstart event */
2467 send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL);
2470 /* Fill the buffer */
2471 int trackstat = audio_fill_file_buffer();
2473 if (trackstat >= LOAD_TRACK_OK)
2475 /* This is the currently playing track - get metadata, stat */
2476 playing_id3_sync(track_list_current(0), offset);
2478 if (valid_mp3entry(id3_get(PLAYING_ID3)))
2480 /* Only if actually changing tracks... */
2481 if (!(flags & AUDIO_START_RESTART))
2482 audio_playlist_track_change();
2485 else
2487 /* Found nothing playable */
2488 audio_handle_track_load_status(trackstat);
2492 /* Stop playback and enter an idle state
2493 (usually Q_AUDIO_STOP) */
2494 static void audio_stop_playback(void)
2496 logf("%s()", __func__);
2498 if (play_status == PLAY_STOPPED)
2499 return;
2501 bool do_fade = global_settings.fade_on_stop && filling != STATE_ENDED;
2503 pcmbuf_fade(do_fade, false);
2505 /* Wait for fade-out */
2506 audio_wait_fade_complete();
2508 /* Stop the codec and unload it */
2509 halt_decoding_track(true);
2510 pcmbuf_play_stop();
2511 codec_unload();
2513 /* Save resume information - "filling" might have been set to
2514 "STATE_ENDED" by caller in order to facilitate end of playlist */
2515 audio_playlist_track_finish();
2517 skip_pending = TRACK_SKIP_NONE;
2518 automatic_skip = false;
2520 /* Close all tracks and mark them NULL */
2521 remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
2522 remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
2523 remove_event(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback);
2525 track_list_clear(TRACK_LIST_CLEAR_ALL);
2527 /* Update our state */
2528 ff_rw_mode = false;
2529 play_status = PLAY_STOPPED;
2531 wipe_track_metadata(true);
2533 /* Go idle */
2534 filling = STATE_IDLE;
2535 cancel_cpu_boost();
2538 /* Pause the playback of the current track
2539 (Q_AUDIO_PAUSE) */
2540 static void audio_on_pause(bool pause)
2542 logf("%s(%s)", __func__, pause ? "true" : "false");
2544 if (play_status == PLAY_STOPPED || pause == (play_status == PLAY_PAUSED))
2545 return;
2547 play_status = pause ? PLAY_PAUSED : PLAY_PLAYING;
2549 if (!pause && codec_skip_pending)
2551 /* Actually do the skip that is due - resets the status flag */
2552 audio_on_codec_complete(codec_skip_status);
2555 bool do_fade = global_settings.fade_on_stop;
2557 pcmbuf_fade(do_fade, !pause);
2559 if (!ff_rw_mode && !(do_fade && pause))
2561 /* Not in ff/rw mode - can actually change the audio state now */
2562 pcmbuf_pause(pause);
2566 /* Skip a certain number of tracks forwards or backwards
2567 (Q_AUDIO_SKIP) */
2568 static void audio_on_skip(void)
2570 id3_mutex_lock();
2572 /* Eat the delta to keep it synced, even if not playing */
2573 int toskip = skip_offset;
2574 skip_offset = 0;
2576 logf("%s(): %d", __func__, toskip);
2578 id3_mutex_unlock();
2580 if (play_status == PLAY_STOPPED)
2581 return;
2583 /* Force codec to abort this track */
2584 halt_decoding_track(true);
2586 /* Kill the ff/rw halt */
2587 ff_rw_mode = false;
2589 /* Manual skip */
2590 automatic_skip = false;
2592 /* If there was an auto skip in progress, there will be residual
2593 advancement of the playlist and/or track list so compensation will be
2594 required in order to end up in the right spot */
2595 int track_list_delta = toskip;
2596 int playlist_delta = toskip;
2598 if (skip_pending != TRACK_SKIP_NONE)
2600 if (skip_pending != TRACK_SKIP_AUTO_END_PLAYLIST)
2601 track_list_delta--;
2603 if (skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)
2604 playlist_delta--;
2607 audio_playlist_track_finish();
2608 skip_pending = TRACK_SKIP_NONE;
2610 /* Update the playlist current track now */
2611 while (playlist_next(playlist_delta) < 0)
2613 /* Manual skip out of range (because the playlist wasn't updated
2614 yet by us and so the check in audio_skip returned 'ok') - bring
2615 back into range */
2616 int d = toskip < 0 ? 1 : -1;
2618 while (!playlist_check(playlist_delta))
2620 if (playlist_delta == d)
2622 /* Had to move the opposite direction to correct, which is
2623 wrong - this is the end */
2624 filling = STATE_ENDED;
2625 audio_stop_playback();
2626 return;
2629 playlist_delta += d;
2630 track_list_delta += d;
2634 /* Adjust things by how much the playlist was manually moved */
2635 playlist_peek_offset -= playlist_delta;
2637 struct track_info *info = track_list_advance_current(track_list_delta);
2638 int trackstat = LOAD_TRACK_OK;
2640 if (!info || info->audio_hid < 0)
2642 /* We don't know the next track thus we know we don't have it */
2643 trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1);
2646 audio_begin_track_change(TRACK_CHANGE_MANUAL, trackstat);
2649 /* Skip to the next/previous directory
2650 (Q_AUDIO_DIR_SKIP) */
2651 static void audio_on_dir_skip(int direction)
2653 logf("%s(%d)", __func__, direction);
2655 id3_mutex_lock();
2656 skip_offset = 0;
2657 id3_mutex_unlock();
2659 if (play_status == PLAY_STOPPED)
2660 return;
2662 /* Force codec to abort this track */
2663 halt_decoding_track(true);
2665 /* Kill the ff/rw halt */
2666 ff_rw_mode = false;
2668 /* Manual skip */
2669 automatic_skip = false;
2671 audio_playlist_track_finish();
2673 /* Unless automatic and gapless, skips do not pend */
2674 skip_pending = TRACK_SKIP_NONE;
2676 /* Regardless of the return value we need to rebuffer. If it fails the old
2677 playlist will resume, else the next dir will start playing. */
2678 playlist_next_dir(direction);
2680 wipe_track_metadata(false);
2682 int trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1);
2684 if (trackstat == LOAD_TRACK_ERR_NO_MORE)
2686 /* The day the music died - finish-off whatever is playing and call it
2687 quits */
2688 audio_monitor_end_of_playlist();
2689 return;
2692 audio_begin_track_change(TRACK_CHANGE_MANUAL, trackstat);
2695 /* Enter seek mode in order to start a seek
2696 (Q_AUDIO_PRE_FF_REWIND) */
2697 static void audio_on_pre_ff_rewind(void)
2699 logf("%s()", __func__);
2701 if (play_status == PLAY_STOPPED || ff_rw_mode)
2702 return;
2704 ff_rw_mode = true;
2706 audio_wait_fade_complete();
2708 if (play_status == PLAY_PAUSED)
2709 return;
2711 pcmbuf_pause(true);
2714 /* Seek the playback of the current track to the specified time
2715 (Q_AUDIO_FF_REWIND) */
2716 static void audio_on_ff_rewind(long time)
2718 logf("%s(%ld)", __func__, time);
2720 if (play_status == PLAY_STOPPED)
2721 return;
2723 enum track_skip_type pending = skip_pending;
2725 switch (pending)
2727 case TRACK_SKIP_NONE: /* The usual case */
2728 case TRACK_SKIP_AUTO: /* Have to back it out (fun!) */
2729 case TRACK_SKIP_AUTO_END_PLAYLIST: /* Still have the last codec used */
2731 struct mp3entry *id3 = id3_get(PLAYING_ID3);
2732 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
2734 automatic_skip = false;
2736 /* Send event before clobbering the time */
2737 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2738 then skipping back to this track resumes properly. Something else
2739 should be sent. We're not _really_ finishing the track are we? */
2740 if (time == 0)
2741 send_event(PLAYBACK_EVENT_TRACK_FINISH, id3);
2743 id3->elapsed = time;
2744 queue_reply(&audio_queue, 1);
2746 bool haltres = halt_decoding_track(pending == TRACK_SKIP_AUTO);
2748 /* Need this set in case ff/rw mode + error but _after_ the codec
2749 halt that will reset it */
2750 codec_seeking = true;
2752 /* If in transition, key will have changed - sync to it */
2753 position_key = pcmbuf_get_position_key();
2755 if (pending == TRACK_SKIP_AUTO)
2757 if (!track_list_advance_current(-1))
2759 /* Not in list - must rebuffer at the current playlist index */
2760 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1)
2761 < LOAD_TRACK_OK)
2763 /* Codec is stopped */
2764 break;
2769 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2770 rebuffer is needed */
2771 skip_pending = TRACK_SKIP_NONE;
2772 struct track_info *cur_info = track_list_current(0);
2774 /* Track must complete the loading _now_ since a codec and audio
2775 handle are needed in order to do the seek */
2776 if (cur_info->audio_hid < 0 &&
2777 audio_finish_load_track(cur_info) != LOAD_TRACK_READY)
2779 /* Call above should push any load sequence - no need for
2780 halt_decoding_track here if no skip was pending here because
2781 there would not be a codec started if no audio handle was yet
2782 opened */
2783 break;
2786 if (pending == TRACK_SKIP_AUTO)
2788 if (!bufreadid3(cur_info->id3_hid, ci_id3) ||
2789 !audio_init_codec(cur_info, ci_id3))
2791 /* We should have still been able to get it - skip it and move
2792 onto the next one - like it or not this track is broken */
2793 break;
2796 /* Set the codec API to the correct metadata and track info */
2797 ci.audio_hid = cur_info->audio_hid;
2798 ci.filesize = cur_info->filesize;
2799 buf_set_base_handle(cur_info->audio_hid);
2802 if (!haltres)
2804 /* If codec must be (re)started, reset the offset */
2805 ci_id3->offset = 0;
2808 codec_seek(time);
2809 return;
2812 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2814 /* We cannot do this because the playlist must be reversed by one
2815 and it doesn't always return the same song when going backwards
2816 across boundaries as forwards (either because of randomization
2817 or inconsistency in deciding what the previous track should be),
2818 therefore the whole operation would often end up as nonsense -
2819 lock out seeking for a couple seconds */
2821 /* Sure as heck cancel seek mode too! */
2822 audio_ff_rewind_end();
2823 return;
2826 default:
2827 /* Won't see this */
2828 return;
2831 if (play_status == PLAY_STOPPED)
2833 /* Playback ended because of an error completing a track load */
2834 return;
2837 /* Always fake it as a codec start error which will handle mode
2838 cancellations and skip to the next track */
2839 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2842 /* Invalidates all but currently playing track
2843 (Q_AUDIO_FLUSH) */
2844 static void audio_on_audio_flush(void)
2846 logf("%s", __func__);
2848 if (track_list_empty())
2849 return; /* Nothing to flush out */
2851 switch (skip_pending)
2853 case TRACK_SKIP_NONE:
2854 case TRACK_SKIP_AUTO_END_PLAYLIST:
2855 /* Remove all but the currently playing track from the list and
2856 refill after that */
2857 track_list_clear(TRACK_LIST_KEEP_CURRENT);
2858 playlist_peek_offset = 0;
2859 id3_write_locked(UNBUFFERED_ID3, NULL);
2860 audio_update_and_announce_next_track(NULL);
2862 /* Ignore return since it's about the next track, not this one */
2863 audio_fill_file_buffer();
2865 if (skip_pending == TRACK_SKIP_NONE)
2866 break;
2868 /* There's now a track after this one now - convert to auto skip -
2869 no skip should pend right now because multiple flush messages can
2870 be fired which would cause a restart in the below cases */
2871 skip_pending = TRACK_SKIP_NONE;
2872 audio_clear_track_notifications();
2873 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, CODEC_OK);
2874 break;
2876 case TRACK_SKIP_AUTO:
2877 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2878 /* Precisely removing what it already decoded for the next track is
2879 not possible so a restart is required in order to continue the
2880 currently playing track without the now invalid future track
2881 playing */
2882 audio_start_playback(0, AUDIO_START_RESTART);
2883 break;
2885 default: /* Nothing else is a state */
2886 break;
2890 #ifdef AUDIO_HAVE_RECORDING
2891 /* Load the requested encoder type
2892 (Q_AUDIO_LOAD_ENCODER) */
2893 static void audio_on_load_encoder(int afmt)
2895 bool res = true;
2897 if (play_status != PLAY_STOPPED)
2898 audio_stop_playback(); /* Can't load both types at once */
2899 else
2900 codec_unload(); /* Encoder still loaded, stop and unload it */
2902 if (afmt != AFMT_UNKNOWN)
2904 res = codec_load(-1, afmt | CODEC_TYPE_ENCODER);
2905 if (res)
2906 codec_go(); /* These are run immediately */
2909 queue_reply(&audio_queue, res);
2911 #endif /* AUDIO_HAVE_RECORDING */
2913 static void audio_thread(void)
2915 struct queue_event ev;
2917 pcm_postinit();
2919 while (1)
2921 switch (filling)
2923 /* Active states */
2924 case STATE_FULL:
2925 case STATE_END_OF_PLAYLIST:
2926 if (buf_get_watermark() == 0)
2928 /* End of buffering for now, let's calculate the watermark,
2929 register for a low buffer event and unboost */
2930 audio_update_filebuf_watermark(0);
2931 add_event(BUFFER_EVENT_BUFFER_LOW, true,
2932 buffer_event_buffer_low_callback);
2934 /* Fall-through */
2935 case STATE_FINISHED:
2936 /* All data was buffered */
2937 cancel_cpu_boost();
2938 /* Fall-through */
2939 case STATE_FILLING:
2940 case STATE_ENDING:
2941 if (audio_pcmbuf_track_change_scan())
2943 /* Transfer notification to audio queue event */
2944 ev.id = Q_AUDIO_TRACK_CHANGED;
2945 ev.data = 1;
2947 else
2949 /* If doing auto skip, poll pcmbuf track notifications a bit
2950 faster to promply detect the transition */
2951 queue_wait_w_tmo(&audio_queue, &ev,
2952 skip_pending == TRACK_SKIP_NONE ?
2953 HZ/2 : HZ/10);
2955 break;
2957 /* Idle states */
2958 default:
2959 queue_wait(&audio_queue, &ev);
2961 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2962 switch (ev.id)
2964 #ifdef AUDIO_HAVE_RECORDING
2965 /* Must monitor the encoder message for recording so it can remove
2966 it if we process the insertion before it does. It cannot simply
2967 be removed from under recording however. */
2968 case Q_AUDIO_LOAD_ENCODER:
2969 break;
2970 #endif
2971 case SYS_USB_DISCONNECTED:
2972 filling = STATE_IDLE;
2973 break;
2975 default:
2976 if (filling == STATE_USB)
2977 continue;
2979 #endif /* CONFIG_PLATFORM */
2982 switch (ev.id)
2984 /** Codec and track change messages **/
2985 case Q_AUDIO_CODEC_COMPLETE:
2986 /* Codec is done processing track and has gone idle */
2987 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev.data);
2988 audio_on_codec_complete(ev.data);
2989 break;
2991 case Q_AUDIO_CODEC_SEEK_COMPLETE:
2992 /* Codec is done seeking */
2993 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
2994 audio_on_codec_seek_complete();
2995 break;
2997 case Q_AUDIO_TRACK_CHANGED:
2998 /* PCM track change done */
2999 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3000 audio_on_track_changed();
3001 break;
3003 /** Control messages **/
3004 case Q_AUDIO_PLAY:
3005 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3006 audio_start_playback(ev.data, 0);
3007 break;
3009 case Q_AUDIO_STOP:
3010 LOGFQUEUE("audio < Q_AUDIO_STOP");
3011 audio_stop_playback();
3012 if (ev.data != 0)
3013 queue_clear(&audio_queue);
3014 break;
3016 case Q_AUDIO_PAUSE:
3017 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3018 audio_on_pause(ev.data);
3019 break;
3021 case Q_AUDIO_SKIP:
3022 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3023 audio_on_skip();
3024 break;
3026 case Q_AUDIO_DIR_SKIP:
3027 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3028 audio_on_dir_skip(ev.data);
3029 break;
3031 case Q_AUDIO_PRE_FF_REWIND:
3032 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3033 audio_on_pre_ff_rewind();
3034 break;
3036 case Q_AUDIO_FF_REWIND:
3037 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3038 audio_on_ff_rewind(ev.data);
3039 break;
3041 case Q_AUDIO_FLUSH:
3042 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev.data);
3043 audio_on_audio_flush();
3044 break;
3046 /** Buffering messages **/
3047 case Q_AUDIO_BUFFERING:
3048 /* some buffering event */
3049 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev.data);
3050 audio_on_buffering(ev.data);
3051 break;
3053 case Q_AUDIO_FILL_BUFFER:
3054 /* continue buffering next track */
3055 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3056 audio_on_fill_buffer();
3057 break;
3059 case Q_AUDIO_FINISH_LOAD_TRACK:
3060 /* metadata is buffered */
3061 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3062 audio_on_finish_load_track(ev.data);
3063 break;
3065 case Q_AUDIO_HANDLE_FINISHED:
3066 /* some other type is buffered */
3067 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3068 audio_on_handle_finished(ev.data);
3069 break;
3071 /** Miscellaneous messages **/
3072 case Q_AUDIO_REMAKE_AUDIO_BUFFER:
3073 /* buffer needs to be reinitialized */
3074 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3075 audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
3076 break;
3078 #ifdef HAVE_DISK_STORAGE
3079 case Q_AUDIO_UPDATE_WATERMARK:
3080 /* buffering watermark needs updating */
3081 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev.data);
3082 audio_update_filebuf_watermark(ev.data);
3083 break;
3084 #endif /* HAVE_DISK_STORAGE */
3086 #ifdef AUDIO_HAVE_RECORDING
3087 case Q_AUDIO_LOAD_ENCODER:
3088 /* load an encoder for recording */
3089 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev.data);
3090 audio_on_load_encoder(ev.data);
3091 break;
3092 #endif /* AUDIO_HAVE_RECORDING */
3094 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3095 case SYS_USB_CONNECTED:
3096 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3097 audio_stop_playback();
3098 #ifdef PLAYBACK_VOICE
3099 voice_stop();
3100 #endif
3101 filling = STATE_USB;
3102 usb_acknowledge(SYS_USB_CONNECTED_ACK);
3103 break;
3104 #endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */
3106 case SYS_TIMEOUT:
3107 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3108 break;
3110 default:
3111 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3112 break;
3113 } /* end switch */
3114 } /* end while */
3118 /* --- Buffering callbacks --- */
3120 /* Called when fullness is below the watermark level */
3121 static void buffer_event_buffer_low_callback(void *data)
3123 logf("low buffer callback");
3124 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3125 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW);
3126 (void)data;
3129 /* Called when handles must be discarded in order to buffer new data */
3130 static void buffer_event_rebuffer_callback(void *data)
3132 logf("rebuffer callback");
3133 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3134 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER);
3135 (void)data;
3138 /* A handle has completed buffering and all required data is available */
3139 static void buffer_event_finished_callback(void *data)
3141 int hid = *(const int *)data;
3142 const enum data_type htype = buf_handle_data_type(hid);
3144 logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype);
3146 /* Limit queue traffic */
3147 switch (htype)
3149 case TYPE_ID3:
3150 /* The metadata handle for the last loaded track has been buffered.
3151 We can ask the audio thread to load the rest of the track's data. */
3152 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid);
3153 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK, hid);
3154 break;
3156 case TYPE_PACKET_AUDIO:
3157 /* Strip any useless trailing tags that are left. */
3158 strip_tags(hid);
3159 /* Fall-through */
3160 case TYPE_ATOMIC_AUDIO:
3161 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid);
3162 audio_queue_post(Q_AUDIO_HANDLE_FINISHED, hid);
3163 break;
3165 default:
3166 /* Don't care to know about these */
3167 break;
3172 /** -- Codec callbacks -- **/
3174 /* Update elapsed time for next PCM insert */
3175 void audio_codec_update_elapsed(unsigned long elapsed)
3177 #ifdef AB_REPEAT_ENABLE
3178 ab_position_report(elapsed);
3179 #endif
3180 /* Save in codec's id3 where it is used at next pcm insert */
3181 id3_get(CODEC_ID3)->elapsed = elapsed;
3184 /* Update offset for next PCM insert */
3185 void audio_codec_update_offset(size_t offset)
3187 /* Save in codec's id3 where it is used at next pcm insert */
3188 id3_get(CODEC_ID3)->offset = offset;
3191 /* Codec has finished running */
3192 void audio_codec_complete(int status)
3194 #ifdef AB_REPEAT_ENABLE
3195 if (status >= CODEC_OK)
3197 /* Normal automatic skip */
3198 ab_end_of_track_report();
3200 #endif
3202 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status);
3203 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, status);
3206 /* Codec has finished seeking */
3207 void audio_codec_seek_complete(void)
3209 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_SEEK_COMPLETE");
3210 audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE, 0);
3214 /** --- Pcmbuf callbacks --- **/
3216 /* Update the elapsed and offset from the information cached during the
3217 PCM buffer insert */
3218 void audio_pcmbuf_position_callback(unsigned long elapsed, off_t offset,
3219 unsigned int key)
3221 if (key == position_key)
3223 struct mp3entry *id3 = id3_get(PLAYING_ID3);
3224 id3->elapsed = elapsed;
3225 id3->offset = offset;
3229 /* Synchronize position info to the codec's */
3230 void audio_pcmbuf_sync_position(void)
3232 audio_pcmbuf_position_callback(ci.id3->elapsed, ci.id3->offset,
3233 pcmbuf_get_position_key());
3236 /* Post message from pcmbuf that the end of the previous track has just
3237 * been played */
3238 void audio_pcmbuf_track_change(bool pcmbuf)
3240 if (pcmbuf)
3242 /* Notify of the change in special-purpose semaphore object */
3243 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3244 audio_pcmbuf_track_change_post();
3246 else
3248 /* Safe to post directly to the queue */
3249 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3250 audio_queue_post(Q_AUDIO_TRACK_CHANGED, 0);
3254 /* May pcmbuf start PCM playback when the buffer is full enough? */
3255 bool audio_pcmbuf_may_play(void)
3257 return play_status == PLAY_PLAYING && !ff_rw_mode;
3261 /** -- External interfaces -- **/
3263 /* Return the playback and recording status */
3264 int audio_status(void)
3266 unsigned int ret = play_status;
3268 #ifdef AUDIO_HAVE_RECORDING
3269 /* Do this here for constitency with mpeg.c version */
3270 ret |= pcm_rec_status();
3271 #endif
3273 return (int)ret;
3276 /* Clear all accumulated audio errors for playback and recording */
3277 void audio_error_clear(void)
3279 #ifdef AUDIO_HAVE_RECORDING
3280 pcm_rec_error_clear();
3281 #endif
3284 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3285 bool audio_peek_track(struct mp3entry *id3, int offset)
3287 bool retval = false;
3289 id3_mutex_lock();
3291 if (play_status != PLAY_STOPPED)
3293 id3->path[0] = '\0'; /* Null path means it should be filled now */
3294 retval = audio_get_track_metadata(offset + skip_offset, id3) &&
3295 id3->path[0] != '\0';
3298 id3_mutex_unlock();
3300 return retval;
3303 /* Return the mp3entry for the currently playing track */
3304 struct mp3entry * audio_current_track(void)
3306 struct mp3entry *id3;
3308 id3_mutex_lock();
3310 #ifdef AUDIO_FAST_SKIP_PREVIEW
3311 if (skip_offset != 0)
3313 /* This is a peekahead */
3314 id3 = id3_get(PLAYING_PEEK_ID3);
3315 audio_peek_track(id3, 0);
3317 else
3318 #endif
3320 /* Normal case */
3321 id3 = id3_get(PLAYING_ID3);
3322 audio_get_track_metadata(0, id3);
3325 id3_mutex_unlock();
3327 return id3;
3330 /* Obtains the mp3entry for the next track from the current */
3331 struct mp3entry * audio_next_track(void)
3333 struct mp3entry *id3 = id3_get(NEXTTRACK_ID3);
3335 id3_mutex_lock();
3337 #ifdef AUDIO_FAST_SKIP_PREVIEW
3338 if (skip_offset != 0)
3340 /* This is a peekahead */
3341 if (!audio_peek_track(id3, 1))
3342 id3 = NULL;
3344 else
3345 #endif
3347 /* Normal case */
3348 if (!audio_get_track_metadata(1, id3))
3349 id3 = NULL;
3352 id3_mutex_unlock();
3354 return id3;
3357 /* Start playback at the specified offset */
3358 void audio_play(long offset)
3360 logf("audio_play");
3362 #ifdef PLAYBACK_VOICE
3363 /* Truncate any existing voice output so we don't have spelling
3364 * etc. over the first part of the played track */
3365 talk_force_shutup();
3366 #endif
3368 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
3369 audio_queue_send(Q_AUDIO_PLAY, offset);
3372 /* Stop playback if playing */
3373 void audio_stop(void)
3375 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3376 audio_queue_send(Q_AUDIO_STOP, 0);
3379 /* Pause playback if playing */
3380 void audio_pause(void)
3382 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3383 audio_queue_send(Q_AUDIO_PAUSE, true);
3386 /* This sends a stop message and the audio thread will dump all its
3387 subsequent messages */
3388 void audio_hard_stop(void)
3390 /* Stop playback */
3391 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3392 audio_queue_send(Q_AUDIO_STOP, 1);
3393 #ifdef PLAYBACK_VOICE
3394 voice_stop();
3395 #endif
3396 if (audiobuf_handle > 0)
3397 audiobuf_handle = core_free(audiobuf_handle);
3400 /* Resume playback if paused */
3401 void audio_resume(void)
3403 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3404 audio_queue_send(Q_AUDIO_PAUSE, false);
3407 /* Skip the specified number of tracks forward or backward from the current */
3408 void audio_skip(int offset)
3410 id3_mutex_lock();
3412 /* If offset has to be backed-out to stay in range, no skip is done */
3413 int accum = skip_offset + offset;
3415 while (offset != 0 && !playlist_check(accum))
3417 offset += offset < 0 ? 1 : -1;
3418 accum = skip_offset + offset;
3421 if (offset != 0)
3423 /* Accumulate net manual skip count since the audio thread last
3424 processed one */
3425 skip_offset = accum;
3427 system_sound_play(SOUND_TRACK_SKIP);
3429 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset);
3431 #ifdef AUDIO_FAST_SKIP_PREVIEW
3432 /* Do this before posting so that the audio thread can correct us
3433 when things settle down - additionally, if audio gets a message
3434 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3435 handler a skip event with the correct info but doesn't skip */
3436 send_event(PLAYBACK_EVENT_TRACK_SKIP, NULL);
3437 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3439 /* Playback only needs the final state even if more than one is
3440 processed because it wasn't removed in time */
3441 queue_remove_from_head(&audio_queue, Q_AUDIO_SKIP);
3442 audio_queue_post(Q_AUDIO_SKIP, 0);
3444 else
3446 /* No more tracks */
3447 system_sound_play(SOUND_TRACK_NO_MORE);
3450 id3_mutex_unlock();
3453 /* Skip one track forward from the current */
3454 void audio_next(void)
3456 audio_skip(1);
3459 /* Skip one track backward from the current */
3460 void audio_prev(void)
3462 audio_skip(-1);
3465 /* Move one directory forward */
3466 void audio_next_dir(void)
3468 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3469 audio_queue_post(Q_AUDIO_DIR_SKIP, 1);
3472 /* Move one directory backward */
3473 void audio_prev_dir(void)
3475 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3476 audio_queue_post(Q_AUDIO_DIR_SKIP, -1);
3479 /* Pause playback in order to start a seek that flushes the old audio */
3480 void audio_pre_ff_rewind(void)
3482 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3483 audio_queue_post(Q_AUDIO_PRE_FF_REWIND, 0);
3486 /* Seek to the new time in the current track */
3487 void audio_ff_rewind(long time)
3489 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3490 audio_queue_post(Q_AUDIO_FF_REWIND, time);
3493 /* Clear all but the currently playing track then rebuffer */
3494 void audio_flush_and_reload_tracks(void)
3496 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3497 audio_queue_post(Q_AUDIO_FLUSH, 0);
3500 /* Return the pointer to the main audio buffer, optionally preserving
3501 voicing */
3502 unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
3504 unsigned char *buf;
3506 if (audio_is_initialized)
3508 audio_hard_stop();
3510 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3512 if (buffer_size == NULL)
3514 /* Special case for talk_init to use since it already knows it's
3515 trashed */
3516 buffer_state = AUDIOBUF_STATE_TRASHED;
3517 return NULL;
3520 /* make sure buffer is freed and re-allocated to simplify code below
3521 * (audio_hard_stop() likely has done that already) */
3522 if (audiobuf_handle > 0)
3523 audiobuf_handle = core_free(audiobuf_handle);
3525 audiobuf_handle = core_alloc_maximum("audiobuf", &filebuflen, &ops);
3526 buf = core_get_data(audiobuf_handle);
3528 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
3529 || !talk_voice_required())
3531 logf("get buffer: talk, audio");
3532 /* Ok to use everything from audiobuf - voice is loaded,
3533 the talk buffer is not needed because voice isn't being used, or
3534 could be AUDIOBUF_STATE_TRASHED already. If state is
3535 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3536 written without the caller knowing what's going on. Changing certain
3537 settings may move it to a worse condition but the memory in use by
3538 something else will remain undisturbed.
3540 if (buffer_state != AUDIOBUF_STATE_TRASHED)
3542 talk_buffer_steal();
3543 buffer_state = AUDIOBUF_STATE_TRASHED;
3546 else
3548 logf("get buffer: audio");
3549 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3550 still AUDIOBUF_STATE_INITIALIZED */
3551 /* Skip talk buffer and move pcm buffer to end to maximize available
3552 contiguous memory - no audio running means voice will not need the
3553 swap space */
3554 size_t talkbuf_size;
3555 buf += talkbuf_size = talkbuf_init(buf);
3556 filebuflen -= talkbuf_size;
3557 filebuflen -= voicebuf_init(buf + filebuflen);
3559 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
3562 *buffer_size = filebuflen;
3563 return buf;
3566 #ifdef HAVE_RECORDING
3567 /* Stop audio, voice and obtain all available buffer space */
3568 unsigned char * audio_get_recording_buffer(size_t *buffer_size)
3570 audio_hard_stop();
3571 return audio_get_buffer(true, buffer_size);
3573 #endif /* HAVE_RECORDING */
3575 /* Restore audio buffer to a particular state (one more valid than the current
3576 state) */
3577 bool audio_restore_playback(int type)
3579 switch (type)
3581 case AUDIO_WANT_PLAYBACK:
3582 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
3583 audio_reset_buffer();
3584 return true;
3585 case AUDIO_WANT_VOICE:
3586 if (buffer_state == AUDIOBUF_STATE_TRASHED)
3587 audio_reset_buffer();
3588 return true;
3589 default:
3590 return false;
3594 /* Has the playback buffer been completely claimed? */
3595 bool audio_buffer_state_trashed(void)
3597 return buffer_state == AUDIOBUF_STATE_TRASHED;
3601 /** --- Miscellaneous public interfaces --- **/
3603 #ifdef HAVE_ALBUMART
3604 /* Return which album art handle is current for the user in the given slot */
3605 int playback_current_aa_hid(int slot)
3607 if ((unsigned)slot < MAX_MULTIPLE_AA)
3609 struct track_info *info = track_list_user_current(skip_offset);
3611 if (!info && abs(skip_offset) <= 1)
3613 /* Give the actual position a go */
3614 info = track_list_user_current(0);
3617 if (info)
3618 return info->aa_hid[slot];
3621 return ERR_HANDLE_NOT_FOUND;
3624 /* Find an album art slot that doesn't match the dimensions of another that
3625 is already claimed - increment the use count if it is */
3626 int playback_claim_aa_slot(struct dim *dim)
3628 int i;
3630 /* First try to find a slot already having the size to reuse it since we
3631 don't want albumart of the same size buffered multiple times */
3632 FOREACH_ALBUMART(i)
3634 struct albumart_slot *slot = &albumart_slots[i];
3636 if (slot->dim.width == dim->width &&
3637 slot->dim.height == dim->height)
3639 slot->used++;
3640 return i;
3644 /* Size is new, find a free slot */
3645 FOREACH_ALBUMART(i)
3647 if (!albumart_slots[i].used)
3649 albumart_slots[i].used++;
3650 albumart_slots[i].dim = *dim;
3651 return i;
3655 /* Sorry, no free slot */
3656 return -1;
3659 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3660 void playback_release_aa_slot(int slot)
3662 if ((unsigned)slot < MAX_MULTIPLE_AA)
3664 struct albumart_slot *aa_slot = &albumart_slots[slot];
3666 if (aa_slot->used > 0)
3667 aa_slot->used--;
3670 #endif /* HAVE_ALBUMART */
3673 #ifdef HAVE_RECORDING
3674 /* Load an encoder and run it */
3675 bool audio_load_encoder(int afmt)
3677 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3678 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt);
3679 return audio_queue_send(Q_AUDIO_LOAD_ENCODER, afmt) != 0;
3680 #else
3681 (void)afmt;
3682 return true;
3683 #endif
3686 /* Stop an encoder and unload it */
3687 void audio_remove_encoder(void)
3689 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3690 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3691 audio_queue_send(Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN);
3692 #endif
3694 #endif /* HAVE_RECORDING */
3696 /* Is an automatic skip in progress? If called outside transition callbacks,
3697 indicates the last skip type at the time it was processed and isn't very
3698 meaningful. */
3699 bool audio_automatic_skip(void)
3701 return automatic_skip;
3704 /* Would normally calculate byte offset from an elapsed time but is not
3705 used on SWCODEC */
3706 int audio_get_file_pos(void)
3708 return 0;
3711 /* Return the elapsed time of the track previous to the current */
3712 unsigned long audio_prev_elapsed(void)
3714 return prev_track_elapsed;
3717 /* Return total file buffer length after accounting for the talk buf */
3718 size_t audio_get_filebuflen(void)
3720 return buf_length();
3723 /* How many tracks exist on the buffer - full or partial */
3724 int audio_track_count(void)
3725 __attribute__((alias("track_list_count")));
3727 /* Return total ringbuffer space occupied - ridx to widx */
3728 long audio_filebufused(void)
3730 return buf_used();
3734 /** -- Settings -- **/
3736 /* Enable or disable cuesheet support and allocate/don't allocate the
3737 extra associated resources */
3738 void audio_set_cuesheet(int enable)
3740 if (play_status == PLAY_STOPPED || !enable != !get_current_cuesheet())
3742 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3743 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
3747 #ifdef HAVE_DISK_STORAGE
3748 /* Set the audio antiskip buffer margin by index */
3749 void audio_set_buffer_margin(int setting)
3751 static const unsigned short lookup[] =
3752 { 5, 15, 30, 60, 120, 180, 300, 600 };
3754 if ((unsigned)setting >= ARRAYLEN(lookup))
3755 setting = 0;
3757 logf("buffer margin: %u", (unsigned)lookup[setting]);
3759 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3760 (unsigned)lookup[setting]);
3761 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK, lookup[setting]);
3763 #endif /* HAVE_DISK_STORAGE */
3765 #ifdef HAVE_CROSSFADE
3766 /* Take necessary steps to enable or disable the crossfade setting */
3767 void audio_set_crossfade(int enable)
3769 /* Tell it the next setting to use */
3770 pcmbuf_request_crossfade_enable(enable);
3772 /* Return if size hasn't changed or this is too early to determine
3773 which in the second case there's no way we could be playing
3774 anything at all */
3775 if (!pcmbuf_is_same_size())
3777 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3778 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
3781 #endif /* HAVE_CROSSFADE */
3784 /** -- Startup -- **/
3786 /* Initialize the audio system - called from init() in main.c */
3787 void audio_init(void)
3789 /* Can never do this twice */
3790 if (audio_is_initialized)
3792 logf("audio: already initialized");
3793 return;
3796 logf("audio: initializing");
3798 /* Initialize queues before giving control elsewhere in case it likes
3799 to send messages. Thread creation will be delayed however so nothing
3800 starts running until ready if something yields such as talk_init. */
3801 queue_init(&audio_queue, true);
3803 mutex_init(&id3_mutex);
3805 pcm_init();
3807 codec_thread_init();
3809 /* This thread does buffer, so match its priority */
3810 audio_thread_id = create_thread(audio_thread, audio_stack,
3811 sizeof(audio_stack), 0, audio_thread_name
3812 IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE))
3813 IF_COP(, CPU));
3815 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
3816 audio_thread_id);
3818 #ifdef PLAYBACK_VOICE
3819 voice_thread_init();
3820 #endif
3822 /* audio_reset_buffer must know the size of voice buffer so init
3823 talk first */
3824 talk_init();
3826 #ifdef HAVE_CROSSFADE
3827 /* Set crossfade setting for next buffer init which should be about... */
3828 pcmbuf_request_crossfade_enable(global_settings.crossfade);
3829 #endif
3831 /* Initialize the buffering system */
3832 track_list_init();
3833 buffering_init();
3834 /* ...now! Set up the buffers */
3835 audio_reset_buffer();
3837 /* Probably safe to say */
3838 audio_is_initialized = true;
3840 sound_settings_apply();
3841 #ifdef HAVE_DISK_STORAGE
3842 audio_set_buffer_margin(global_settings.buffer_margin);
3843 #endif