1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
27 #include "core_alloc.h"
32 #include "codec_thread.h"
33 #include "voice_thread.h"
36 #include "buffering.h"
49 #ifdef AUDIO_HAVE_RECORDING
50 #include "pcm_record.h"
53 #ifdef HAVE_LCD_BITMAP
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
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 */
79 /* Macros to enable logf for queues
80 logging on SYS_TIMEOUT can be disabled */
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*/
88 #ifdef PLAYBACK_LOGQUEUES
89 #define LOGFQUEUE logf
91 #define LOGFQUEUE(...)
94 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
95 #define LOGFQUEUE_SYS_TIMEOUT logf
97 #define LOGFQUEUE_SYS_TIMEOUT(...)
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
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-) */
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
142 /* These are allocated statically */
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 */
151 /* These go in the scratch memory */
152 UNBUFFERED_ID3
= ID3_TYPE_NUM_STATIC
,
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
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 */
196 } filling
= STATE_IDLE
;
198 /* Track info - holds information about each track in the buffer */
201 /* In per-track allocated order: */
202 int id3_hid
; /* Metadata handle ID */
203 int cuesheet_hid
; /* Parsed cuesheet handle ID */
205 int aa_hid
[MAX_MULTIPLE_AA
];/* Album art handle IDs */
207 #ifdef HAVE_CODEC_BUFFERING
208 int codec_hid
; /* Buffered codec handle ID */
210 int audio_hid
; /* Main audio data handle ID */
211 size_t filesize
; /* File total length on disk
212 TODO: This should be stored
214 id3 and would use less
218 /* Track list - holds info about all buffered tracks */
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
226 #define TRACK_LIST_LEN 16
229 #define TRACK_LIST_MASK (TRACK_LIST_LEN-1)
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;
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,
272 LOAD_TRACK_READY
= 1,
275 /** Track change controls **/
277 /* What sort of skip is pending globally? */
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 */
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 };
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;
336 static struct event_queue audio_queue SHAREDBSS_ATTR
;
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
)
388 struct mp3entry
*id3
;
389 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
391 if (ret
!= sizeof(struct mp3entry
))
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
);
404 copy_mp3entry(id3out
, id3
);
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
)
429 return &audio_scratch_memory
->unbuffered_id3
;
431 return &audio_scratch_memory
->codec_id3
;
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
);
444 copy_mp3entry(dest_id3
, id3_src
);
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
)
455 id3_write(id3_num
, id3_src
);
460 /** --- Track info --- **/
462 /* Close a handle and mark it invalid */
463 static void track_info_close_handle(int *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 */
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
);
486 track_info_close_handle(&info
->aa_hid
[i
]);
488 #ifdef HAVE_CODEC_BUFFERING
489 track_info_close_handle(&info
->codec_hid
);
491 track_info_close_handle(&info
->audio_hid
);
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
;
503 info
->aa_hid
[i
] = ERR_HANDLE_NOT_FOUND
;
505 #ifdef HAVE_CODEC_BUFFERING
506 info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
508 info
->audio_hid
= ERR_HANDLE_NOT_FOUND
;
513 /** --- Track list --- **/
515 /* Initialize the track list */
516 static void track_list_init(void)
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
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
))
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())
574 return track_list_entry(track_list
.end
++);
577 /* Remove the last track entry allocated in order to support backing out
579 static void track_list_unalloc_track(void)
581 if (track_list_empty())
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
))
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
)
615 return track_list_current(offset
);
618 /* Advance current track by an offset, return false if result is out of
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
))
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
;
664 case TRACK_LIST_CLEAR_ALL
:
665 /* Result: .start = .current, .end = .current */
666 track_list
.end
= current
;
669 case TRACK_LIST_KEEP_CURRENT
:
670 /* Result: .start = .current, .end = .current + 1 */
671 track_list
.end
= current
+ 1;
674 case TRACK_LIST_KEEP_NEW
:
675 /* Result: .start = .current, .end = .end */
680 /* Close all open handles in the range except the for the current track
681 if preserving that */
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
);
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
);
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 */
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 */
764 /* Subtract whatever voice needs */
765 allocsize
= talkbuf_init(filebuf
);
766 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
767 if (allocsize
> filebuflen
)
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
)
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
)
793 filebuflen
-= allocsize
;
796 allocsize
= scratch_mem_size();
797 if (allocsize
> filebuflen
)
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
));
824 panicf("%s(): EOM (%zu > %zu)", __func__
, allocsize
, filebuflen
);
827 /* Buffer must not move. */
828 static int shrink_callback(int handle
, unsigned hints
, void* start
, size_t old_size
)
830 struct queue_event ev
;
831 static const long filter_list
[][2] =
834 { Q_AUDIO_PLAY
, Q_AUDIO_PLAY
},
836 /* filebuflen is, at this point, the buffering.c buffer size,
837 * i.e. the audiobuf except voice, scratch mem, pcm, ... */
838 ssize_t extradata_size
= old_size
- filebuflen
;
839 /* check what buflib requests */
840 size_t wanted_size
= (hints
& BUFLIB_SHRINK_SIZE_MASK
);
841 ssize_t size
= (ssize_t
)old_size
- wanted_size
;
842 /* keep at least 256K for the buffering */
843 if ((size
- extradata_size
) < 256*1024)
844 return BUFLIB_CB_CANNOT_SHRINK
;
847 /* TODO: Do it without stopping playback, if possible */
848 long offset
= audio_current_track()->offset
;
849 bool playing
= (audio_status() & AUDIO_STATUS_PLAY
) == AUDIO_STATUS_PLAY
;
850 /* There's one problem with stoping and resuming: If it happens in a too
851 * frequent fashion, the codecs lose the resume postion and playback
852 * begins from the beginning.
853 * To work around use queue_post() to effectively delay the resume in case
854 * we're called another time. However this has another problem: id3->offset
855 * gets zero since playback is stopped. Therefore, try to peek at the
856 * queue_post from the last call to get the correct offset. This also
857 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
859 bool play_queued
= queue_peek_ex(&audio_queue
, &ev
, QPEEK_REMOVE_EVENTS
, filter_list
);
861 if (playing
&& offset
> 0) /* current id3->offset is king */
864 /* don't call audio_hard_stop() as it frees this handle */
865 if (thread_self() == audio_thread_id
)
866 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
867 * if we're in the audio thread */
868 audio_stop_playback();
869 queue_clear(&audio_queue
);
872 audio_queue_send(Q_AUDIO_STOP
, 1);
873 #ifdef PLAYBACK_VOICE
876 /* we should be free to change the buffer now
877 * set final buffer size before calling audio_reset_buffer_noalloc()
878 * (now it's the total size, the call will subtract voice etc) */
880 switch (hints
& BUFLIB_SHRINK_POS_MASK
)
882 case BUFLIB_SHRINK_POS_BACK
:
883 core_shrink(handle
, start
, size
);
884 audio_reset_buffer_noalloc(start
);
886 case BUFLIB_SHRINK_POS_FRONT
:
887 core_shrink(handle
, start
+ wanted_size
, size
);
888 audio_reset_buffer_noalloc(start
+ wanted_size
);
891 if (playing
|| play_queued
)
893 /* post, to make subsequent calls not break the resume position */
894 audio_queue_post(Q_AUDIO_PLAY
, ev
.data
);
900 static struct buflib_callbacks ops
= {
901 .move_callback
= NULL
,
902 .shrink_callback
= shrink_callback
,
905 static void audio_reset_buffer(void)
907 if (audiobuf_handle
> 0)
909 core_free(audiobuf_handle
);
912 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
913 unsigned char *filebuf
= core_get_data(audiobuf_handle
);
915 audio_reset_buffer_noalloc(filebuf
);
918 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
919 static void audio_update_filebuf_watermark(int seconds
)
923 #ifdef HAVE_DISK_STORAGE
924 int spinup
= ata_spinup_time();
928 /* By current setting */
929 seconds
= buffer_margin
;
934 buffer_margin
= seconds
;
936 if (buf_get_watermark() == 0)
938 /* Write a watermark only if the audio thread already did so for
939 itself or it will fail to set the event and the watermark - if
940 it hasn't yet, it will use the new setting when it does */
946 seconds
+= (spinup
/ HZ
) + 1;
950 seconds
+= buffer_margin
;
956 /* Watermark is a function of the bitrate of the last track in the buffer */
957 struct mp3entry
*id3
= NULL
;
958 struct track_info
*info
= track_list_last(0);
961 id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
965 if (get_audio_base_data_type(id3
->codectype
) == TYPE_PACKET_AUDIO
)
967 bytes
= id3
->bitrate
* (1000/8) * seconds
;
971 /* Bitrate has no meaning to buffering margin for atomic audio -
972 rebuffer when it's the only track left unless it's the only
973 track that fits, in which case we should avoid constant buffer
975 if (track_list_count() > 1)
976 bytes
= info
->filesize
+ 1;
981 /* Then set the minimum - this should not occur anyway */
982 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
983 track_list
.start
, track_list
.current
, track_list
.end
);
986 /* Actually setting zero disables the notification and we use that
987 to detect that it has been reset */
988 buf_set_watermark(MAX(bytes
, 1));
989 logf("fwmark: %lu", (unsigned long)bytes
);
993 /** -- Track change notification -- **/
995 /* Check the pcmbuf track changes and return write the message into the event
997 static inline bool audio_pcmbuf_track_change_scan(void)
999 if (track_change
.out
!= track_change
.in
)
1008 /* Clear outstanding track change posts */
1009 static inline void audio_pcmbuf_track_change_clear(void)
1011 track_change
.out
= track_change
.in
;
1014 /* Post a track change notification - called by audio ISR */
1015 static inline void audio_pcmbuf_track_change_post(void)
1021 /** --- Helper functions --- **/
1023 /* Removes messages that might end up in the queue before or while processing
1024 a manual track change. Responding to them would be harmful since they
1025 belong to a previous track's playback period. Anything that would generate
1026 the stale messages must first be put into a state where it will not do so.
1028 static void audio_clear_track_notifications(void)
1030 static const long filter_list
[][2] =
1032 /* codec messages */
1033 { Q_AUDIO_CODEC_SEEK_COMPLETE
, Q_AUDIO_CODEC_COMPLETE
},
1034 /* track change messages */
1035 { Q_AUDIO_TRACK_CHANGED
, Q_AUDIO_TRACK_CHANGED
},
1038 const int filter_count
= ARRAYLEN(filter_list
) - 1;
1040 /* Remove any pcmbuf notifications */
1041 pcmbuf_monitor_track_change(false);
1042 audio_pcmbuf_track_change_clear();
1044 /* Scrub the audio queue of the old mold */
1045 while (queue_peek_ex(&audio_queue
, NULL
,
1046 filter_count
| QPEEK_REMOVE_EVENTS
,
1049 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1053 /* Takes actions based upon track load status codes */
1054 static void audio_handle_track_load_status(int trackstat
)
1058 case LOAD_TRACK_ERR_NO_MORE
:
1059 if (track_list_count() > 0)
1062 case LOAD_TRACK_ERR_START_CODEC
:
1063 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_ERROR
);
1071 /* Announce the end of playing the current track */
1072 static void audio_playlist_track_finish(void)
1074 struct mp3entry
*ply_id3
= id3_get(PLAYING_ID3
);
1075 struct mp3entry
*id3
= valid_mp3entry(ply_id3
);
1077 playlist_update_resume_info(filling
== STATE_ENDED
? NULL
: id3
);
1081 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
1082 prev_track_elapsed
= id3
->elapsed
;
1086 prev_track_elapsed
= 0;
1090 /* Announce the beginning of the new track */
1091 static void audio_playlist_track_change(void)
1093 struct mp3entry
*id3
= valid_mp3entry(id3_get(PLAYING_ID3
));
1096 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, id3
);
1098 position_key
= pcmbuf_get_position_key();
1100 playlist_update_resume_info(id3
);
1103 /* Change the data for the next track and send the event */
1104 static void audio_update_and_announce_next_track(const struct mp3entry
*id3_next
)
1106 id3_write_locked(NEXTTRACK_ID3
, id3_next
);
1107 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
,
1108 id3_get(NEXTTRACK_ID3
));
1111 /* Bring the user current mp3entry up to date and set a new offset for the
1112 buffered metadata */
1113 static void playing_id3_sync(struct track_info
*user_info
, off_t offset
)
1117 struct mp3entry
*id3
= bufgetid3(user_info
->id3_hid
);
1118 struct mp3entry
*playing_id3
= id3_get(PLAYING_ID3
);
1122 unsigned long e
= playing_id3
->elapsed
;
1123 unsigned long o
= playing_id3
->offset
;
1125 id3_write(PLAYING_ID3
, id3
);
1129 playing_id3
->elapsed
= e
;
1130 playing_id3
->offset
= o
;
1137 id3
->offset
= offset
;
1142 /* Wipe-out track metadata - current is optional */
1143 static void wipe_track_metadata(bool current
)
1148 id3_write(PLAYING_ID3
, NULL
);
1150 id3_write(NEXTTRACK_ID3
, NULL
);
1151 id3_write(UNBUFFERED_ID3
, NULL
);
1156 /* Called when buffering is completed on the last track handle */
1157 static void filling_is_finished(void)
1159 logf("last track finished buffering");
1161 /* There's no more to load or watch for */
1162 buf_set_watermark(0);
1163 filling
= STATE_FINISHED
;
1166 /* Stop the codec decoding or waiting for its data to be ready - returns
1167 'false' if the codec ended up stopped */
1168 static bool halt_decoding_track(bool stop
)
1170 /* If it was waiting for us to clear the buffer to make a rebuffer
1171 happen, it should cease otherwise codec_stop could deadlock waiting
1172 for the codec to go to its main loop - codec's request will now
1174 bool retval
= false;
1176 buf_signal_handle(ci
.audio_hid
, true);
1181 retval
= codec_pause();
1183 audio_clear_track_notifications();
1185 /* We now know it's idle and not waiting for buffered data */
1186 buf_signal_handle(ci
.audio_hid
, false);
1188 codec_skip_pending
= false;
1189 codec_seeking
= false;
1194 /* Wait for any in-progress fade to complete */
1195 static void audio_wait_fade_complete(void)
1197 /* Just loop until it's done */
1198 while (pcmbuf_fading())
1202 /* End the ff/rw mode */
1203 static void audio_ff_rewind_end(void)
1205 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1213 /* Clear the buffer */
1215 audio_pcmbuf_sync_position();
1218 if (play_status
!= PLAY_PAUSED
)
1220 /* Seeking-while-playing, resume PCM playback */
1221 pcmbuf_pause(false);
1226 /* Complete the codec seek */
1227 static void audio_complete_codec_seek(void)
1229 /* If a seek completed while paused, 'paused' is true.
1230 * If seeking from seek mode, 'ff_rw_mode' is true. */
1233 audio_ff_rewind_end();
1234 codec_seeking
= false; /* set _after_ the call! */
1236 /* else it's waiting and we must repond */
1239 /* Get the current cuesheet pointer */
1240 static inline struct cuesheet
* get_current_cuesheet(void)
1242 return audio_scratch_memory
->curr_cue
;
1245 /* Read the cuesheet from the buffer */
1246 static void buf_read_cuesheet(int handle_id
)
1248 struct cuesheet
*cue
= get_current_cuesheet();
1250 if (!cue
|| handle_id
< 0)
1253 bufread(handle_id
, sizeof (struct cuesheet
), cue
);
1256 /* Backend to peek/current/next track metadata interface functions -
1257 fill in the mp3entry with as much information as we may obtain about
1258 the track at the specified offset from the user current track -
1259 returns false if no information exists with us */
1260 static bool audio_get_track_metadata(int offset
, struct mp3entry
*id3
)
1262 if (play_status
== PLAY_STOPPED
)
1265 if (id3
->path
[0] != '\0')
1266 return true; /* Already filled */
1268 struct track_info
*info
= track_list_user_current(offset
);
1272 struct mp3entry
*ub_id3
= id3_get(UNBUFFERED_ID3
);
1274 if (offset
> 0 && track_list_user_current(offset
- 1))
1276 /* Try the unbuffered id3 since we're moving forward */
1277 if (ub_id3
->path
[0] != '\0')
1279 copy_mp3entry(id3
, ub_id3
);
1284 else if (bufreadid3(info
->id3_hid
, id3
))
1286 id3
->cuesheet
= NULL
;
1290 /* We didn't find the ID3 metadata, so we fill it with the little info we
1291 have and return that */
1293 char path
[MAX_PATH
+1];
1294 if (playlist_peek(offset
, path
, sizeof (path
)))
1296 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1297 /* Try to get it from the database */
1298 if (!tagcache_fill_tags(id3
, path
))
1301 /* By now, filename is the only source of info */
1302 fill_metadata_from_path(id3
, path
);
1313 /* Get a resume rewind adjusted offset from the ID3 */
1314 static unsigned long resume_rewind_adjusted_offset(const struct mp3entry
*id3
)
1316 unsigned long offset
= id3
->offset
;
1317 size_t resume_rewind
= global_settings
.resume_rewind
*
1318 id3
->bitrate
* (1000/8);
1320 if (offset
< resume_rewind
)
1323 offset
-= resume_rewind
;
1328 /* Get the codec into ram and initialize it - keep it if it's ready */
1329 static bool audio_init_codec(struct track_info
*track_info
,
1330 struct mp3entry
*track_id3
)
1332 int codt_loaded
= get_audio_base_codec_type(codec_loaded());
1333 int hid
= ERR_HANDLE_NOT_FOUND
;
1335 if (codt_loaded
!= AFMT_UNKNOWN
)
1337 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1339 if (codt
== codt_loaded
)
1341 /* Codec is the same base type */
1342 logf("Reusing prev. codec: %d", track_id3
->codectype
);
1343 #ifdef HAVE_CODEC_BUFFERING
1344 /* Close any buffered codec (we could have skipped directly to a
1345 format transistion that is the same format as the current track
1346 and the buffered one is no longer needed) */
1347 track_info_close_handle(&track_info
->codec_hid
);
1353 /* New codec - first make sure the old one's gone */
1354 logf("Removing prev. codec: %d", codt_loaded
);
1359 logf("New codec: %d/%d", track_id3
->codectype
, codec_loaded());
1361 #ifdef HAVE_CODEC_BUFFERING
1362 /* Codec thread will close the handle even if it fails and will load from
1363 storage if hid is not valid or the buffer load fails */
1364 hid
= track_info
->codec_hid
;
1365 track_info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
1368 return codec_load(hid
, track_id3
->codectype
);
1369 (void)track_info
; /* When codec buffering isn't supported */
1372 /* Start the codec for the current track scheduled to be decoded */
1373 static bool audio_start_codec(bool auto_skip
)
1375 struct track_info
*info
= track_list_current(0);
1376 struct mp3entry
*cur_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1381 buf_pin_handle(info
->id3_hid
, true);
1383 if (!audio_init_codec(info
, cur_id3
))
1385 buf_pin_handle(info
->id3_hid
, false);
1389 #ifdef HAVE_TAGCACHE
1390 bool autoresume_enable
= global_settings
.autoresume_enable
;
1392 if (autoresume_enable
&& !cur_id3
->offset
)
1394 /* Resume all manually selected tracks */
1395 bool resume
= !auto_skip
;
1397 /* Send the "buffer" event to obtain the resume position for the codec */
1398 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1402 /* Automatic skip - do further tests to see if we should just
1403 ignore any autoresume position */
1404 int autoresume_automatic
= global_settings
.autoresume_automatic
;
1406 switch (autoresume_automatic
)
1408 case AUTORESUME_NEXTTRACK_ALWAYS
:
1409 /* Just resume unconditionally */
1412 case AUTORESUME_NEXTTRACK_NEVER
:
1413 /* Force-rewind it */
1416 /* Not "never resume" - pass resume filter? */
1417 resume
= autoresumable(cur_id3
);
1422 cur_id3
->offset
= 0;
1424 logf("%s: Set offset for %s to %lX\n", __func__
,
1425 cur_id3
->title
, cur_id3
->offset
);
1427 #endif /* HAVE_TAGCACHE */
1429 /* Rewind the required amount - if an autoresume was done, this also rewinds
1430 that by the setting's amount
1432 It would be best to have bookkeeping about whether or not the track
1433 sounded or not since skipping to it or else skipping to it while paused
1434 and back again will cause accumulation of silent rewinds - that's not
1435 our job to track directly nor could it be in any reasonable way
1437 cur_id3
->offset
= resume_rewind_adjusted_offset(cur_id3
);
1439 /* Update the codec API with the metadata and track info */
1440 id3_write(CODEC_ID3
, cur_id3
);
1442 ci
.audio_hid
= info
->audio_hid
;
1443 ci
.filesize
= info
->filesize
;
1444 buf_set_base_handle(info
->audio_hid
);
1446 /* All required data is now available for the codec */
1449 #ifdef HAVE_TAGCACHE
1450 if (!autoresume_enable
|| cur_id3
->offset
)
1453 /* Send the "buffer" event now */
1454 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1457 buf_pin_handle(info
->id3_hid
, false);
1460 (void)auto_skip
; /* ifndef HAVE_TAGCACHE */
1464 /** --- Audio thread --- **/
1466 /* Load and parse a cuesheet for the file - returns false if the buffer
1468 static bool audio_load_cuesheet(struct track_info
*info
,
1469 struct mp3entry
*track_id3
)
1471 struct cuesheet
*cue
= get_current_cuesheet();
1472 track_id3
->cuesheet
= NULL
;
1474 if (cue
&& info
->cuesheet_hid
== ERR_HANDLE_NOT_FOUND
)
1476 /* If error other than a full buffer, then mark it "unsupported" to
1477 avoid reloading attempt */
1478 int hid
= ERR_UNSUPPORTED_TYPE
;
1479 char cuepath
[MAX_PATH
];
1481 #ifdef HAVE_IO_PRIORITY
1482 buf_back_off_storage(true);
1484 if (look_for_cuesheet_file(track_id3
->path
, cuepath
))
1486 hid
= bufalloc(NULL
, sizeof (struct cuesheet
), TYPE_CUESHEET
);
1490 void *cuesheet
= NULL
;
1491 bufgetdata(hid
, sizeof (struct cuesheet
), &cuesheet
);
1493 if (parse_cuesheet(cuepath
, (struct cuesheet
*)cuesheet
))
1495 /* Indicate cuesheet is present (while track remains
1497 track_id3
->cuesheet
= cue
;
1502 hid
= ERR_UNSUPPORTED_TYPE
;
1507 #ifdef HAVE_IO_PRIORITY
1508 buf_back_off_storage(false);
1510 if (hid
== ERR_BUFFER_FULL
)
1512 logf("buffer is full for now (%s)", __func__
);
1518 logf("Cuesheet loading failed");
1520 info
->cuesheet_hid
= hid
;
1527 #ifdef HAVE_ALBUMART
1528 /* Load any album art for the file - returns false if the buffer is full */
1529 static bool audio_load_albumart(struct track_info
*info
,
1530 struct mp3entry
*track_id3
)
1535 struct bufopen_bitmap_data user_data
;
1536 int *aa_hid
= &info
->aa_hid
[i
];
1537 int hid
= ERR_UNSUPPORTED_TYPE
;
1539 /* albumart_slots may change during a yield of bufopen,
1540 * but that's no problem */
1541 if (*aa_hid
>= 0 || *aa_hid
== ERR_UNSUPPORTED_TYPE
||
1542 !albumart_slots
[i
].used
)
1545 memset(&user_data
, 0, sizeof(user_data
));
1546 user_data
.dim
= &albumart_slots
[i
].dim
;
1548 #ifdef HAVE_IO_PRIORITY
1549 buf_back_off_storage(true);
1552 /* We can only decode jpeg for embedded AA */
1553 if (track_id3
->embed_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1555 user_data
.embedded_albumart
= &track_id3
->albumart
;
1556 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1559 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1561 /* No embedded AA or it couldn't be loaded - try other sources */
1562 char path
[MAX_PATH
];
1564 if (find_albumart(track_id3
, path
, sizeof(path
),
1565 &albumart_slots
[i
].dim
))
1567 user_data
.embedded_albumart
= NULL
;
1568 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1572 #ifdef HAVE_IO_PRIORITY
1573 buf_back_off_storage(false);
1575 if (hid
== ERR_BUFFER_FULL
)
1577 logf("buffer is full for now (%s)", __func__
);
1582 /* If error other than a full buffer, then mark it "unsupported"
1583 to avoid reloading attempt */
1586 logf("Album art loading failed");
1587 hid
= ERR_UNSUPPORTED_TYPE
;
1596 #endif /* HAVE_ALBUMART */
1598 #ifdef HAVE_CODEC_BUFFERING
1599 /* Load a codec for the file onto the buffer - assumes we're working from the
1600 currently loading track - not called for the current track */
1601 static bool audio_buffer_codec(struct track_info
*track_info
,
1602 struct mp3entry
*track_id3
)
1604 /* This will not be the current track -> it cannot be the first and the
1605 current track cannot be ahead of buffering -> there is a previous
1606 track entry which is either current or ahead of the current */
1607 struct track_info
*prev_info
= track_list_last(-1);
1608 struct mp3entry
*prev_id3
= bufgetid3(prev_info
->id3_hid
);
1610 /* If the previous codec is the same as this one, there is no need to
1611 put another copy of it on the file buffer (in other words, only
1612 buffer codecs at format transitions) */
1615 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1616 int prev_codt
= get_audio_base_codec_type(prev_id3
->codectype
);
1618 if (codt
== prev_codt
)
1620 logf("Reusing prev. codec: %d", prev_id3
->codectype
);
1624 /* else just load it (harmless) */
1626 /* Load the codec onto the buffer if possible */
1627 const char *codec_fn
= get_codec_filename(track_id3
->codectype
);
1631 char codec_path
[MAX_PATH
+1]; /* Full path to codec */
1632 codec_get_full_path(codec_path
, codec_fn
);
1634 track_info
->codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1636 if (track_info
->codec_hid
>= 0)
1638 logf("Buffered codec: %d", afmt
);
1644 #endif /* HAVE_CODEC_BUFFERING */
1646 /* Load metadata for the next track (with bufopen). The rest of the track
1647 loading will be handled by audio_finish_load_track once the metadata has
1648 been actually loaded by the buffering thread.
1650 Each track is arranged in the buffer as follows:
1651 <id3|[cuesheet|][album art|][codec|]audio>
1653 The next will not be loaded until the previous succeeds if the buffer was
1654 full at the time. To put any metadata after audio would make those handles
1657 static int audio_load_track(void)
1659 if (in_progress_id3_hid
>= 0)
1661 /* There must be an info pointer if the in-progress id3 is even there */
1662 struct track_info
*info
= track_list_last(0);
1664 if (info
->id3_hid
== in_progress_id3_hid
)
1666 if (filling
== STATE_FILLING
)
1668 /* Haven't finished the metadata but the notification is
1669 anticipated to come soon */
1670 logf("%s(): in progress ok: %d". __func__
, info
->id3_hid
);
1671 return LOAD_TRACK_OK
;
1673 else if (filling
== STATE_FULL
)
1675 /* Buffer was full trying to complete the load after the
1676 metadata finished, so attempt to continue - older handles
1677 should have been cleared already */
1678 logf("%s(): finishing load: %d". __func__
, info
->id3_hid
);
1679 filling
= STATE_FILLING
;
1680 buffer_event_finished_callback(&info
->id3_hid
);
1681 return LOAD_TRACK_OK
;
1685 /* Some old, stray buffering message */
1686 logf("%s(): already in progress: %d". __func__
, info
->id3_hid
);
1687 return LOAD_TRACK_ERR_BUSY
;
1690 filling
= STATE_FILLING
;
1692 struct track_info
*info
= track_list_alloc_track();
1695 /* List is full so stop buffering tracks - however, attempt to obtain
1696 metadata as the unbuffered id3 */
1697 logf("No free tracks");
1698 filling
= STATE_FULL
;
1701 playlist_peek_offset
++;
1703 logf("Buffering track: s%u/c%u/e%u/p%d",
1704 track_list
.start
, track_list
.current
, track_list
.end
,
1705 playlist_peek_offset
);
1707 /* Get track name from current playlist read position */
1709 char name_buf
[MAX_PATH
+ 1];
1710 const char *trackname
;
1715 trackname
= playlist_peek(playlist_peek_offset
, name_buf
,
1721 /* Test for broken playlists by probing for the files */
1722 fd
= open(trackname
, O_RDONLY
);
1726 logf("Open failed");
1727 /* Skip invalid entry from playlist */
1728 playlist_skip_entry(NULL
, playlist_peek_offset
);
1730 /* Sync the playlist if it isn't finished */
1731 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1737 /* No track - exhausted the playlist entries */
1738 logf("End-of-playlist");
1739 id3_write_locked(UNBUFFERED_ID3
, NULL
);
1741 if (filling
!= STATE_FULL
)
1742 track_list_unalloc_track(); /* Free this entry */
1744 playlist_peek_offset
--; /* Maintain at last index */
1746 /* We can end up here after the real last track signals its completion
1747 and miss the transition to STATE_FINISHED esp. if dropping the last
1748 songs of a playlist late in their load (2nd stage) */
1749 info
= track_list_last(0);
1751 if (info
&& buf_handle_remaining(info
->audio_hid
) == 0)
1752 filling_is_finished();
1754 filling
= STATE_END_OF_PLAYLIST
;
1756 return LOAD_TRACK_ERR_NO_MORE
;
1759 /* Successfully opened the file - get track metadata */
1760 if (filling
== STATE_FULL
||
1761 (info
->id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
)) < 0)
1763 /* Buffer or track list is full */
1764 struct mp3entry
*ub_id3
;
1766 playlist_peek_offset
--;
1768 /* Load the metadata for the first unbuffered track */
1769 ub_id3
= id3_get(UNBUFFERED_ID3
);
1771 get_metadata(ub_id3
, fd
, trackname
);
1774 if (filling
!= STATE_FULL
)
1776 track_list_unalloc_track();
1777 filling
= STATE_FULL
;
1780 logf("%s: buffer is full for now (%u tracks)", __func__
,
1781 track_list_count());
1785 /* Successful load initiation */
1786 info
->filesize
= filesize(fd
);
1787 in_progress_id3_hid
= info
->id3_hid
; /* Remember what's in-progress */
1791 return LOAD_TRACK_OK
;
1794 /* Second part of the track loading: We now have the metadata available, so we
1795 can load the codec, the album art and finally the audio data.
1796 This is called on the audio thread after the buffering thread calls the
1797 buffering_handle_finished_callback callback. */
1798 static int audio_finish_load_track(struct track_info
*info
)
1800 int trackstat
= LOAD_TRACK_OK
;
1802 if (info
->id3_hid
!= in_progress_id3_hid
)
1804 /* We must not be here if not! */
1805 logf("%s: wrong track %d/%d", __func__
, info
->id3_hid
,
1806 in_progress_id3_hid
);
1807 return LOAD_TRACK_ERR_BUSY
;
1810 /* The current track for decoding (there is always one if the list is
1812 struct track_info
*cur_info
= track_list_current(0);
1813 struct mp3entry
*track_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1817 /* This is an error condition. Track cannot be played without valid
1818 metadata; skip the track. */
1819 logf("No metadata");
1820 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1821 goto audio_finish_load_track_exit
;
1824 /* Try to load a cuesheet for the track */
1825 if (!audio_load_cuesheet(info
, track_id3
))
1827 /* No space for cuesheet on buffer, not an error */
1828 filling
= STATE_FULL
;
1829 goto audio_finish_load_track_exit
;
1832 #ifdef HAVE_ALBUMART
1833 /* Try to load album art for the track */
1834 if (!audio_load_albumart(info
, track_id3
))
1836 /* No space for album art on buffer, not an error */
1837 filling
= STATE_FULL
;
1838 goto audio_finish_load_track_exit
;
1842 /* All handles available to external routines are ready - audio and codec
1843 information is private */
1845 if (info
== track_list_user_current(0))
1847 /* Send only when the track handles could not all be opened ahead of
1848 time for the user's current track - otherwise everything is ready
1849 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1850 send_event(PLAYBACK_EVENT_CUR_TRACK_READY
, id3_get(PLAYING_ID3
));
1853 #ifdef HAVE_CODEC_BUFFERING
1854 /* Try to buffer a codec for the track */
1855 if (info
!= cur_info
&& !audio_buffer_codec(info
, track_id3
))
1857 if (info
->codec_hid
== ERR_BUFFER_FULL
)
1859 /* No space for codec on buffer, not an error */
1860 filling
= STATE_FULL
;
1861 logf("buffer is full for now (%s)", __func__
);
1865 /* This is an error condition, either no codec was found, or
1866 reading the codec file failed part way through, either way,
1868 logf("No codec for: %s", track_id3
->path
);
1869 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1872 goto audio_finish_load_track_exit
;
1874 #endif /* HAVE_CODEC_BUFFERING */
1876 /** Finally, load the audio **/
1877 size_t file_offset
= 0;
1878 track_id3
->elapsed
= 0;
1880 if (track_id3
->offset
>= info
->filesize
)
1881 track_id3
->offset
= 0;
1883 logf("%s: set offset for %s to %lu\n", __func__
,
1884 id3
->title
, (unsigned long)offset
);
1886 /* Adjust for resume rewind so we know what to buffer - starting the codec
1887 calls it again, so we don't save it (and they shouldn't accumulate) */
1888 size_t offset
= resume_rewind_adjusted_offset(track_id3
);
1890 enum data_type audiotype
= get_audio_base_data_type(track_id3
->codectype
);
1892 if (audiotype
== TYPE_ATOMIC_AUDIO
)
1893 logf("Loading atomic %d", track_id3
->codectype
);
1895 if (format_buffers_with_offset(track_id3
->codectype
))
1897 /* This format can begin buffering from any point */
1898 file_offset
= offset
;
1901 logf("load track: %s", track_id3
->path
);
1903 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1905 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1906 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1910 /* No offset given or it is very minimal - begin at the first frame
1911 according to the metadata */
1912 file_offset
= track_id3
->first_frame_offset
;
1915 int hid
= bufopen(track_id3
->path
, file_offset
, audiotype
, NULL
);
1919 info
->audio_hid
= hid
;
1921 if (info
== cur_info
)
1923 /* This is the current track to decode - should be started now */
1924 trackstat
= LOAD_TRACK_READY
;
1929 /* Buffer could be full but not properly so if this is the only
1931 if (hid
== ERR_BUFFER_FULL
&& audio_track_count() > 1)
1933 filling
= STATE_FULL
;
1934 logf("Buffer is full for now (%s)", __func__
);
1938 /* Nothing to play if no audio handle - skip this */
1939 logf("Could not add audio data handle");
1940 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1944 audio_finish_load_track_exit
:
1945 if (trackstat
< LOAD_TRACK_OK
)
1947 playlist_skip_entry(NULL
, playlist_peek_offset
);
1948 track_info_close(info
);
1949 track_list_unalloc_track();
1951 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1954 playlist_peek_offset
--;
1957 if (filling
!= STATE_FULL
)
1959 /* Load next track - error or not */
1960 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
1961 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1962 audio_queue_post(Q_AUDIO_FILL_BUFFER
, 0);
1967 trackstat
= LOAD_TRACK_ERR_FINISH_FULL
;
1973 /* Start a new track load */
1974 static int audio_fill_file_buffer(void)
1976 if (play_status
== PLAY_STOPPED
)
1977 return LOAD_TRACK_ERR_FAILED
;
1979 trigger_cpu_boost();
1981 /* Must reset the buffer before use if trashed or voice only - voice
1982 file size shouldn't have changed so we can go straight from
1983 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1984 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1985 audio_reset_buffer();
1987 logf("Starting buffer fill");
1989 int trackstat
= audio_load_track();
1991 if (trackstat
>= LOAD_TRACK_OK
)
1993 if (track_list_current(0) == track_list_user_current(0))
1996 if (filling
== STATE_FULL
&& !track_list_user_current(1))
1998 /* There are no user tracks on the buffer after this therefore
1999 this is the next track */
2000 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3
));
2007 /* Discard unwanted tracks and start refill from after the specified playlist
2009 static int audio_reset_and_rebuffer(
2010 enum track_clear_action action
, int peek_offset
)
2012 logf("Forcing rebuffer: 0x%X, %d", flags
, peek_offset
);
2014 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2016 /* Remove unwanted tracks - caller must have ensured codec isn't using
2018 track_list_clear(action
);
2020 /* Refill at specified position (-1 starts at index offset 0) */
2021 playlist_peek_offset
= peek_offset
;
2023 /* Fill the buffer */
2024 return audio_fill_file_buffer();
2027 /* Handle buffering events
2028 (Q_AUDIO_BUFFERING) */
2029 static void audio_on_buffering(int event
)
2031 enum track_clear_action action
;
2034 if (track_list_empty())
2039 case BUFFER_EVENT_BUFFER_LOW
:
2040 if (filling
!= STATE_FULL
&& filling
!= STATE_END_OF_PLAYLIST
)
2041 return; /* Should be nothing left to fill */
2043 /* Clear old tracks and continue buffering where it left off */
2044 action
= TRACK_LIST_KEEP_NEW
;
2045 peek_offset
= playlist_peek_offset
;
2048 case BUFFER_EVENT_REBUFFER
:
2049 /* Remove all but the currently decoding track and redo buffering
2051 action
= TRACK_LIST_KEEP_CURRENT
;
2052 peek_offset
= (skip_pending
== TRACK_SKIP_AUTO
) ? 1 : 0;
2059 switch (skip_pending
)
2061 case TRACK_SKIP_NONE
:
2062 case TRACK_SKIP_AUTO
:
2063 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2064 audio_reset_and_rebuffer(action
, peek_offset
);
2067 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2068 /* Already finished */
2073 logf("Buffering call, inv. state: %d", (int)skip_pending
);
2077 /* Handle starting the next track load
2078 (Q_AUDIO_FILL_BUFFER) */
2079 static void audio_on_fill_buffer(void)
2081 audio_handle_track_load_status(audio_fill_file_buffer());
2084 /* Handle posted load track finish event
2085 (Q_AUDIO_FINISH_LOAD_TRACK) */
2086 static void audio_on_finish_load_track(int id3_hid
)
2088 struct track_info
*info
= track_list_last(0);
2090 if (!info
|| !buf_is_handle(id3_hid
))
2093 if (info
== track_list_user_current(1))
2095 /* Just loaded the metadata right after the current position */
2096 audio_update_and_announce_next_track(bufgetid3(info
->id3_hid
));
2099 if (audio_finish_load_track(info
) != LOAD_TRACK_READY
)
2100 return; /* Not current track */
2102 bool is_user_current
= info
== track_list_user_current(0);
2104 if (is_user_current
)
2107 buf_read_cuesheet(info
->cuesheet_hid
);
2110 if (audio_start_codec(automatic_skip
))
2112 if (is_user_current
)
2114 /* Be sure all tagtree info is synchronized; it will be needed for the
2115 track finish event - the sync will happen when finalizing a track
2117 bool was_valid
= valid_mp3entry(id3_get(PLAYING_ID3
));
2119 playing_id3_sync(info
, -1);
2123 /* Playing id3 hadn't been updated yet because no valid track
2124 was yet available - treat like the first track */
2125 audio_playlist_track_change();
2131 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2135 /* Called when handles other than metadata handles have finished buffering
2136 (Q_AUDIO_HANDLE_FINISHED) */
2137 static void audio_on_handle_finished(int hid
)
2139 /* Right now, only audio handles should end up calling this */
2140 if (filling
== STATE_END_OF_PLAYLIST
)
2142 struct track_info
*info
= track_list_last(0);
2144 /* Really we don't know which order the handles will actually complete
2145 to zero bytes remaining since another thread is doing it - be sure
2146 it's the right one */
2147 if (info
&& info
->audio_hid
== hid
)
2149 /* This was the last track in the playlist and we now have all the
2151 filling_is_finished();
2156 /* Called to make an outstanding track skip the current track and to send the
2157 transition events */
2158 static void audio_finalise_track_change(void)
2160 switch (skip_pending
)
2162 case TRACK_SKIP_NONE
: /* Manual skip */
2165 case TRACK_SKIP_AUTO
:
2166 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2168 int playlist_delta
= skip_pending
== TRACK_SKIP_AUTO
? 1 : 0;
2169 audio_playlist_track_finish();
2171 if (!playlist_peek(playlist_delta
, NULL
, 0))
2173 /* Track ended up rejected - push things ahead like the codec blew
2174 it (because it was never started and now we're here where it
2175 should have been decoding the next track by now) - next, a
2176 directory change or end of playback will most likely happen */
2177 skip_pending
= TRACK_SKIP_NONE
;
2178 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2182 if (!playlist_delta
)
2185 playlist_peek_offset
-= playlist_delta
;
2186 if (playlist_next(playlist_delta
) >= 0)
2188 /* What!? Disappear? Hopeless bleak despair */
2191 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2192 default: /* Invalid */
2193 filling
= STATE_ENDED
;
2194 audio_stop_playback();
2198 struct track_info
*info
= track_list_current(0);
2199 struct mp3entry
*track_id3
= NULL
;
2203 /* Update the current cuesheet if any and enabled */
2206 buf_read_cuesheet(info
->cuesheet_hid
);
2207 track_id3
= bufgetid3(info
->id3_hid
);
2210 id3_write(PLAYING_ID3
, track_id3
);
2212 /* The skip is technically over */
2213 skip_pending
= TRACK_SKIP_NONE
;
2215 /* Sync the next track information */
2216 info
= track_list_current(1);
2218 id3_write(NEXTTRACK_ID3
, info
? bufgetid3(info
->id3_hid
) :
2219 id3_get(UNBUFFERED_ID3
));
2223 audio_playlist_track_change();
2226 /* Actually begin a transition and take care of the codec change - may complete
2227 it now or ask pcmbuf for notification depending on the type */
2228 static void audio_begin_track_change(enum pcm_track_change_type type
,
2231 /* Even if the new track is bad, the old track must be finished off */
2232 pcmbuf_start_track_change(type
);
2234 bool auto_skip
= type
!= TRACK_CHANGE_MANUAL
;
2238 /* Manual track change happens now */
2239 audio_finalise_track_change();
2240 pcmbuf_sync_position_update();
2242 if (play_status
== PLAY_STOPPED
)
2243 return; /* Stopped us */
2246 if (trackstat
>= LOAD_TRACK_OK
)
2248 struct track_info
*info
= track_list_current(0);
2250 if (info
->audio_hid
< 0)
2253 /* Everything needed for the codec is ready - start it */
2254 if (audio_start_codec(auto_skip
))
2257 playing_id3_sync(info
, -1);
2261 trackstat
= LOAD_TRACK_ERR_START_CODEC
;
2264 audio_handle_track_load_status(trackstat
);
2267 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2268 static void audio_monitor_end_of_playlist(void)
2270 skip_pending
= TRACK_SKIP_AUTO_END_PLAYLIST
;
2271 filling
= STATE_ENDING
;
2272 pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA
);
2275 /* Codec has completed decoding the track
2276 (usually Q_AUDIO_CODEC_COMPLETE) */
2277 static void audio_on_codec_complete(int status
)
2279 logf("%s(%d)", __func__
, status
);
2281 if (play_status
== PLAY_STOPPED
)
2284 /* If it didn't notify us first, don't expect "seek complete" message
2285 since the codec can't post it now - do things like it would have
2287 audio_complete_codec_seek();
2289 if (play_status
== PLAY_PAUSED
|| skip_pending
!= TRACK_SKIP_NONE
)
2291 /* Old-hay on the ip-skay - codec has completed decoding
2293 Paused: We're not sounding it, so just remember that it happened
2294 and the resume will begin the transition
2296 Skipping: There was already a skip in progress, remember it and
2297 allow no further progress until the PCM from the previous
2300 codec_skip_pending
= true;
2301 codec_skip_status
= status
;
2305 codec_skip_pending
= false;
2307 int trackstat
= LOAD_TRACK_OK
;
2309 automatic_skip
= true;
2310 skip_pending
= TRACK_SKIP_AUTO
;
2312 /* Does this track have an entry allocated? */
2313 struct track_info
*info
= track_list_advance_current(1);
2315 if (!info
|| info
->audio_hid
< 0)
2317 bool end_of_playlist
= false;
2321 /* Track load is not complete - it might have stopped on a
2322 full buffer without reaching the audio handle or we just
2325 If this type is atomic and we couldn't get the audio,
2326 perhaps it would need to wrap to make the allocation and
2327 handles are in the way - to maximize the liklihood it can
2328 be allocated, clear all handles to reset the buffer and
2329 its indexes to 0 - for packet audio, this should not be an
2330 issue and a pointless full reload of all the track's
2331 metadata may be avoided */
2333 struct mp3entry
*track_id3
= bufgetid3(info
->id3_hid
);
2336 get_audio_base_data_type(track_id3
->codectype
)
2337 == TYPE_PACKET_AUDIO
)
2339 /* Continue filling after this track */
2340 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT
, 1);
2341 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2344 /* else rebuffer at this track; status applies to the track we
2347 else if (!playlist_peek(1, NULL
, 0))
2349 /* Play sequence is complete - directory change or other playlist
2350 resequencing - the playlist must now be advanced in order to
2351 continue since a peek ahead to the next track is not possible */
2352 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2353 end_of_playlist
= playlist_next(1) < 0;
2356 if (!end_of_playlist
)
2358 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
,
2359 skip_pending
== TRACK_SKIP_AUTO
? 0 : -1);
2361 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2363 /* Failed to find anything after all - do playlist switchover
2365 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2366 end_of_playlist
= playlist_next(1) < 0;
2370 if (end_of_playlist
)
2372 audio_monitor_end_of_playlist();
2377 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2380 /* Called when codec completes seek operation
2381 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2382 static void audio_on_codec_seek_complete(void)
2384 logf("%s()", __func__
);
2385 audio_complete_codec_seek();
2389 /* Called when PCM track change has completed
2390 (Q_AUDIO_TRACK_CHANGED) */
2391 static void audio_on_track_changed(void)
2393 /* Finish whatever is pending so that the WPS is in sync */
2394 audio_finalise_track_change();
2396 if (codec_skip_pending
)
2398 /* Codec got ahead completing a short track - complete the
2399 codec's skip and begin the next */
2400 codec_skip_pending
= false;
2401 audio_on_codec_complete(codec_skip_status
);
2405 /* Begin playback from an idle state, transition to a new playlist or
2406 invalidate the buffer and resume (if playing).
2407 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2408 static void audio_start_playback(size_t offset
, unsigned int flags
)
2410 enum play_status old_status
= play_status
;
2412 if (flags
& AUDIO_START_NEWBUF
)
2414 /* Mark the buffer dirty - if not playing, it will be reset next
2416 if (buffer_state
== AUDIOBUF_STATE_INITIALIZED
)
2417 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
2420 if (old_status
!= PLAY_STOPPED
)
2422 logf("%s(%lu): skipping", __func__
, (unsigned long)offset
);
2424 halt_decoding_track(true);
2426 automatic_skip
= false;
2429 if (flags
& AUDIO_START_RESTART
)
2431 /* Clear out some stuff to resume the current track where it
2434 offset
= id3_get(PLAYING_ID3
)->offset
;
2435 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2439 /* This is more-or-less treated as manual track transition */
2440 /* Save resume information for current track */
2441 audio_playlist_track_finish();
2442 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2444 /* Indicate manual track change */
2445 pcmbuf_start_track_change(TRACK_CHANGE_MANUAL
);
2446 wipe_track_metadata(true);
2449 /* Set after track finish event in case skip was in progress */
2450 skip_pending
= TRACK_SKIP_NONE
;
2454 if (flags
& AUDIO_START_RESTART
)
2455 return; /* Must already be playing */
2457 /* Cold playback start from a stopped state */
2458 logf("%s(%lu): starting", __func__
, offset
);
2460 /* Set audio parameters */
2461 #if INPUT_SRC_CAPS != 0
2462 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
2463 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
2465 #ifndef PLATFORM_HAS_VOLUME_CHANGE
2466 sound_set_volume(global_settings
.volume
);
2468 /* Be sure channel is audible */
2469 pcmbuf_fade(false, true);
2471 /* Update our state */
2472 play_status
= PLAY_PLAYING
;
2475 /* Codec's position should be available as soon as it knows it */
2476 position_key
= pcmbuf_get_position_key();
2477 pcmbuf_sync_position_update();
2479 /* Start fill from beginning of playlist */
2480 playlist_peek_offset
= -1;
2481 buf_set_base_handle(-1);
2483 /* Officially playing */
2484 queue_reply(&audio_queue
, 1);
2486 /* Add these now - finish event for the first id3 will most likely be sent
2488 add_event(BUFFER_EVENT_REBUFFER
, false, buffer_event_rebuffer_callback
);
2489 add_event(BUFFER_EVENT_FINISHED
, false, buffer_event_finished_callback
);
2491 if (old_status
== PLAY_STOPPED
)
2493 /* Send coldstart event */
2494 send_event(PLAYBACK_EVENT_START_PLAYBACK
, NULL
);
2497 /* Fill the buffer */
2498 int trackstat
= audio_fill_file_buffer();
2500 if (trackstat
>= LOAD_TRACK_OK
)
2502 /* This is the currently playing track - get metadata, stat */
2503 playing_id3_sync(track_list_current(0), offset
);
2505 if (valid_mp3entry(id3_get(PLAYING_ID3
)))
2507 /* Only if actually changing tracks... */
2508 if (!(flags
& AUDIO_START_RESTART
))
2509 audio_playlist_track_change();
2514 /* Found nothing playable */
2515 audio_handle_track_load_status(trackstat
);
2519 /* Stop playback and enter an idle state
2520 (usually Q_AUDIO_STOP) */
2521 static void audio_stop_playback(void)
2523 logf("%s()", __func__
);
2525 if (play_status
== PLAY_STOPPED
)
2528 bool do_fade
= global_settings
.fade_on_stop
&& filling
!= STATE_ENDED
;
2530 pcmbuf_fade(do_fade
, false);
2532 /* Wait for fade-out */
2533 audio_wait_fade_complete();
2535 /* Stop the codec and unload it */
2536 halt_decoding_track(true);
2540 /* Save resume information - "filling" might have been set to
2541 "STATE_ENDED" by caller in order to facilitate end of playlist */
2542 audio_playlist_track_finish();
2544 skip_pending
= TRACK_SKIP_NONE
;
2545 automatic_skip
= false;
2547 /* Close all tracks and mark them NULL */
2548 remove_event(BUFFER_EVENT_REBUFFER
, buffer_event_rebuffer_callback
);
2549 remove_event(BUFFER_EVENT_FINISHED
, buffer_event_finished_callback
);
2550 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffer_event_buffer_low_callback
);
2552 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2554 /* Update our state */
2556 play_status
= PLAY_STOPPED
;
2558 wipe_track_metadata(true);
2561 filling
= STATE_IDLE
;
2565 /* Pause the playback of the current track
2567 static void audio_on_pause(bool pause
)
2569 logf("%s(%s)", __func__
, pause
? "true" : "false");
2571 if (play_status
== PLAY_STOPPED
|| pause
== (play_status
== PLAY_PAUSED
))
2574 play_status
= pause
? PLAY_PAUSED
: PLAY_PLAYING
;
2576 if (!pause
&& codec_skip_pending
)
2578 /* Actually do the skip that is due - resets the status flag */
2579 audio_on_codec_complete(codec_skip_status
);
2582 bool do_fade
= global_settings
.fade_on_stop
;
2584 pcmbuf_fade(do_fade
, !pause
);
2586 if (!ff_rw_mode
&& !(do_fade
&& pause
))
2588 /* Not in ff/rw mode - can actually change the audio state now */
2589 pcmbuf_pause(pause
);
2593 /* Skip a certain number of tracks forwards or backwards
2595 static void audio_on_skip(void)
2599 /* Eat the delta to keep it synced, even if not playing */
2600 int toskip
= skip_offset
;
2603 logf("%s(): %d", __func__
, toskip
);
2607 if (play_status
== PLAY_STOPPED
)
2610 /* Force codec to abort this track */
2611 halt_decoding_track(true);
2613 /* Kill the ff/rw halt */
2617 automatic_skip
= false;
2619 /* If there was an auto skip in progress, there will be residual
2620 advancement of the playlist and/or track list so compensation will be
2621 required in order to end up in the right spot */
2622 int track_list_delta
= toskip
;
2623 int playlist_delta
= toskip
;
2625 if (skip_pending
!= TRACK_SKIP_NONE
)
2627 if (skip_pending
!= TRACK_SKIP_AUTO_END_PLAYLIST
)
2630 if (skip_pending
== TRACK_SKIP_AUTO_NEW_PLAYLIST
)
2634 audio_playlist_track_finish();
2635 skip_pending
= TRACK_SKIP_NONE
;
2637 /* Update the playlist current track now */
2638 while (playlist_next(playlist_delta
) < 0)
2640 /* Manual skip out of range (because the playlist wasn't updated
2641 yet by us and so the check in audio_skip returned 'ok') - bring
2643 int d
= toskip
< 0 ? 1 : -1;
2645 while (!playlist_check(playlist_delta
))
2647 if (playlist_delta
== d
)
2649 /* Had to move the opposite direction to correct, which is
2650 wrong - this is the end */
2651 filling
= STATE_ENDED
;
2652 audio_stop_playback();
2656 playlist_delta
+= d
;
2657 track_list_delta
+= d
;
2661 /* Adjust things by how much the playlist was manually moved */
2662 playlist_peek_offset
-= playlist_delta
;
2664 struct track_info
*info
= track_list_advance_current(track_list_delta
);
2665 int trackstat
= LOAD_TRACK_OK
;
2667 if (!info
|| info
->audio_hid
< 0)
2669 /* We don't know the next track thus we know we don't have it */
2670 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2673 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2676 /* Skip to the next/previous directory
2677 (Q_AUDIO_DIR_SKIP) */
2678 static void audio_on_dir_skip(int direction
)
2680 logf("%s(%d)", __func__
, direction
);
2686 if (play_status
== PLAY_STOPPED
)
2689 /* Force codec to abort this track */
2690 halt_decoding_track(true);
2692 /* Kill the ff/rw halt */
2696 automatic_skip
= false;
2698 audio_playlist_track_finish();
2700 /* Unless automatic and gapless, skips do not pend */
2701 skip_pending
= TRACK_SKIP_NONE
;
2703 /* Regardless of the return value we need to rebuffer. If it fails the old
2704 playlist will resume, else the next dir will start playing. */
2705 playlist_next_dir(direction
);
2707 wipe_track_metadata(false);
2709 int trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2711 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2713 /* The day the music died - finish-off whatever is playing and call it
2715 audio_monitor_end_of_playlist();
2719 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2722 /* Enter seek mode in order to start a seek
2723 (Q_AUDIO_PRE_FF_REWIND) */
2724 static void audio_on_pre_ff_rewind(void)
2726 logf("%s()", __func__
);
2728 if (play_status
== PLAY_STOPPED
|| ff_rw_mode
)
2733 audio_wait_fade_complete();
2735 if (play_status
== PLAY_PAUSED
)
2741 /* Seek the playback of the current track to the specified time
2742 (Q_AUDIO_FF_REWIND) */
2743 static void audio_on_ff_rewind(long time
)
2745 logf("%s(%ld)", __func__
, time
);
2747 if (play_status
== PLAY_STOPPED
)
2750 enum track_skip_type pending
= skip_pending
;
2754 case TRACK_SKIP_NONE
: /* The usual case */
2755 case TRACK_SKIP_AUTO
: /* Have to back it out (fun!) */
2756 case TRACK_SKIP_AUTO_END_PLAYLIST
: /* Still have the last codec used */
2758 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
2759 struct mp3entry
*ci_id3
= id3_get(CODEC_ID3
);
2761 automatic_skip
= false;
2763 /* Send event before clobbering the time */
2764 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2765 then skipping back to this track resumes properly. Something else
2766 should be sent. We're not _really_ finishing the track are we? */
2768 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
2770 id3
->elapsed
= time
;
2771 queue_reply(&audio_queue
, 1);
2773 bool haltres
= halt_decoding_track(pending
== TRACK_SKIP_AUTO
);
2775 /* Need this set in case ff/rw mode + error but _after_ the codec
2776 halt that will reset it */
2777 codec_seeking
= true;
2779 /* If in transition, key will have changed - sync to it */
2780 position_key
= pcmbuf_get_position_key();
2782 if (pending
== TRACK_SKIP_AUTO
)
2784 if (!track_list_advance_current(-1))
2786 /* Not in list - must rebuffer at the current playlist index */
2787 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1)
2790 /* Codec is stopped */
2796 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2797 rebuffer is needed */
2798 skip_pending
= TRACK_SKIP_NONE
;
2799 struct track_info
*cur_info
= track_list_current(0);
2801 /* Track must complete the loading _now_ since a codec and audio
2802 handle are needed in order to do the seek */
2803 if (cur_info
->audio_hid
< 0 &&
2804 audio_finish_load_track(cur_info
) != LOAD_TRACK_READY
)
2806 /* Call above should push any load sequence - no need for
2807 halt_decoding_track here if no skip was pending here because
2808 there would not be a codec started if no audio handle was yet
2813 if (pending
== TRACK_SKIP_AUTO
)
2815 if (!bufreadid3(cur_info
->id3_hid
, ci_id3
) ||
2816 !audio_init_codec(cur_info
, ci_id3
))
2818 /* We should have still been able to get it - skip it and move
2819 onto the next one - like it or not this track is broken */
2823 /* Set the codec API to the correct metadata and track info */
2824 ci
.audio_hid
= cur_info
->audio_hid
;
2825 ci
.filesize
= cur_info
->filesize
;
2826 buf_set_base_handle(cur_info
->audio_hid
);
2831 /* If codec must be (re)started, reset the offset */
2839 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2841 /* We cannot do this because the playlist must be reversed by one
2842 and it doesn't always return the same song when going backwards
2843 across boundaries as forwards (either because of randomization
2844 or inconsistency in deciding what the previous track should be),
2845 therefore the whole operation would often end up as nonsense -
2846 lock out seeking for a couple seconds */
2848 /* Sure as heck cancel seek mode too! */
2849 audio_ff_rewind_end();
2854 /* Won't see this */
2858 if (play_status
== PLAY_STOPPED
)
2860 /* Playback ended because of an error completing a track load */
2864 /* Always fake it as a codec start error which will handle mode
2865 cancellations and skip to the next track */
2866 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2869 /* Invalidates all but currently playing track
2871 static void audio_on_audio_flush(void)
2873 logf("%s", __func__
);
2875 if (track_list_empty())
2876 return; /* Nothing to flush out */
2878 switch (skip_pending
)
2880 case TRACK_SKIP_NONE
:
2881 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2882 /* Remove all but the currently playing track from the list and
2883 refill after that */
2884 track_list_clear(TRACK_LIST_KEEP_CURRENT
);
2885 playlist_peek_offset
= 0;
2886 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2887 audio_update_and_announce_next_track(NULL
);
2889 /* Ignore return since it's about the next track, not this one */
2890 audio_fill_file_buffer();
2892 if (skip_pending
== TRACK_SKIP_NONE
)
2895 /* There's now a track after this one now - convert to auto skip -
2896 no skip should pend right now because multiple flush messages can
2897 be fired which would cause a restart in the below cases */
2898 skip_pending
= TRACK_SKIP_NONE
;
2899 audio_clear_track_notifications();
2900 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_OK
);
2903 case TRACK_SKIP_AUTO
:
2904 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2905 /* Precisely removing what it already decoded for the next track is
2906 not possible so a restart is required in order to continue the
2907 currently playing track without the now invalid future track
2909 audio_start_playback(0, AUDIO_START_RESTART
);
2912 default: /* Nothing else is a state */
2917 #ifdef AUDIO_HAVE_RECORDING
2918 /* Load the requested encoder type
2919 (Q_AUDIO_LOAD_ENCODER) */
2920 static void audio_on_load_encoder(int afmt
)
2924 if (play_status
!= PLAY_STOPPED
)
2925 audio_stop_playback(); /* Can't load both types at once */
2927 codec_unload(); /* Encoder still loaded, stop and unload it */
2929 if (afmt
!= AFMT_UNKNOWN
)
2931 res
= codec_load(-1, afmt
| CODEC_TYPE_ENCODER
);
2933 codec_go(); /* These are run immediately */
2936 queue_reply(&audio_queue
, res
);
2938 #endif /* AUDIO_HAVE_RECORDING */
2940 static void audio_thread(void)
2942 struct queue_event ev
;
2952 case STATE_END_OF_PLAYLIST
:
2953 if (buf_get_watermark() == 0)
2955 /* End of buffering for now, let's calculate the watermark,
2956 register for a low buffer event and unboost */
2957 audio_update_filebuf_watermark(0);
2958 add_event(BUFFER_EVENT_BUFFER_LOW
, true,
2959 buffer_event_buffer_low_callback
);
2962 case STATE_FINISHED
:
2963 /* All data was buffered */
2968 if (audio_pcmbuf_track_change_scan())
2970 /* Transfer notification to audio queue event */
2971 ev
.id
= Q_AUDIO_TRACK_CHANGED
;
2976 /* If doing auto skip, poll pcmbuf track notifications a bit
2977 faster to promply detect the transition */
2978 queue_wait_w_tmo(&audio_queue
, &ev
,
2979 skip_pending
== TRACK_SKIP_NONE
?
2986 queue_wait(&audio_queue
, &ev
);
2988 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2991 #ifdef AUDIO_HAVE_RECORDING
2992 /* Must monitor the encoder message for recording so it can remove
2993 it if we process the insertion before it does. It cannot simply
2994 be removed from under recording however. */
2995 case Q_AUDIO_LOAD_ENCODER
:
2998 case SYS_USB_DISCONNECTED
:
2999 filling
= STATE_IDLE
;
3003 if (filling
== STATE_USB
)
3006 #endif /* CONFIG_PLATFORM */
3011 /** Codec and track change messages **/
3012 case Q_AUDIO_CODEC_COMPLETE
:
3013 /* Codec is done processing track and has gone idle */
3014 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev
.data
);
3015 audio_on_codec_complete(ev
.data
);
3018 case Q_AUDIO_CODEC_SEEK_COMPLETE
:
3019 /* Codec is done seeking */
3020 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
3021 audio_on_codec_seek_complete();
3024 case Q_AUDIO_TRACK_CHANGED
:
3025 /* PCM track change done */
3026 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3027 audio_on_track_changed();
3030 /** Control messages **/
3032 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3033 audio_start_playback(ev
.data
, 0);
3037 LOGFQUEUE("audio < Q_AUDIO_STOP");
3038 audio_stop_playback();
3040 queue_clear(&audio_queue
);
3044 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3045 audio_on_pause(ev
.data
);
3049 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3053 case Q_AUDIO_DIR_SKIP
:
3054 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3055 audio_on_dir_skip(ev
.data
);
3058 case Q_AUDIO_PRE_FF_REWIND
:
3059 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3060 audio_on_pre_ff_rewind();
3063 case Q_AUDIO_FF_REWIND
:
3064 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3065 audio_on_ff_rewind(ev
.data
);
3069 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev
.data
);
3070 audio_on_audio_flush();
3073 /** Buffering messages **/
3074 case Q_AUDIO_BUFFERING
:
3075 /* some buffering event */
3076 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev
.data
);
3077 audio_on_buffering(ev
.data
);
3080 case Q_AUDIO_FILL_BUFFER
:
3081 /* continue buffering next track */
3082 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3083 audio_on_fill_buffer();
3086 case Q_AUDIO_FINISH_LOAD_TRACK
:
3087 /* metadata is buffered */
3088 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3089 audio_on_finish_load_track(ev
.data
);
3092 case Q_AUDIO_HANDLE_FINISHED
:
3093 /* some other type is buffered */
3094 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3095 audio_on_handle_finished(ev
.data
);
3098 /** Miscellaneous messages **/
3099 case Q_AUDIO_REMAKE_AUDIO_BUFFER
:
3100 /* buffer needs to be reinitialized */
3101 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3102 audio_start_playback(0, AUDIO_START_RESTART
| AUDIO_START_NEWBUF
);
3105 #ifdef HAVE_DISK_STORAGE
3106 case Q_AUDIO_UPDATE_WATERMARK
:
3107 /* buffering watermark needs updating */
3108 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev
.data
);
3109 audio_update_filebuf_watermark(ev
.data
);
3111 #endif /* HAVE_DISK_STORAGE */
3113 #ifdef AUDIO_HAVE_RECORDING
3114 case Q_AUDIO_LOAD_ENCODER
:
3115 /* load an encoder for recording */
3116 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev
.data
);
3117 audio_on_load_encoder(ev
.data
);
3119 #endif /* AUDIO_HAVE_RECORDING */
3121 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3122 case SYS_USB_CONNECTED
:
3123 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3124 audio_stop_playback();
3125 #ifdef PLAYBACK_VOICE
3128 filling
= STATE_USB
;
3129 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3131 #endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */
3134 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3138 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3145 /* --- Buffering callbacks --- */
3147 /* Called when fullness is below the watermark level */
3148 static void buffer_event_buffer_low_callback(void *data
)
3150 logf("low buffer callback");
3151 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3152 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_BUFFER_LOW
);
3156 /* Called when handles must be discarded in order to buffer new data */
3157 static void buffer_event_rebuffer_callback(void *data
)
3159 logf("rebuffer callback");
3160 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3161 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_REBUFFER
);
3165 /* A handle has completed buffering and all required data is available */
3166 static void buffer_event_finished_callback(void *data
)
3168 int hid
= *(const int *)data
;
3169 const enum data_type htype
= buf_handle_data_type(hid
);
3171 logf("handle %d finished buffering (type:%u)", hid
, (unsigned)htype
);
3173 /* Limit queue traffic */
3177 /* The metadata handle for the last loaded track has been buffered.
3178 We can ask the audio thread to load the rest of the track's data. */
3179 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid
);
3180 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK
, hid
);
3183 case TYPE_PACKET_AUDIO
:
3184 /* Strip any useless trailing tags that are left. */
3187 case TYPE_ATOMIC_AUDIO
:
3188 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid
);
3189 audio_queue_post(Q_AUDIO_HANDLE_FINISHED
, hid
);
3193 /* Don't care to know about these */
3199 /** -- Codec callbacks -- **/
3201 /* Update elapsed time for next PCM insert */
3202 void audio_codec_update_elapsed(unsigned long elapsed
)
3204 #ifdef AB_REPEAT_ENABLE
3205 ab_position_report(elapsed
);
3207 /* Save in codec's id3 where it is used at next pcm insert */
3208 id3_get(CODEC_ID3
)->elapsed
= elapsed
;
3211 /* Update offset for next PCM insert */
3212 void audio_codec_update_offset(size_t offset
)
3214 /* Save in codec's id3 where it is used at next pcm insert */
3215 id3_get(CODEC_ID3
)->offset
= offset
;
3218 /* Codec has finished running */
3219 void audio_codec_complete(int status
)
3221 #ifdef AB_REPEAT_ENABLE
3222 if (status
>= CODEC_OK
)
3224 /* Normal automatic skip */
3225 ab_end_of_track_report();
3229 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status
);
3230 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, status
);
3233 /* Codec has finished seeking */
3234 void audio_codec_seek_complete(void)
3236 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_SEEK_COMPLETE");
3237 audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE
, 0);
3241 /** --- Pcmbuf callbacks --- **/
3243 /* Update the elapsed and offset from the information cached during the
3244 PCM buffer insert */
3245 void audio_pcmbuf_position_callback(unsigned long elapsed
, off_t offset
,
3248 if (key
== position_key
)
3250 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
3251 id3
->elapsed
= elapsed
;
3252 id3
->offset
= offset
;
3256 /* Synchronize position info to the codec's */
3257 void audio_pcmbuf_sync_position(void)
3259 audio_pcmbuf_position_callback(ci
.id3
->elapsed
, ci
.id3
->offset
,
3260 pcmbuf_get_position_key());
3263 /* Post message from pcmbuf that the end of the previous track has just
3265 void audio_pcmbuf_track_change(bool pcmbuf
)
3269 /* Notify of the change in special-purpose semaphore object */
3270 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3271 audio_pcmbuf_track_change_post();
3275 /* Safe to post directly to the queue */
3276 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3277 audio_queue_post(Q_AUDIO_TRACK_CHANGED
, 0);
3281 /* May pcmbuf start PCM playback when the buffer is full enough? */
3282 bool audio_pcmbuf_may_play(void)
3284 return play_status
== PLAY_PLAYING
&& !ff_rw_mode
;
3288 /** -- External interfaces -- **/
3290 /* Return the playback and recording status */
3291 int audio_status(void)
3293 unsigned int ret
= play_status
;
3295 #ifdef AUDIO_HAVE_RECORDING
3296 /* Do this here for constitency with mpeg.c version */
3297 ret
|= pcm_rec_status();
3303 /* Clear all accumulated audio errors for playback and recording */
3304 void audio_error_clear(void)
3306 #ifdef AUDIO_HAVE_RECORDING
3307 pcm_rec_error_clear();
3311 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3312 bool audio_peek_track(struct mp3entry
*id3
, int offset
)
3314 bool retval
= false;
3318 if (play_status
!= PLAY_STOPPED
)
3320 id3
->path
[0] = '\0'; /* Null path means it should be filled now */
3321 retval
= audio_get_track_metadata(offset
+ skip_offset
, id3
) &&
3322 id3
->path
[0] != '\0';
3330 /* Return the mp3entry for the currently playing track */
3331 struct mp3entry
* audio_current_track(void)
3333 struct mp3entry
*id3
;
3337 #ifdef AUDIO_FAST_SKIP_PREVIEW
3338 if (skip_offset
!= 0)
3340 /* This is a peekahead */
3341 id3
= id3_get(PLAYING_PEEK_ID3
);
3342 audio_peek_track(id3
, 0);
3348 id3
= id3_get(PLAYING_ID3
);
3349 audio_get_track_metadata(0, id3
);
3357 /* Obtains the mp3entry for the next track from the current */
3358 struct mp3entry
* audio_next_track(void)
3360 struct mp3entry
*id3
= id3_get(NEXTTRACK_ID3
);
3364 #ifdef AUDIO_FAST_SKIP_PREVIEW
3365 if (skip_offset
!= 0)
3367 /* This is a peekahead */
3368 if (!audio_peek_track(id3
, 1))
3375 if (!audio_get_track_metadata(1, id3
))
3384 /* Start playback at the specified offset */
3385 void audio_play(long offset
)
3389 #ifdef PLAYBACK_VOICE
3390 /* Truncate any existing voice output so we don't have spelling
3391 * etc. over the first part of the played track */
3392 talk_force_shutup();
3395 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
3396 audio_queue_send(Q_AUDIO_PLAY
, offset
);
3399 /* Stop playback if playing */
3400 void audio_stop(void)
3402 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3403 audio_queue_send(Q_AUDIO_STOP
, 0);
3406 /* Pause playback if playing */
3407 void audio_pause(void)
3409 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3410 audio_queue_send(Q_AUDIO_PAUSE
, true);
3413 /* This sends a stop message and the audio thread will dump all its
3414 subsequent messages */
3415 void audio_hard_stop(void)
3418 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3419 audio_queue_send(Q_AUDIO_STOP
, 1);
3420 #ifdef PLAYBACK_VOICE
3423 if (audiobuf_handle
> 0)
3424 audiobuf_handle
= core_free(audiobuf_handle
);
3427 /* Resume playback if paused */
3428 void audio_resume(void)
3430 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3431 audio_queue_send(Q_AUDIO_PAUSE
, false);
3434 /* Skip the specified number of tracks forward or backward from the current */
3435 void audio_skip(int offset
)
3439 /* If offset has to be backed-out to stay in range, no skip is done */
3440 int accum
= skip_offset
+ offset
;
3442 while (offset
!= 0 && !playlist_check(accum
))
3444 offset
+= offset
< 0 ? 1 : -1;
3445 accum
= skip_offset
+ offset
;
3450 /* Accumulate net manual skip count since the audio thread last
3452 skip_offset
= accum
;
3454 system_sound_play(SOUND_TRACK_SKIP
);
3456 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset
);
3458 #ifdef AUDIO_FAST_SKIP_PREVIEW
3459 /* Do this before posting so that the audio thread can correct us
3460 when things settle down - additionally, if audio gets a message
3461 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3462 handler a skip event with the correct info but doesn't skip */
3463 send_event(PLAYBACK_EVENT_TRACK_SKIP
, NULL
);
3464 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3466 /* Playback only needs the final state even if more than one is
3467 processed because it wasn't removed in time */
3468 queue_remove_from_head(&audio_queue
, Q_AUDIO_SKIP
);
3469 audio_queue_post(Q_AUDIO_SKIP
, 0);
3473 /* No more tracks */
3474 system_sound_play(SOUND_TRACK_NO_MORE
);
3480 /* Skip one track forward from the current */
3481 void audio_next(void)
3486 /* Skip one track backward from the current */
3487 void audio_prev(void)
3492 /* Move one directory forward */
3493 void audio_next_dir(void)
3495 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3496 audio_queue_post(Q_AUDIO_DIR_SKIP
, 1);
3499 /* Move one directory backward */
3500 void audio_prev_dir(void)
3502 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3503 audio_queue_post(Q_AUDIO_DIR_SKIP
, -1);
3506 /* Pause playback in order to start a seek that flushes the old audio */
3507 void audio_pre_ff_rewind(void)
3509 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3510 audio_queue_post(Q_AUDIO_PRE_FF_REWIND
, 0);
3513 /* Seek to the new time in the current track */
3514 void audio_ff_rewind(long time
)
3516 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3517 audio_queue_post(Q_AUDIO_FF_REWIND
, time
);
3520 /* Clear all but the currently playing track then rebuffer */
3521 void audio_flush_and_reload_tracks(void)
3523 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3524 audio_queue_post(Q_AUDIO_FLUSH
, 0);
3527 /* Return the pointer to the main audio buffer, optionally preserving
3529 unsigned char * audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
3533 if (audio_is_initialized
)
3537 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3539 if (buffer_size
== NULL
)
3541 /* Special case for talk_init to use since it already knows it's
3543 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3547 /* make sure buffer is freed and re-allocated to simplify code below
3548 * (audio_hard_stop() likely has done that already) */
3549 if (audiobuf_handle
> 0)
3550 audiobuf_handle
= core_free(audiobuf_handle
);
3552 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
3553 buf
= core_get_data(audiobuf_handle
);
3555 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
3556 || !talk_voice_required())
3558 logf("get buffer: talk, audio");
3559 /* Ok to use everything from audiobuf - voice is loaded,
3560 the talk buffer is not needed because voice isn't being used, or
3561 could be AUDIOBUF_STATE_TRASHED already. If state is
3562 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3563 written without the caller knowing what's going on. Changing certain
3564 settings may move it to a worse condition but the memory in use by
3565 something else will remain undisturbed.
3567 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
3569 talk_buffer_steal();
3570 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3575 logf("get buffer: audio");
3576 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3577 still AUDIOBUF_STATE_INITIALIZED */
3578 /* Skip talk buffer and move pcm buffer to end to maximize available
3579 contiguous memory - no audio running means voice will not need the
3581 size_t talkbuf_size
;
3582 buf
+= talkbuf_size
= talkbuf_init(buf
);
3583 filebuflen
-= talkbuf_size
;
3584 filebuflen
-= voicebuf_init(buf
+ filebuflen
);
3586 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
3589 *buffer_size
= filebuflen
;
3593 #ifdef HAVE_RECORDING
3594 /* Stop audio, voice and obtain all available buffer space */
3595 unsigned char * audio_get_recording_buffer(size_t *buffer_size
)
3598 return audio_get_buffer(true, buffer_size
);
3600 #endif /* HAVE_RECORDING */
3602 /* Restore audio buffer to a particular state (one more valid than the current
3604 bool audio_restore_playback(int type
)
3608 case AUDIO_WANT_PLAYBACK
:
3609 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
3610 audio_reset_buffer();
3612 case AUDIO_WANT_VOICE
:
3613 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
3614 audio_reset_buffer();
3621 /* Has the playback buffer been completely claimed? */
3622 bool audio_buffer_state_trashed(void)
3624 return buffer_state
== AUDIOBUF_STATE_TRASHED
;
3628 /** --- Miscellaneous public interfaces --- **/
3630 #ifdef HAVE_ALBUMART
3631 /* Return which album art handle is current for the user in the given slot */
3632 int playback_current_aa_hid(int slot
)
3634 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3636 struct track_info
*info
= track_list_user_current(skip_offset
);
3638 if (!info
&& abs(skip_offset
) <= 1)
3640 /* Give the actual position a go */
3641 info
= track_list_user_current(0);
3645 return info
->aa_hid
[slot
];
3648 return ERR_HANDLE_NOT_FOUND
;
3651 /* Find an album art slot that doesn't match the dimensions of another that
3652 is already claimed - increment the use count if it is */
3653 int playback_claim_aa_slot(struct dim
*dim
)
3657 /* First try to find a slot already having the size to reuse it since we
3658 don't want albumart of the same size buffered multiple times */
3661 struct albumart_slot
*slot
= &albumart_slots
[i
];
3663 if (slot
->dim
.width
== dim
->width
&&
3664 slot
->dim
.height
== dim
->height
)
3671 /* Size is new, find a free slot */
3674 if (!albumart_slots
[i
].used
)
3676 albumart_slots
[i
].used
++;
3677 albumart_slots
[i
].dim
= *dim
;
3682 /* Sorry, no free slot */
3686 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3687 void playback_release_aa_slot(int slot
)
3689 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3691 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
3693 if (aa_slot
->used
> 0)
3697 #endif /* HAVE_ALBUMART */
3700 #ifdef HAVE_RECORDING
3701 /* Load an encoder and run it */
3702 bool audio_load_encoder(int afmt
)
3704 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3705 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
3706 return audio_queue_send(Q_AUDIO_LOAD_ENCODER
, afmt
) != 0;
3713 /* Stop an encoder and unload it */
3714 void audio_remove_encoder(void)
3716 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3717 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3718 audio_queue_send(Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
3721 #endif /* HAVE_RECORDING */
3723 /* Is an automatic skip in progress? If called outside transition callbacks,
3724 indicates the last skip type at the time it was processed and isn't very
3726 bool audio_automatic_skip(void)
3728 return automatic_skip
;
3731 /* Would normally calculate byte offset from an elapsed time but is not
3733 int audio_get_file_pos(void)
3738 /* Return the elapsed time of the track previous to the current */
3739 unsigned long audio_prev_elapsed(void)
3741 return prev_track_elapsed
;
3744 /* Return total file buffer length after accounting for the talk buf */
3745 size_t audio_get_filebuflen(void)
3747 return buf_length();
3750 /* How many tracks exist on the buffer - full or partial */
3751 int audio_track_count(void)
3752 __attribute__((alias("track_list_count")));
3754 /* Return total ringbuffer space occupied - ridx to widx */
3755 long audio_filebufused(void)
3761 /** -- Settings -- **/
3763 /* Enable or disable cuesheet support and allocate/don't allocate the
3764 extra associated resources */
3765 void audio_set_cuesheet(int enable
)
3767 if (play_status
== PLAY_STOPPED
|| !enable
!= !get_current_cuesheet())
3769 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3770 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3774 #ifdef HAVE_DISK_STORAGE
3775 /* Set the audio antiskip buffer margin by index */
3776 void audio_set_buffer_margin(int setting
)
3778 static const unsigned short lookup
[] =
3779 { 5, 15, 30, 60, 120, 180, 300, 600 };
3781 if ((unsigned)setting
>= ARRAYLEN(lookup
))
3784 logf("buffer margin: %u", (unsigned)lookup
[setting
]);
3786 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3787 (unsigned)lookup
[setting
]);
3788 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK
, lookup
[setting
]);
3790 #endif /* HAVE_DISK_STORAGE */
3792 #ifdef HAVE_CROSSFADE
3793 /* Take necessary steps to enable or disable the crossfade setting */
3794 void audio_set_crossfade(int enable
)
3796 /* Tell it the next setting to use */
3797 pcmbuf_request_crossfade_enable(enable
);
3799 /* Return if size hasn't changed or this is too early to determine
3800 which in the second case there's no way we could be playing
3802 if (!pcmbuf_is_same_size())
3804 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3805 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3808 #endif /* HAVE_CROSSFADE */
3811 /** -- Startup -- **/
3813 /* Initialize the audio system - called from init() in main.c */
3814 void audio_init(void)
3816 /* Can never do this twice */
3817 if (audio_is_initialized
)
3819 logf("audio: already initialized");
3823 logf("audio: initializing");
3825 /* Initialize queues before giving control elsewhere in case it likes
3826 to send messages. Thread creation will be delayed however so nothing
3827 starts running until ready if something yields such as talk_init. */
3828 queue_init(&audio_queue
, true);
3830 mutex_init(&id3_mutex
);
3834 codec_thread_init();
3836 /* This thread does buffer, so match its priority */
3837 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
3838 sizeof(audio_stack
), 0, audio_thread_name
3839 IF_PRIO(, MIN(PRIORITY_BUFFERING
, PRIORITY_USER_INTERFACE
))
3842 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
3845 #ifdef PLAYBACK_VOICE
3846 voice_thread_init();
3849 /* audio_reset_buffer must know the size of voice buffer so init
3853 #ifdef HAVE_CROSSFADE
3854 /* Set crossfade setting for next buffer init which should be about... */
3855 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
3858 /* Initialize the buffering system */
3861 /* ...now! Set up the buffers */
3862 audio_reset_buffer();
3864 /* Probably safe to say */
3865 audio_is_initialized
= true;
3867 sound_settings_apply();
3868 #ifdef HAVE_DISK_STORAGE
3869 audio_set_buffer_margin(global_settings
.buffer_margin
);