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 STATE_USB
, /* USB mode, ignore most messages */
194 } filling
= STATE_IDLE
;
196 /* Track info - holds information about each track in the buffer */
199 /* In per-track allocated order: */
200 int id3_hid
; /* Metadata handle ID */
201 int cuesheet_hid
; /* Parsed cuesheet handle ID */
203 int aa_hid
[MAX_MULTIPLE_AA
];/* Album art handle IDs */
205 #ifdef HAVE_CODEC_BUFFERING
206 int codec_hid
; /* Buffered codec handle ID */
208 int audio_hid
; /* Main audio data handle ID */
209 size_t filesize
; /* File total length on disk
210 TODO: This should be stored
212 id3 and would use less
216 /* Track list - holds info about all buffered tracks */
218 #define TRACK_LIST_LEN 128 /* Must be 2^int(+n) */
219 #elif MEMORYSIZE >= 16
220 #define TRACK_LIST_LEN 64
221 #elif MEMORYSIZE >= 8
222 #define TRACK_LIST_LEN 32
224 #define TRACK_LIST_LEN 16
227 #define TRACK_LIST_MASK (TRACK_LIST_LEN-1)
231 /* read, write and current are maintained unwrapped, limited only by the
232 unsigned int range and wrap-safe comparisons are used */
234 /* NOTE: there appears to be a bug in arm-elf-eabi-gcc 4.4.4 for ARMv4 where
235 if 'end' follows 'start' in this structure, track_list_count performs
236 'start - end' rather than 'end - start', giving negative count values...
237 so leave it this way for now! */
238 unsigned int end
; /* Next open position */
239 unsigned int start
; /* First track in list */
240 unsigned int current
; /* Currently decoding track */
241 struct track_info tracks
[TRACK_LIST_LEN
]; /* Buffered track information */
242 } track_list
; /* (A, O-) */
245 /* Playlist steps from playlist position to next track to be buffered */
246 static int playlist_peek_offset
= 0;
248 /* Metadata handle of track load in progress (meaning all handles have not
249 yet been opened for the track, id3 always exists or the track does not)
251 Tracks are keyed by their metadata handles if track list pointers are
252 insufficient to make comparisons */
253 static int in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
255 #ifdef HAVE_DISK_STORAGE
256 /* Buffer margin A.K.A. anti-skip buffer (in seconds) */
257 static size_t buffer_margin
= 5;
260 /* Values returned for track loading */
261 enum track_load_status
263 LOAD_TRACK_ERR_START_CODEC
= -6,
264 LOAD_TRACK_ERR_FINISH_FAILED
= -5,
265 LOAD_TRACK_ERR_FINISH_FULL
= -4,
266 LOAD_TRACK_ERR_BUSY
= -3,
267 LOAD_TRACK_ERR_NO_MORE
= -2,
268 LOAD_TRACK_ERR_FAILED
= -1,
270 LOAD_TRACK_READY
= 1,
273 /** Track change controls **/
275 /* What sort of skip is pending globally? */
278 /* Relative to what user is intended to see: */
279 /* Codec: +0, Track List: +0, Playlist: +0 */
280 TRACK_SKIP_NONE
= 0, /* no track skip */
281 /* Codec: +1, Track List: +1, Playlist: +0 */
282 TRACK_SKIP_AUTO
, /* codec-initiated skip */
283 /* Codec: +1, Track List: +1, Playlist: +1 */
284 TRACK_SKIP_AUTO_NEW_PLAYLIST
, /* codec-initiated skip is new playlist */
285 /* Codec: xx, Track List: +0, Playlist: +0 */
286 TRACK_SKIP_AUTO_END_PLAYLIST
, /* codec-initiated end of playlist */
287 /* Manual skip: Never pends */
288 TRACK_SKIP_MANUAL
, /* manual track skip */
289 /* Manual skip: Never pends */
290 TRACK_SKIP_DIR_CHANGE
, /* manual directory skip */
291 } skip_pending
= TRACK_SKIP_NONE
;
293 /* Note about TRACK_SKIP_AUTO_NEW_PLAYLIST:
294 Fixing playlist code to be able to peek into the first song of
295 the next playlist would fix any issues and this wouldn't need
296 to be a special case since pre-advancing the playlist would be
297 unneeded - it could be much more like TRACK_SKIP_AUTO and all
298 actions that require reversal during an in-progress transition
299 would work as expected */
301 /* Used to indicate status for the events. Must be separate to satisfy all
302 clients so the correct metadata is read when sending the change events
303 and also so that it is read correctly outside the events. */
304 static bool automatic_skip
= false; /* (A, O-) */
306 /* Pending manual track skip offset */
307 static int skip_offset
= 0; /* (A, O) */
309 /* Track change notification */
312 unsigned int in
; /* Number of pcmbuf posts (audio isr) */
313 unsigned int out
; /* Number of times audio has read the difference */
314 } track_change
= { 0, 0 };
317 /* Did the codec notify us it finished while we were paused or while still
318 in an automatic transition?
320 If paused, it is necessary to defer a codec-initiated skip until resuming
321 or else the track will move forward while not playing audio!
323 If in-progress, skips should not build-up ahead of where the WPS is when
324 really short tracks finish decoding.
326 If it is forgotten, it will be missed altogether and playback will just sit
327 there looking stupid and comatose until the user does something */
328 static bool codec_skip_pending
= false;
329 static int codec_skip_status
;
330 static bool codec_seeking
= false; /* Codec seeking ack expected? */
331 static unsigned int position_key
= 0;
334 static struct event_queue audio_queue SHAREDBSS_ATTR
;
337 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR
;
338 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
339 static const char audio_thread_name
[] = "audio";
340 static unsigned int audio_thread_id
= 0;
342 /* Forward declarations */
343 enum audio_start_playback_flags
345 AUDIO_START_RESTART
= 0x1, /* "Restart" playback (flush _all_ tracks) */
346 AUDIO_START_NEWBUF
= 0x2, /* Mark the audiobuffer as invalid */
349 static void audio_start_playback(size_t offset
, unsigned int flags
);
350 static void audio_stop_playback(void);
351 static void buffer_event_buffer_low_callback(void *data
);
352 static void buffer_event_rebuffer_callback(void *data
);
353 static void buffer_event_finished_callback(void *data
);
354 void audio_pcmbuf_sync_position(void);
357 /**************************************/
359 /** --- audio_queue helpers --- **/
360 static void audio_queue_post(long id
, intptr_t data
)
362 queue_post(&audio_queue
, id
, data
);
365 static intptr_t audio_queue_send(long id
, intptr_t data
)
367 return queue_send(&audio_queue
, id
, data
);
371 /** --- MP3Entry --- **/
373 /* Does the mp3entry have enough info for us to use it? */
374 static struct mp3entry
* valid_mp3entry(const struct mp3entry
*id3
)
376 return id3
&& (id3
->length
!= 0 || id3
->filesize
!= 0) &&
377 id3
->codectype
!= AFMT_UNKNOWN
? (struct mp3entry
*)id3
: NULL
;
380 /* Return a pointer to an mp3entry on the buffer, as it is */
381 static struct mp3entry
* bufgetid3(int handle_id
)
386 struct mp3entry
*id3
;
387 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
389 if (ret
!= sizeof(struct mp3entry
))
395 /* Read an mp3entry from the buffer, adjusted */
396 static bool bufreadid3(int handle_id
, struct mp3entry
*id3out
)
398 struct mp3entry
*id3
= bufgetid3(handle_id
);
402 copy_mp3entry(id3out
, id3
);
409 /* Lock the id3 mutex */
410 static void id3_mutex_lock(void)
412 mutex_lock(&id3_mutex
);
415 /* Unlock the id3 mutex */
416 static void id3_mutex_unlock(void)
418 mutex_unlock(&id3_mutex
);
421 /* Return one of the collection of mp3entry pointers - collect them all here */
422 static inline struct mp3entry
* id3_get(enum audio_id3_types id3_num
)
427 return &audio_scratch_memory
->unbuffered_id3
;
429 return &audio_scratch_memory
->codec_id3
;
431 return &static_id3_entries
[id3_num
];
435 /* Copy an mp3entry into one of the mp3 entries */
436 static void id3_write(enum audio_id3_types id3_num
,
437 const struct mp3entry
*id3_src
)
439 struct mp3entry
*dest_id3
= id3_get(id3_num
);
442 copy_mp3entry(dest_id3
, id3_src
);
444 wipe_mp3entry(dest_id3
);
447 /* Call id3_write "safely" because peek aheads can yield, even if the fast
448 preview isn't enabled */
449 static void id3_write_locked(enum audio_id3_types id3_num
,
450 const struct mp3entry
*id3_src
)
453 id3_write(id3_num
, id3_src
);
458 /** --- Track info --- **/
460 /* Close a handle and mark it invalid */
461 static void track_info_close_handle(int *hid_p
)
465 /* bufclose returns true if the handle is not found, or if it is closed
466 * successfully, so these checks are safe on non-existant handles */
470 /* Always reset to "no handle" in case it was something else */
471 *hid_p
= ERR_HANDLE_NOT_FOUND
;
474 /* Close all handles in a struct track_info and clear it */
475 static void track_info_close(struct track_info
*info
)
477 /* Close them in the order they are allocated on the buffer to speed up
478 the handle searching */
479 track_info_close_handle(&info
->id3_hid
);
480 track_info_close_handle(&info
->cuesheet_hid
);
484 track_info_close_handle(&info
->aa_hid
[i
]);
486 #ifdef HAVE_CODEC_BUFFERING
487 track_info_close_handle(&info
->codec_hid
);
489 track_info_close_handle(&info
->audio_hid
);
493 /* Invalidate all members to initial values - does not close handles */
494 static void track_info_wipe(struct track_info
* info
)
496 info
->id3_hid
= ERR_HANDLE_NOT_FOUND
;
497 info
->cuesheet_hid
= ERR_HANDLE_NOT_FOUND
;
501 info
->aa_hid
[i
] = ERR_HANDLE_NOT_FOUND
;
503 #ifdef HAVE_CODEC_BUFFERING
504 info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
506 info
->audio_hid
= ERR_HANDLE_NOT_FOUND
;
511 /** --- Track list --- **/
513 /* Initialize the track list */
514 static void track_list_init(void)
517 for (i
= 0; i
< TRACK_LIST_LEN
; i
++)
518 track_info_wipe(&track_list
.tracks
[i
]);
520 track_list
.start
= track_list
.end
= track_list
.current
;
523 /* Return number of items allocated in the list */
524 static unsigned int track_list_count(void)
526 return track_list
.end
- track_list
.start
;
529 /* Return true if the list is empty */
530 static inline bool track_list_empty(void)
532 return track_list
.end
== track_list
.start
;
535 /* Returns true if the list is holding the maximum number of items */
536 static bool track_list_full(void)
538 return track_list
.end
- track_list
.start
>= TRACK_LIST_LEN
;
541 /* Test if the index is within the allocated range */
542 static bool track_list_in_range(int pos
)
544 return (int)(pos
- track_list
.start
) >= 0 &&
545 (int)(pos
- track_list
.end
) < 0;
548 static struct track_info
* track_list_entry(int pos
)
550 return &track_list
.tracks
[pos
& TRACK_LIST_MASK
];
553 /* Return the info of the last allocation plus an offset, NULL if result is
555 static struct track_info
* track_list_last(int offset
)
557 /* Last is before the end since the end isn't inclusive */
558 unsigned int pos
= track_list
.end
+ offset
- 1;
560 if (!track_list_in_range(pos
))
563 return track_list_entry(pos
);
566 /* Allocate space at the end for another track if not full */
567 static struct track_info
* track_list_alloc_track(void)
569 if (track_list_full())
572 return track_list_entry(track_list
.end
++);
575 /* Remove the last track entry allocated in order to support backing out
577 static void track_list_unalloc_track(void)
579 if (track_list_empty())
584 if (track_list
.current
== track_list
.end
&&
585 track_list
.current
!= track_list
.start
)
587 /* Current _must_ remain within bounds */
588 track_list
.current
--;
592 /* Return current track plus an offset, NULL if result is out of bounds */
593 static struct track_info
* track_list_current(int offset
)
595 unsigned int pos
= track_list
.current
+ offset
;
597 if (!track_list_in_range(pos
))
600 return track_list_entry(pos
);
603 /* Return current based upon what's intended that the user sees - not
604 necessarily where decoding is taking place */
605 static struct track_info
* track_list_user_current(int offset
)
607 if (skip_pending
== TRACK_SKIP_AUTO
||
608 skip_pending
== TRACK_SKIP_AUTO_NEW_PLAYLIST
)
613 return track_list_current(offset
);
616 /* Advance current track by an offset, return false if result is out of
618 static struct track_info
* track_list_advance_current(int offset
)
620 unsigned int pos
= track_list
.current
+ offset
;
622 if (!track_list_in_range(pos
))
625 track_list
.current
= pos
;
626 return track_list_entry(pos
);
629 /* Clear tracks in the list, optionally preserving the current track -
630 returns 'false' if the operation was changed */
631 enum track_clear_action
633 TRACK_LIST_CLEAR_ALL
= 0, /* Clear all tracks */
634 TRACK_LIST_KEEP_CURRENT
, /* Keep current only; clear before + after */
635 TRACK_LIST_KEEP_NEW
/* Keep current and those that follow */
638 static void track_list_clear(enum track_clear_action action
)
640 logf("%s(%d)", __func__
, (int)action
);
642 /* Don't care now since rebuffering is imminent */
643 buf_set_watermark(0);
645 if (action
!= TRACK_LIST_CLEAR_ALL
)
647 struct track_info
*cur
= track_list_current(0);
649 if (!cur
|| cur
->id3_hid
< 0)
650 action
= TRACK_LIST_CLEAR_ALL
; /* Nothing worthwhile keeping */
653 /* Noone should see this progressing */
654 int start
= track_list
.start
;
655 int current
= track_list
.current
;
656 int end
= track_list
.end
;
658 track_list
.start
= current
;
662 case TRACK_LIST_CLEAR_ALL
:
663 /* Result: .start = .current, .end = .current */
664 track_list
.end
= current
;
667 case TRACK_LIST_KEEP_CURRENT
:
668 /* Result: .start = .current, .end = .current + 1 */
669 track_list
.end
= current
+ 1;
672 case TRACK_LIST_KEEP_NEW
:
673 /* Result: .start = .current, .end = .end */
678 /* Close all open handles in the range except the for the current track
679 if preserving that */
682 if (action
!= TRACK_LIST_KEEP_CURRENT
|| start
!= current
)
684 struct track_info
*info
=
685 &track_list
.tracks
[start
& TRACK_LIST_MASK
];
687 /* If this is the in-progress load, abort it */
688 if (in_progress_id3_hid
>= 0 &&
689 info
->id3_hid
== in_progress_id3_hid
)
691 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
694 track_info_close(info
);
702 /** --- Audio buffer -- **/
704 /* What size is needed for the scratch buffer? */
705 static size_t scratch_mem_size(void)
707 size_t size
= sizeof (struct audio_scratch_memory
);
709 if (global_settings
.cuesheet
)
710 size
+= sizeof (struct cuesheet
);
715 /* Initialize the memory area where data is stored that is only used when
716 playing audio and anything depending upon it */
717 static void scratch_mem_init(void *mem
)
719 audio_scratch_memory
= (struct audio_scratch_memory
*)mem
;
720 id3_write_locked(UNBUFFERED_ID3
, NULL
);
721 id3_write(CODEC_ID3
, NULL
);
722 ci
.id3
= id3_get(CODEC_ID3
);
723 audio_scratch_memory
->curr_cue
= NULL
;
725 if (global_settings
.cuesheet
)
727 audio_scratch_memory
->curr_cue
=
728 SKIPBYTES((struct cuesheet
*)audio_scratch_memory
,
729 sizeof (struct audio_scratch_memory
));
733 static int audiobuf_handle
;
734 #define AUDIO_BUFFER_RESERVE (256*1024)
735 static size_t filebuflen
;
738 size_t audio_buffer_size(void)
740 if (audiobuf_handle
> 0)
741 return filebuflen
- AUDIO_BUFFER_RESERVE
;
745 size_t audio_buffer_available(void)
748 size_t core_size
= core_available();
749 if (audiobuf_handle
> 0) /* if allocated return what we can give */
750 size
= filebuflen
- AUDIO_BUFFER_RESERVE
- 128;
751 return MAX(core_size
, size
);
754 /* Set up the audio buffer for playback
755 * filebuflen must be pre-initialized with the maximum size */
756 static void audio_reset_buffer_noalloc(void* filebuf
)
759 * Layout audio buffer as follows:
760 * [[|TALK]|SCRATCH|BUFFERING|PCM|[VOICE|]]
763 /* see audio_get_recording_buffer if this is modified */
764 logf("%s()", __func__
);
766 /* If the setup of anything allocated before the file buffer is
767 changed, do check the adjustments after the buffer_alloc call
768 as it will likely be affected and need sliding over */
770 /* Initially set up file buffer as all space available */
773 /* Subtract whatever voice needs */
774 allocsize
= talkbuf_init(filebuf
);
775 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
776 if (allocsize
> filebuflen
)
779 filebuf
+= allocsize
;
780 filebuflen
-= allocsize
;
782 if (talk_voice_required())
784 /* Need a space for voice PCM output */
785 allocsize
= voicebuf_init(filebuf
+ filebuflen
);
787 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
788 if (allocsize
> filebuflen
)
791 filebuflen
-= allocsize
;
794 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
795 allocsize
= pcmbuf_init(filebuf
+ filebuflen
);
797 /* Make sure filebuflen is a pointer sized multiple after adjustment */
798 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
799 if (allocsize
> filebuflen
)
802 filebuflen
-= allocsize
;
805 allocsize
= scratch_mem_size();
806 if (allocsize
> filebuflen
)
809 scratch_mem_init(filebuf
);
810 filebuf
+= allocsize
;
811 filebuflen
-= allocsize
;
813 buffering_reset(filebuf
, filebuflen
);
815 /* Clear any references to the file buffer */
816 buffer_state
= AUDIOBUF_STATE_INITIALIZED
;
818 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
819 /* Make sure everything adds up - yes, some info is a bit redundant but
820 aids viewing and the summation of certain variables should add up to
821 the location of others. */
823 logf("fbuf: %08X", (unsigned)filebuf
);
824 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
825 logf("sbuf: %08X", (unsigned)audio_scratch_memory
);
826 logf("sbufe: %08X", (unsigned)(audio_scratch_memory
+ allocsize
));
833 panicf("%s(): EOM (%zu > %zu)", __func__
, allocsize
, filebuflen
);
836 /* Buffer must not move. */
837 static int shrink_callback(int handle
, unsigned hints
, void* start
, size_t old_size
)
839 struct queue_event ev
;
840 static const long filter_list
[][2] =
843 { Q_AUDIO_PLAY
, Q_AUDIO_PLAY
},
845 /* filebuflen is, at this point, the buffering.c buffer size,
846 * i.e. the audiobuf except voice, scratch mem, pcm, ... */
847 ssize_t extradata_size
= old_size
- filebuflen
;
848 /* check what buflib requests */
849 size_t wanted_size
= (hints
& BUFLIB_SHRINK_SIZE_MASK
);
850 ssize_t size
= (ssize_t
)old_size
- wanted_size
;
851 /* keep at least 256K for the buffering */
852 if ((size
- extradata_size
) < AUDIO_BUFFER_RESERVE
)
853 return BUFLIB_CB_CANNOT_SHRINK
;
856 /* TODO: Do it without stopping playback, if possible */
857 long offset
= audio_current_track()->offset
;
858 /* resume if playing */
859 bool playing
= (audio_status() == AUDIO_STATUS_PLAY
);
860 /* There's one problem with stoping and resuming: If it happens in a too
861 * frequent fashion, the codecs lose the resume postion and playback
862 * begins from the beginning.
863 * To work around use queue_post() to effectively delay the resume in case
864 * we're called another time. However this has another problem: id3->offset
865 * gets zero since playback is stopped. Therefore, try to peek at the
866 * queue_post from the last call to get the correct offset. This also
867 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
869 bool play_queued
= queue_peek_ex(&audio_queue
, &ev
, QPEEK_REMOVE_EVENTS
, filter_list
);
871 if (playing
&& offset
> 0) /* current id3->offset is king */
874 /* don't call audio_hard_stop() as it frees this handle */
875 if (thread_self() == audio_thread_id
)
876 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
877 * if we're in the audio thread */
878 audio_stop_playback();
879 queue_clear(&audio_queue
);
882 audio_queue_send(Q_AUDIO_STOP
, 1);
883 #ifdef PLAYBACK_VOICE
886 /* we should be free to change the buffer now
887 * set final buffer size before calling audio_reset_buffer_noalloc()
888 * (now it's the total size, the call will subtract voice etc) */
890 switch (hints
& BUFLIB_SHRINK_POS_MASK
)
892 case BUFLIB_SHRINK_POS_BACK
:
893 core_shrink(handle
, start
, size
);
894 audio_reset_buffer_noalloc(start
);
896 case BUFLIB_SHRINK_POS_FRONT
:
897 core_shrink(handle
, start
+ wanted_size
, size
);
898 audio_reset_buffer_noalloc(start
+ wanted_size
);
901 if (playing
|| play_queued
)
903 /* post, to make subsequent calls not break the resume position */
904 audio_queue_post(Q_AUDIO_PLAY
, ev
.data
);
910 static struct buflib_callbacks ops
= {
911 .move_callback
= NULL
,
912 .shrink_callback
= shrink_callback
,
915 static void audio_reset_buffer(void)
917 if (audiobuf_handle
> 0)
919 core_free(audiobuf_handle
);
922 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
923 unsigned char *filebuf
= core_get_data(audiobuf_handle
);
925 audio_reset_buffer_noalloc(filebuf
);
928 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
929 static void audio_update_filebuf_watermark(int seconds
)
933 #ifdef HAVE_DISK_STORAGE
934 int spinup
= ata_spinup_time();
938 /* By current setting */
939 seconds
= buffer_margin
;
944 buffer_margin
= seconds
;
946 if (buf_get_watermark() == 0)
948 /* Write a watermark only if the audio thread already did so for
949 itself or it will fail to set the event and the watermark - if
950 it hasn't yet, it will use the new setting when it does */
956 seconds
+= (spinup
/ HZ
) + 1;
960 seconds
+= buffer_margin
;
966 /* Watermark is a function of the bitrate of the last track in the buffer */
967 struct mp3entry
*id3
= NULL
;
968 struct track_info
*info
= track_list_last(0);
971 id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
975 if (get_audio_base_data_type(id3
->codectype
) == TYPE_PACKET_AUDIO
)
977 bytes
= id3
->bitrate
* (1000/8) * seconds
;
981 /* Bitrate has no meaning to buffering margin for atomic audio -
982 rebuffer when it's the only track left unless it's the only
983 track that fits, in which case we should avoid constant buffer
985 if (track_list_count() > 1)
986 bytes
= info
->filesize
+ 1;
991 /* Then set the minimum - this should not occur anyway */
992 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
993 track_list
.start
, track_list
.current
, track_list
.end
);
996 /* Actually setting zero disables the notification and we use that
997 to detect that it has been reset */
998 buf_set_watermark(MAX(bytes
, 1));
999 logf("fwmark: %lu", (unsigned long)bytes
);
1003 /** -- Track change notification -- **/
1005 /* Check the pcmbuf track changes and return write the message into the event
1007 static inline bool audio_pcmbuf_track_change_scan(void)
1009 if (track_change
.out
!= track_change
.in
)
1018 /* Clear outstanding track change posts */
1019 static inline void audio_pcmbuf_track_change_clear(void)
1021 track_change
.out
= track_change
.in
;
1024 /* Post a track change notification - called by audio ISR */
1025 static inline void audio_pcmbuf_track_change_post(void)
1031 /** --- Helper functions --- **/
1033 /* Removes messages that might end up in the queue before or while processing
1034 a manual track change. Responding to them would be harmful since they
1035 belong to a previous track's playback period. Anything that would generate
1036 the stale messages must first be put into a state where it will not do so.
1038 static void audio_clear_track_notifications(void)
1040 static const long filter_list
[][2] =
1042 /* codec messages */
1043 { Q_AUDIO_CODEC_SEEK_COMPLETE
, Q_AUDIO_CODEC_COMPLETE
},
1044 /* track change messages */
1045 { Q_AUDIO_TRACK_CHANGED
, Q_AUDIO_TRACK_CHANGED
},
1048 const int filter_count
= ARRAYLEN(filter_list
) - 1;
1050 /* Remove any pcmbuf notifications */
1051 pcmbuf_monitor_track_change(false);
1052 audio_pcmbuf_track_change_clear();
1054 /* Scrub the audio queue of the old mold */
1055 while (queue_peek_ex(&audio_queue
, NULL
,
1056 filter_count
| QPEEK_REMOVE_EVENTS
,
1059 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1063 /* Takes actions based upon track load status codes */
1064 static void audio_handle_track_load_status(int trackstat
)
1068 case LOAD_TRACK_ERR_NO_MORE
:
1069 if (track_list_count() > 0)
1072 case LOAD_TRACK_ERR_START_CODEC
:
1073 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_ERROR
);
1081 /* Announce the end of playing the current track */
1082 static void audio_playlist_track_finish(void)
1084 struct mp3entry
*ply_id3
= id3_get(PLAYING_ID3
);
1085 struct mp3entry
*id3
= valid_mp3entry(ply_id3
);
1087 playlist_update_resume_info(filling
== STATE_ENDED
? NULL
: id3
);
1091 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
1092 prev_track_elapsed
= id3
->elapsed
;
1096 prev_track_elapsed
= 0;
1100 /* Announce the beginning of the new track */
1101 static void audio_playlist_track_change(void)
1103 struct mp3entry
*id3
= valid_mp3entry(id3_get(PLAYING_ID3
));
1106 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, id3
);
1108 position_key
= pcmbuf_get_position_key();
1110 playlist_update_resume_info(id3
);
1113 /* Change the data for the next track and send the event */
1114 static void audio_update_and_announce_next_track(const struct mp3entry
*id3_next
)
1116 id3_write_locked(NEXTTRACK_ID3
, id3_next
);
1117 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
,
1118 id3_get(NEXTTRACK_ID3
));
1121 /* Bring the user current mp3entry up to date and set a new offset for the
1122 buffered metadata */
1123 static void playing_id3_sync(struct track_info
*user_info
, off_t offset
)
1127 struct mp3entry
*id3
= bufgetid3(user_info
->id3_hid
);
1128 struct mp3entry
*playing_id3
= id3_get(PLAYING_ID3
);
1132 unsigned long e
= playing_id3
->elapsed
;
1133 unsigned long o
= playing_id3
->offset
;
1135 id3_write(PLAYING_ID3
, id3
);
1139 playing_id3
->elapsed
= e
;
1140 playing_id3
->offset
= o
;
1147 id3
->offset
= offset
;
1152 /* Wipe-out track metadata - current is optional */
1153 static void wipe_track_metadata(bool current
)
1158 id3_write(PLAYING_ID3
, NULL
);
1160 id3_write(NEXTTRACK_ID3
, NULL
);
1161 id3_write(UNBUFFERED_ID3
, NULL
);
1166 /* Called when buffering is completed on the last track handle */
1167 static void filling_is_finished(void)
1169 logf("last track finished buffering");
1171 /* There's no more to load or watch for */
1172 buf_set_watermark(0);
1173 filling
= STATE_FINISHED
;
1176 /* Stop the codec decoding or waiting for its data to be ready - returns
1177 'false' if the codec ended up stopped */
1178 static bool halt_decoding_track(bool stop
)
1180 /* If it was waiting for us to clear the buffer to make a rebuffer
1181 happen, it should cease otherwise codec_stop could deadlock waiting
1182 for the codec to go to its main loop - codec's request will now
1184 bool retval
= false;
1186 buf_signal_handle(ci
.audio_hid
, true);
1191 retval
= codec_pause();
1193 audio_clear_track_notifications();
1195 /* We now know it's idle and not waiting for buffered data */
1196 buf_signal_handle(ci
.audio_hid
, false);
1198 codec_skip_pending
= false;
1199 codec_seeking
= false;
1204 /* Wait for any in-progress fade to complete */
1205 static void audio_wait_fade_complete(void)
1207 /* Just loop until it's done */
1208 while (pcmbuf_fading())
1212 /* End the ff/rw mode */
1213 static void audio_ff_rewind_end(void)
1215 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1223 /* Clear the buffer */
1225 audio_pcmbuf_sync_position();
1228 if (play_status
!= PLAY_PAUSED
)
1230 /* Seeking-while-playing, resume PCM playback */
1231 pcmbuf_pause(false);
1236 /* Complete the codec seek */
1237 static void audio_complete_codec_seek(void)
1239 /* If a seek completed while paused, 'paused' is true.
1240 * If seeking from seek mode, 'ff_rw_mode' is true. */
1243 audio_ff_rewind_end();
1244 codec_seeking
= false; /* set _after_ the call! */
1246 /* else it's waiting and we must repond */
1249 /* Get the current cuesheet pointer */
1250 static inline struct cuesheet
* get_current_cuesheet(void)
1252 return audio_scratch_memory
->curr_cue
;
1255 /* Read the cuesheet from the buffer */
1256 static void buf_read_cuesheet(int handle_id
)
1258 struct cuesheet
*cue
= get_current_cuesheet();
1260 if (!cue
|| handle_id
< 0)
1263 bufread(handle_id
, sizeof (struct cuesheet
), cue
);
1266 /* Backend to peek/current/next track metadata interface functions -
1267 fill in the mp3entry with as much information as we may obtain about
1268 the track at the specified offset from the user current track -
1269 returns false if no information exists with us */
1270 static bool audio_get_track_metadata(int offset
, struct mp3entry
*id3
)
1272 if (play_status
== PLAY_STOPPED
)
1275 if (id3
->path
[0] != '\0')
1276 return true; /* Already filled */
1278 struct track_info
*info
= track_list_user_current(offset
);
1282 struct mp3entry
*ub_id3
= id3_get(UNBUFFERED_ID3
);
1284 if (offset
> 0 && track_list_user_current(offset
- 1))
1286 /* Try the unbuffered id3 since we're moving forward */
1287 if (ub_id3
->path
[0] != '\0')
1289 copy_mp3entry(id3
, ub_id3
);
1294 else if (bufreadid3(info
->id3_hid
, id3
))
1296 id3
->cuesheet
= NULL
;
1300 /* We didn't find the ID3 metadata, so we fill it with the little info we
1301 have and return that */
1303 char path
[MAX_PATH
+1];
1304 if (playlist_peek(offset
, path
, sizeof (path
)))
1306 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1307 /* Try to get it from the database */
1308 if (!tagcache_fill_tags(id3
, path
))
1311 /* By now, filename is the only source of info */
1312 fill_metadata_from_path(id3
, path
);
1323 /* Get a resume rewind adjusted offset from the ID3 */
1324 static unsigned long resume_rewind_adjusted_offset(const struct mp3entry
*id3
)
1326 unsigned long offset
= id3
->offset
;
1327 size_t resume_rewind
= global_settings
.resume_rewind
*
1328 id3
->bitrate
* (1000/8);
1330 if (offset
< resume_rewind
)
1333 offset
-= resume_rewind
;
1338 /* Get the codec into ram and initialize it - keep it if it's ready */
1339 static bool audio_init_codec(struct track_info
*track_info
,
1340 struct mp3entry
*track_id3
)
1342 int codt_loaded
= get_audio_base_codec_type(codec_loaded());
1343 int hid
= ERR_HANDLE_NOT_FOUND
;
1345 if (codt_loaded
!= AFMT_UNKNOWN
)
1347 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1349 if (codt
== codt_loaded
)
1351 /* Codec is the same base type */
1352 logf("Reusing prev. codec: %d", track_id3
->codectype
);
1353 #ifdef HAVE_CODEC_BUFFERING
1354 /* Close any buffered codec (we could have skipped directly to a
1355 format transistion that is the same format as the current track
1356 and the buffered one is no longer needed) */
1357 track_info_close_handle(&track_info
->codec_hid
);
1363 /* New codec - first make sure the old one's gone */
1364 logf("Removing prev. codec: %d", codt_loaded
);
1369 logf("New codec: %d/%d", track_id3
->codectype
, codec_loaded());
1371 #ifdef HAVE_CODEC_BUFFERING
1372 /* Codec thread will close the handle even if it fails and will load from
1373 storage if hid is not valid or the buffer load fails */
1374 hid
= track_info
->codec_hid
;
1375 track_info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
1378 return codec_load(hid
, track_id3
->codectype
);
1379 (void)track_info
; /* When codec buffering isn't supported */
1382 /* Start the codec for the current track scheduled to be decoded */
1383 static bool audio_start_codec(bool auto_skip
)
1385 struct track_info
*info
= track_list_current(0);
1386 struct mp3entry
*cur_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1391 buf_pin_handle(info
->id3_hid
, true);
1393 if (!audio_init_codec(info
, cur_id3
))
1395 buf_pin_handle(info
->id3_hid
, false);
1399 #ifdef HAVE_TAGCACHE
1400 bool autoresume_enable
= global_settings
.autoresume_enable
;
1402 if (autoresume_enable
&& !cur_id3
->offset
)
1404 /* Resume all manually selected tracks */
1405 bool resume
= !auto_skip
;
1407 /* Send the "buffer" event to obtain the resume position for the codec */
1408 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1412 /* Automatic skip - do further tests to see if we should just
1413 ignore any autoresume position */
1414 int autoresume_automatic
= global_settings
.autoresume_automatic
;
1416 switch (autoresume_automatic
)
1418 case AUTORESUME_NEXTTRACK_ALWAYS
:
1419 /* Just resume unconditionally */
1422 case AUTORESUME_NEXTTRACK_NEVER
:
1423 /* Force-rewind it */
1426 /* Not "never resume" - pass resume filter? */
1427 resume
= autoresumable(cur_id3
);
1432 cur_id3
->offset
= 0;
1434 logf("%s: Set offset for %s to %lX\n", __func__
,
1435 cur_id3
->title
, cur_id3
->offset
);
1437 #endif /* HAVE_TAGCACHE */
1439 /* Rewind the required amount - if an autoresume was done, this also rewinds
1440 that by the setting's amount
1442 It would be best to have bookkeeping about whether or not the track
1443 sounded or not since skipping to it or else skipping to it while paused
1444 and back again will cause accumulation of silent rewinds - that's not
1445 our job to track directly nor could it be in any reasonable way
1447 cur_id3
->offset
= resume_rewind_adjusted_offset(cur_id3
);
1449 /* Update the codec API with the metadata and track info */
1450 id3_write(CODEC_ID3
, cur_id3
);
1452 ci
.audio_hid
= info
->audio_hid
;
1453 ci
.filesize
= info
->filesize
;
1454 buf_set_base_handle(info
->audio_hid
);
1456 /* All required data is now available for the codec */
1459 #ifdef HAVE_TAGCACHE
1460 if (!autoresume_enable
|| cur_id3
->offset
)
1463 /* Send the "buffer" event now */
1464 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1467 buf_pin_handle(info
->id3_hid
, false);
1470 (void)auto_skip
; /* ifndef HAVE_TAGCACHE */
1474 /** --- Audio thread --- **/
1476 /* Load and parse a cuesheet for the file - returns false if the buffer
1478 static bool audio_load_cuesheet(struct track_info
*info
,
1479 struct mp3entry
*track_id3
)
1481 struct cuesheet
*cue
= get_current_cuesheet();
1482 track_id3
->cuesheet
= NULL
;
1484 if (cue
&& info
->cuesheet_hid
== ERR_HANDLE_NOT_FOUND
)
1486 /* If error other than a full buffer, then mark it "unsupported" to
1487 avoid reloading attempt */
1488 int hid
= ERR_UNSUPPORTED_TYPE
;
1489 struct cuesheet_file cue_file
;
1491 #ifdef HAVE_IO_PRIORITY
1492 buf_back_off_storage(true);
1494 if (look_for_cuesheet_file(track_id3
, &cue_file
))
1496 hid
= bufalloc(NULL
, sizeof (struct cuesheet
), TYPE_CUESHEET
);
1500 void *cuesheet
= NULL
;
1501 bufgetdata(hid
, sizeof (struct cuesheet
), &cuesheet
);
1503 if (parse_cuesheet(&cue_file
, (struct cuesheet
*)cuesheet
))
1505 /* Indicate cuesheet is present (while track remains
1507 track_id3
->cuesheet
= cue
;
1512 hid
= ERR_UNSUPPORTED_TYPE
;
1517 #ifdef HAVE_IO_PRIORITY
1518 buf_back_off_storage(false);
1520 if (hid
== ERR_BUFFER_FULL
)
1522 logf("buffer is full for now (%s)", __func__
);
1528 logf("Cuesheet loading failed");
1530 info
->cuesheet_hid
= hid
;
1537 #ifdef HAVE_ALBUMART
1538 /* Load any album art for the file - returns false if the buffer is full */
1539 static bool audio_load_albumart(struct track_info
*info
,
1540 struct mp3entry
*track_id3
)
1545 struct bufopen_bitmap_data user_data
;
1546 int *aa_hid
= &info
->aa_hid
[i
];
1547 int hid
= ERR_UNSUPPORTED_TYPE
;
1549 /* albumart_slots may change during a yield of bufopen,
1550 * but that's no problem */
1551 if (*aa_hid
>= 0 || *aa_hid
== ERR_UNSUPPORTED_TYPE
||
1552 !albumart_slots
[i
].used
)
1555 memset(&user_data
, 0, sizeof(user_data
));
1556 user_data
.dim
= &albumart_slots
[i
].dim
;
1558 #ifdef HAVE_IO_PRIORITY
1559 buf_back_off_storage(true);
1562 /* We can only decode jpeg for embedded AA */
1563 if (track_id3
->has_embedded_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1565 user_data
.embedded_albumart
= &track_id3
->albumart
;
1566 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1569 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1571 /* No embedded AA or it couldn't be loaded - try other sources */
1572 char path
[MAX_PATH
];
1574 if (find_albumart(track_id3
, path
, sizeof(path
),
1575 &albumart_slots
[i
].dim
))
1577 user_data
.embedded_albumart
= NULL
;
1578 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1582 #ifdef HAVE_IO_PRIORITY
1583 buf_back_off_storage(false);
1585 if (hid
== ERR_BUFFER_FULL
)
1587 logf("buffer is full for now (%s)", __func__
);
1592 /* If error other than a full buffer, then mark it "unsupported"
1593 to avoid reloading attempt */
1596 logf("Album art loading failed");
1597 hid
= ERR_UNSUPPORTED_TYPE
;
1606 #endif /* HAVE_ALBUMART */
1608 #ifdef HAVE_CODEC_BUFFERING
1609 /* Load a codec for the file onto the buffer - assumes we're working from the
1610 currently loading track - not called for the current track */
1611 static bool audio_buffer_codec(struct track_info
*track_info
,
1612 struct mp3entry
*track_id3
)
1614 /* This will not be the current track -> it cannot be the first and the
1615 current track cannot be ahead of buffering -> there is a previous
1616 track entry which is either current or ahead of the current */
1617 struct track_info
*prev_info
= track_list_last(-1);
1618 struct mp3entry
*prev_id3
= bufgetid3(prev_info
->id3_hid
);
1620 /* If the previous codec is the same as this one, there is no need to
1621 put another copy of it on the file buffer (in other words, only
1622 buffer codecs at format transitions) */
1625 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1626 int prev_codt
= get_audio_base_codec_type(prev_id3
->codectype
);
1628 if (codt
== prev_codt
)
1630 logf("Reusing prev. codec: %d", prev_id3
->codectype
);
1634 /* else just load it (harmless) */
1636 /* Load the codec onto the buffer if possible */
1637 const char *codec_fn
= get_codec_filename(track_id3
->codectype
);
1641 char codec_path
[MAX_PATH
+1]; /* Full path to codec */
1642 codec_get_full_path(codec_path
, codec_fn
);
1644 track_info
->codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1646 if (track_info
->codec_hid
>= 0)
1648 logf("Buffered codec: %d", afmt
);
1654 #endif /* HAVE_CODEC_BUFFERING */
1656 /* Load metadata for the next track (with bufopen). The rest of the track
1657 loading will be handled by audio_finish_load_track once the metadata has
1658 been actually loaded by the buffering thread.
1660 Each track is arranged in the buffer as follows:
1661 <id3|[cuesheet|][album art|][codec|]audio>
1663 The next will not be loaded until the previous succeeds if the buffer was
1664 full at the time. To put any metadata after audio would make those handles
1667 static int audio_load_track(void)
1669 if (in_progress_id3_hid
>= 0)
1671 /* There must be an info pointer if the in-progress id3 is even there */
1672 struct track_info
*info
= track_list_last(0);
1674 if (info
->id3_hid
== in_progress_id3_hid
)
1676 if (filling
== STATE_FILLING
)
1678 /* Haven't finished the metadata but the notification is
1679 anticipated to come soon */
1680 logf("%s(): in progress ok: %d". __func__
, info
->id3_hid
);
1681 return LOAD_TRACK_OK
;
1683 else if (filling
== STATE_FULL
)
1685 /* Buffer was full trying to complete the load after the
1686 metadata finished, so attempt to continue - older handles
1687 should have been cleared already */
1688 logf("%s(): finishing load: %d". __func__
, info
->id3_hid
);
1689 filling
= STATE_FILLING
;
1690 buffer_event_finished_callback(&info
->id3_hid
);
1691 return LOAD_TRACK_OK
;
1695 /* Some old, stray buffering message */
1696 logf("%s(): already in progress: %d". __func__
, info
->id3_hid
);
1697 return LOAD_TRACK_ERR_BUSY
;
1700 filling
= STATE_FILLING
;
1702 struct track_info
*info
= track_list_alloc_track();
1705 /* List is full so stop buffering tracks - however, attempt to obtain
1706 metadata as the unbuffered id3 */
1707 logf("No free tracks");
1708 filling
= STATE_FULL
;
1711 playlist_peek_offset
++;
1713 logf("Buffering track: s%u/c%u/e%u/p%d",
1714 track_list
.start
, track_list
.current
, track_list
.end
,
1715 playlist_peek_offset
);
1717 /* Get track name from current playlist read position */
1719 char name_buf
[MAX_PATH
+ 1];
1720 const char *trackname
;
1725 trackname
= playlist_peek(playlist_peek_offset
, name_buf
,
1731 /* Test for broken playlists by probing for the files */
1732 fd
= open(trackname
, O_RDONLY
);
1736 logf("Open failed");
1737 /* Skip invalid entry from playlist */
1738 playlist_skip_entry(NULL
, playlist_peek_offset
);
1740 /* Sync the playlist if it isn't finished */
1741 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1747 /* No track - exhausted the playlist entries */
1748 logf("End-of-playlist");
1749 id3_write_locked(UNBUFFERED_ID3
, NULL
);
1751 if (filling
!= STATE_FULL
)
1752 track_list_unalloc_track(); /* Free this entry */
1754 playlist_peek_offset
--; /* Maintain at last index */
1756 /* We can end up here after the real last track signals its completion
1757 and miss the transition to STATE_FINISHED esp. if dropping the last
1758 songs of a playlist late in their load (2nd stage) */
1759 info
= track_list_last(0);
1761 if (info
&& buf_handle_remaining(info
->audio_hid
) == 0)
1762 filling_is_finished();
1764 filling
= STATE_END_OF_PLAYLIST
;
1766 return LOAD_TRACK_ERR_NO_MORE
;
1769 /* Successfully opened the file - get track metadata */
1770 if (filling
== STATE_FULL
||
1771 (info
->id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
)) < 0)
1773 /* Buffer or track list is full */
1774 struct mp3entry
*ub_id3
;
1776 playlist_peek_offset
--;
1778 /* Load the metadata for the first unbuffered track */
1779 ub_id3
= id3_get(UNBUFFERED_ID3
);
1781 get_metadata(ub_id3
, fd
, trackname
);
1784 if (filling
!= STATE_FULL
)
1786 track_list_unalloc_track();
1787 filling
= STATE_FULL
;
1790 logf("%s: buffer is full for now (%u tracks)", __func__
,
1791 track_list_count());
1795 /* Successful load initiation */
1796 info
->filesize
= filesize(fd
);
1797 in_progress_id3_hid
= info
->id3_hid
; /* Remember what's in-progress */
1801 return LOAD_TRACK_OK
;
1804 /* Second part of the track loading: We now have the metadata available, so we
1805 can load the codec, the album art and finally the audio data.
1806 This is called on the audio thread after the buffering thread calls the
1807 buffering_handle_finished_callback callback. */
1808 static int audio_finish_load_track(struct track_info
*info
)
1810 int trackstat
= LOAD_TRACK_OK
;
1812 if (info
->id3_hid
!= in_progress_id3_hid
)
1814 /* We must not be here if not! */
1815 logf("%s: wrong track %d/%d", __func__
, info
->id3_hid
,
1816 in_progress_id3_hid
);
1817 return LOAD_TRACK_ERR_BUSY
;
1820 /* The current track for decoding (there is always one if the list is
1822 struct track_info
*cur_info
= track_list_current(0);
1823 struct mp3entry
*track_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1827 /* This is an error condition. Track cannot be played without valid
1828 metadata; skip the track. */
1829 logf("No metadata");
1830 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1831 goto audio_finish_load_track_exit
;
1834 /* Try to load a cuesheet for the track */
1835 if (!audio_load_cuesheet(info
, track_id3
))
1837 /* No space for cuesheet on buffer, not an error */
1838 filling
= STATE_FULL
;
1839 goto audio_finish_load_track_exit
;
1842 #ifdef HAVE_ALBUMART
1843 /* Try to load album art for the track */
1844 if (!audio_load_albumart(info
, track_id3
))
1846 /* No space for album art on buffer, not an error */
1847 filling
= STATE_FULL
;
1848 goto audio_finish_load_track_exit
;
1852 /* All handles available to external routines are ready - audio and codec
1853 information is private */
1855 if (info
== track_list_user_current(0))
1857 /* Send only when the track handles could not all be opened ahead of
1858 time for the user's current track - otherwise everything is ready
1859 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1860 send_event(PLAYBACK_EVENT_CUR_TRACK_READY
, id3_get(PLAYING_ID3
));
1863 #ifdef HAVE_CODEC_BUFFERING
1864 /* Try to buffer a codec for the track */
1865 if (info
!= cur_info
&& !audio_buffer_codec(info
, track_id3
))
1867 if (info
->codec_hid
== ERR_BUFFER_FULL
)
1869 /* No space for codec on buffer, not an error */
1870 filling
= STATE_FULL
;
1871 logf("buffer is full for now (%s)", __func__
);
1875 /* This is an error condition, either no codec was found, or
1876 reading the codec file failed part way through, either way,
1878 logf("No codec for: %s", track_id3
->path
);
1879 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1882 goto audio_finish_load_track_exit
;
1884 #endif /* HAVE_CODEC_BUFFERING */
1886 /** Finally, load the audio **/
1887 size_t file_offset
= 0;
1888 track_id3
->elapsed
= 0;
1890 if (track_id3
->offset
>= info
->filesize
)
1891 track_id3
->offset
= 0;
1893 logf("%s: set offset for %s to %lu\n", __func__
,
1894 id3
->title
, (unsigned long)offset
);
1896 /* Adjust for resume rewind so we know what to buffer - starting the codec
1897 calls it again, so we don't save it (and they shouldn't accumulate) */
1898 size_t offset
= resume_rewind_adjusted_offset(track_id3
);
1900 enum data_type audiotype
= get_audio_base_data_type(track_id3
->codectype
);
1902 if (audiotype
== TYPE_ATOMIC_AUDIO
)
1903 logf("Loading atomic %d", track_id3
->codectype
);
1905 if (format_buffers_with_offset(track_id3
->codectype
))
1907 /* This format can begin buffering from any point */
1908 file_offset
= offset
;
1911 logf("load track: %s", track_id3
->path
);
1913 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1915 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1916 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1920 /* No offset given or it is very minimal - begin at the first frame
1921 according to the metadata */
1922 file_offset
= track_id3
->first_frame_offset
;
1925 int hid
= bufopen(track_id3
->path
, file_offset
, audiotype
, NULL
);
1929 info
->audio_hid
= hid
;
1931 if (info
== cur_info
)
1933 /* This is the current track to decode - should be started now */
1934 trackstat
= LOAD_TRACK_READY
;
1939 /* Buffer could be full but not properly so if this is the only
1941 if (hid
== ERR_BUFFER_FULL
&& audio_track_count() > 1)
1943 filling
= STATE_FULL
;
1944 logf("Buffer is full for now (%s)", __func__
);
1948 /* Nothing to play if no audio handle - skip this */
1949 logf("Could not add audio data handle");
1950 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1954 audio_finish_load_track_exit
:
1955 if (trackstat
< LOAD_TRACK_OK
)
1957 playlist_skip_entry(NULL
, playlist_peek_offset
);
1958 track_info_close(info
);
1959 track_list_unalloc_track();
1961 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1964 playlist_peek_offset
--;
1967 if (filling
!= STATE_FULL
)
1969 /* Load next track - error or not */
1970 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
1971 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1972 audio_queue_post(Q_AUDIO_FILL_BUFFER
, 0);
1977 trackstat
= LOAD_TRACK_ERR_FINISH_FULL
;
1983 /* Start a new track load */
1984 static int audio_fill_file_buffer(void)
1986 if (play_status
== PLAY_STOPPED
)
1987 return LOAD_TRACK_ERR_FAILED
;
1989 trigger_cpu_boost();
1991 /* Must reset the buffer before use if trashed or voice only - voice
1992 file size shouldn't have changed so we can go straight from
1993 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1994 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1995 audio_reset_buffer();
1997 logf("Starting buffer fill");
1999 int trackstat
= audio_load_track();
2001 if (trackstat
>= LOAD_TRACK_OK
)
2003 if (track_list_current(0) == track_list_user_current(0))
2006 if (filling
== STATE_FULL
&& !track_list_user_current(1))
2008 /* There are no user tracks on the buffer after this therefore
2009 this is the next track */
2010 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3
));
2017 /* Discard unwanted tracks and start refill from after the specified playlist
2019 static int audio_reset_and_rebuffer(
2020 enum track_clear_action action
, int peek_offset
)
2022 logf("Forcing rebuffer: 0x%X, %d", flags
, peek_offset
);
2024 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2026 /* Remove unwanted tracks - caller must have ensured codec isn't using
2028 track_list_clear(action
);
2030 /* Refill at specified position (-1 starts at index offset 0) */
2031 playlist_peek_offset
= peek_offset
;
2033 /* Fill the buffer */
2034 return audio_fill_file_buffer();
2037 /* Handle buffering events
2038 (Q_AUDIO_BUFFERING) */
2039 static void audio_on_buffering(int event
)
2041 enum track_clear_action action
;
2044 if (track_list_empty())
2049 case BUFFER_EVENT_BUFFER_LOW
:
2050 if (filling
!= STATE_FULL
&& filling
!= STATE_END_OF_PLAYLIST
)
2051 return; /* Should be nothing left to fill */
2053 /* Clear old tracks and continue buffering where it left off */
2054 action
= TRACK_LIST_KEEP_NEW
;
2055 peek_offset
= playlist_peek_offset
;
2058 case BUFFER_EVENT_REBUFFER
:
2059 /* Remove all but the currently decoding track and redo buffering
2061 action
= TRACK_LIST_KEEP_CURRENT
;
2062 peek_offset
= (skip_pending
== TRACK_SKIP_AUTO
) ? 1 : 0;
2069 switch (skip_pending
)
2071 case TRACK_SKIP_NONE
:
2072 case TRACK_SKIP_AUTO
:
2073 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2074 audio_reset_and_rebuffer(action
, peek_offset
);
2077 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2078 /* Already finished */
2083 logf("Buffering call, inv. state: %d", (int)skip_pending
);
2087 /* Handle starting the next track load
2088 (Q_AUDIO_FILL_BUFFER) */
2089 static void audio_on_fill_buffer(void)
2091 audio_handle_track_load_status(audio_fill_file_buffer());
2094 /* Handle posted load track finish event
2095 (Q_AUDIO_FINISH_LOAD_TRACK) */
2096 static void audio_on_finish_load_track(int id3_hid
)
2098 struct track_info
*info
= track_list_last(0);
2100 if (!info
|| !buf_is_handle(id3_hid
))
2103 if (info
== track_list_user_current(1))
2105 /* Just loaded the metadata right after the current position */
2106 audio_update_and_announce_next_track(bufgetid3(info
->id3_hid
));
2109 if (audio_finish_load_track(info
) != LOAD_TRACK_READY
)
2110 return; /* Not current track */
2112 bool is_user_current
= info
== track_list_user_current(0);
2114 if (is_user_current
)
2117 buf_read_cuesheet(info
->cuesheet_hid
);
2120 if (audio_start_codec(automatic_skip
))
2122 if (is_user_current
)
2124 /* Be sure all tagtree info is synchronized; it will be needed for the
2125 track finish event - the sync will happen when finalizing a track
2127 bool was_valid
= valid_mp3entry(id3_get(PLAYING_ID3
));
2129 playing_id3_sync(info
, -1);
2133 /* Playing id3 hadn't been updated yet because no valid track
2134 was yet available - treat like the first track */
2135 audio_playlist_track_change();
2141 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2145 /* Called when handles other than metadata handles have finished buffering
2146 (Q_AUDIO_HANDLE_FINISHED) */
2147 static void audio_on_handle_finished(int hid
)
2149 /* Right now, only audio handles should end up calling this */
2150 if (filling
== STATE_END_OF_PLAYLIST
)
2152 struct track_info
*info
= track_list_last(0);
2154 /* Really we don't know which order the handles will actually complete
2155 to zero bytes remaining since another thread is doing it - be sure
2156 it's the right one */
2157 if (info
&& info
->audio_hid
== hid
)
2159 /* This was the last track in the playlist and we now have all the
2161 filling_is_finished();
2166 /* Called to make an outstanding track skip the current track and to send the
2167 transition events */
2168 static void audio_finalise_track_change(void)
2170 switch (skip_pending
)
2172 case TRACK_SKIP_NONE
: /* Manual skip */
2175 case TRACK_SKIP_AUTO
:
2176 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2178 int playlist_delta
= skip_pending
== TRACK_SKIP_AUTO
? 1 : 0;
2179 audio_playlist_track_finish();
2181 if (!playlist_peek(playlist_delta
, NULL
, 0))
2183 /* Track ended up rejected - push things ahead like the codec blew
2184 it (because it was never started and now we're here where it
2185 should have been decoding the next track by now) - next, a
2186 directory change or end of playback will most likely happen */
2187 skip_pending
= TRACK_SKIP_NONE
;
2188 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2192 if (!playlist_delta
)
2195 playlist_peek_offset
-= playlist_delta
;
2196 if (playlist_next(playlist_delta
) >= 0)
2198 /* What!? Disappear? Hopeless bleak despair */
2201 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2202 default: /* Invalid */
2203 filling
= STATE_ENDED
;
2204 audio_stop_playback();
2208 struct track_info
*info
= track_list_current(0);
2209 struct mp3entry
*track_id3
= NULL
;
2213 /* Update the current cuesheet if any and enabled */
2216 buf_read_cuesheet(info
->cuesheet_hid
);
2217 track_id3
= bufgetid3(info
->id3_hid
);
2220 id3_write(PLAYING_ID3
, track_id3
);
2222 /* The skip is technically over */
2223 skip_pending
= TRACK_SKIP_NONE
;
2225 /* Sync the next track information */
2226 info
= track_list_current(1);
2228 id3_write(NEXTTRACK_ID3
, info
? bufgetid3(info
->id3_hid
) :
2229 id3_get(UNBUFFERED_ID3
));
2233 audio_playlist_track_change();
2236 /* Actually begin a transition and take care of the codec change - may complete
2237 it now or ask pcmbuf for notification depending on the type */
2238 static void audio_begin_track_change(enum pcm_track_change_type type
,
2241 /* Even if the new track is bad, the old track must be finished off */
2242 pcmbuf_start_track_change(type
);
2244 bool auto_skip
= type
!= TRACK_CHANGE_MANUAL
;
2248 /* Manual track change happens now */
2249 audio_finalise_track_change();
2250 pcmbuf_sync_position_update();
2252 if (play_status
== PLAY_STOPPED
)
2253 return; /* Stopped us */
2256 if (trackstat
>= LOAD_TRACK_OK
)
2258 struct track_info
*info
= track_list_current(0);
2260 if (info
->audio_hid
< 0)
2263 /* Everything needed for the codec is ready - start it */
2264 if (audio_start_codec(auto_skip
))
2267 playing_id3_sync(info
, -1);
2271 trackstat
= LOAD_TRACK_ERR_START_CODEC
;
2274 audio_handle_track_load_status(trackstat
);
2277 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2278 static void audio_monitor_end_of_playlist(void)
2280 skip_pending
= TRACK_SKIP_AUTO_END_PLAYLIST
;
2281 filling
= STATE_ENDING
;
2282 pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA
);
2285 /* Codec has completed decoding the track
2286 (usually Q_AUDIO_CODEC_COMPLETE) */
2287 static void audio_on_codec_complete(int status
)
2289 logf("%s(%d)", __func__
, status
);
2291 if (play_status
== PLAY_STOPPED
)
2294 /* If it didn't notify us first, don't expect "seek complete" message
2295 since the codec can't post it now - do things like it would have
2297 audio_complete_codec_seek();
2299 if (play_status
== PLAY_PAUSED
|| skip_pending
!= TRACK_SKIP_NONE
)
2301 /* Old-hay on the ip-skay - codec has completed decoding
2303 Paused: We're not sounding it, so just remember that it happened
2304 and the resume will begin the transition
2306 Skipping: There was already a skip in progress, remember it and
2307 allow no further progress until the PCM from the previous
2310 codec_skip_pending
= true;
2311 codec_skip_status
= status
;
2315 codec_skip_pending
= false;
2317 int trackstat
= LOAD_TRACK_OK
;
2319 automatic_skip
= true;
2320 skip_pending
= TRACK_SKIP_AUTO
;
2322 /* Does this track have an entry allocated? */
2323 struct track_info
*info
= track_list_advance_current(1);
2325 if (!info
|| info
->audio_hid
< 0)
2327 bool end_of_playlist
= false;
2331 /* Track load is not complete - it might have stopped on a
2332 full buffer without reaching the audio handle or we just
2335 If this type is atomic and we couldn't get the audio,
2336 perhaps it would need to wrap to make the allocation and
2337 handles are in the way - to maximize the liklihood it can
2338 be allocated, clear all handles to reset the buffer and
2339 its indexes to 0 - for packet audio, this should not be an
2340 issue and a pointless full reload of all the track's
2341 metadata may be avoided */
2343 struct mp3entry
*track_id3
= bufgetid3(info
->id3_hid
);
2346 get_audio_base_data_type(track_id3
->codectype
)
2347 == TYPE_PACKET_AUDIO
)
2349 /* Continue filling after this track */
2350 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT
, 1);
2351 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2354 /* else rebuffer at this track; status applies to the track we
2357 else if (!playlist_peek(1, NULL
, 0))
2359 /* Play sequence is complete - directory change or other playlist
2360 resequencing - the playlist must now be advanced in order to
2361 continue since a peek ahead to the next track is not possible */
2362 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2363 end_of_playlist
= playlist_next(1) < 0;
2366 if (!end_of_playlist
)
2368 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
,
2369 skip_pending
== TRACK_SKIP_AUTO
? 0 : -1);
2371 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2373 /* Failed to find anything after all - do playlist switchover
2375 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2376 end_of_playlist
= playlist_next(1) < 0;
2380 if (end_of_playlist
)
2382 audio_monitor_end_of_playlist();
2387 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2390 /* Called when codec completes seek operation
2391 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2392 static void audio_on_codec_seek_complete(void)
2394 logf("%s()", __func__
);
2395 audio_complete_codec_seek();
2399 /* Called when PCM track change has completed
2400 (Q_AUDIO_TRACK_CHANGED) */
2401 static void audio_on_track_changed(void)
2403 /* Finish whatever is pending so that the WPS is in sync */
2404 audio_finalise_track_change();
2406 if (codec_skip_pending
)
2408 /* Codec got ahead completing a short track - complete the
2409 codec's skip and begin the next */
2410 codec_skip_pending
= false;
2411 audio_on_codec_complete(codec_skip_status
);
2415 /* Begin playback from an idle state, transition to a new playlist or
2416 invalidate the buffer and resume (if playing).
2417 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2418 static void audio_start_playback(size_t offset
, unsigned int flags
)
2420 enum play_status old_status
= play_status
;
2422 if (flags
& AUDIO_START_NEWBUF
)
2424 /* Mark the buffer dirty - if not playing, it will be reset next
2426 if (buffer_state
== AUDIOBUF_STATE_INITIALIZED
)
2427 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
2430 if (old_status
!= PLAY_STOPPED
)
2432 logf("%s(%lu): skipping", __func__
, (unsigned long)offset
);
2434 halt_decoding_track(true);
2436 automatic_skip
= false;
2439 if (flags
& AUDIO_START_RESTART
)
2441 /* Clear out some stuff to resume the current track where it
2444 offset
= id3_get(PLAYING_ID3
)->offset
;
2445 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2449 /* This is more-or-less treated as manual track transition */
2450 /* Save resume information for current track */
2451 audio_playlist_track_finish();
2452 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2454 /* Indicate manual track change */
2455 pcmbuf_start_track_change(TRACK_CHANGE_MANUAL
);
2456 wipe_track_metadata(true);
2459 /* Set after track finish event in case skip was in progress */
2460 skip_pending
= TRACK_SKIP_NONE
;
2464 if (flags
& AUDIO_START_RESTART
)
2465 return; /* Must already be playing */
2467 /* Cold playback start from a stopped state */
2468 logf("%s(%lu): starting", __func__
, offset
);
2470 /* Set audio parameters */
2471 #if INPUT_SRC_CAPS != 0
2472 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
2473 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
2475 #ifndef PLATFORM_HAS_VOLUME_CHANGE
2476 sound_set_volume(global_settings
.volume
);
2478 /* Be sure channel is audible */
2479 pcmbuf_fade(false, true);
2481 /* Update our state */
2482 play_status
= PLAY_PLAYING
;
2485 /* Codec's position should be available as soon as it knows it */
2486 position_key
= pcmbuf_get_position_key();
2487 pcmbuf_sync_position_update();
2489 /* Start fill from beginning of playlist */
2490 playlist_peek_offset
= -1;
2491 buf_set_base_handle(-1);
2493 /* Officially playing */
2494 queue_reply(&audio_queue
, 1);
2496 /* Add these now - finish event for the first id3 will most likely be sent
2498 add_event(BUFFER_EVENT_REBUFFER
, false, buffer_event_rebuffer_callback
);
2499 add_event(BUFFER_EVENT_FINISHED
, false, buffer_event_finished_callback
);
2501 if (old_status
== PLAY_STOPPED
)
2503 /* Send coldstart event */
2504 send_event(PLAYBACK_EVENT_START_PLAYBACK
, NULL
);
2507 /* Fill the buffer */
2508 int trackstat
= audio_fill_file_buffer();
2510 if (trackstat
>= LOAD_TRACK_OK
)
2512 /* This is the currently playing track - get metadata, stat */
2513 playing_id3_sync(track_list_current(0), offset
);
2515 if (valid_mp3entry(id3_get(PLAYING_ID3
)))
2517 /* Only if actually changing tracks... */
2518 if (!(flags
& AUDIO_START_RESTART
))
2519 audio_playlist_track_change();
2524 /* Found nothing playable */
2525 audio_handle_track_load_status(trackstat
);
2529 /* Stop playback and enter an idle state
2530 (usually Q_AUDIO_STOP) */
2531 static void audio_stop_playback(void)
2533 logf("%s()", __func__
);
2535 if (play_status
== PLAY_STOPPED
)
2538 bool do_fade
= global_settings
.fade_on_stop
&& filling
!= STATE_ENDED
;
2540 pcmbuf_fade(do_fade
, false);
2542 /* Wait for fade-out */
2543 audio_wait_fade_complete();
2545 /* Stop the codec and unload it */
2546 halt_decoding_track(true);
2550 /* Save resume information - "filling" might have been set to
2551 "STATE_ENDED" by caller in order to facilitate end of playlist */
2552 audio_playlist_track_finish();
2554 skip_pending
= TRACK_SKIP_NONE
;
2555 automatic_skip
= false;
2557 /* Close all tracks and mark them NULL */
2558 remove_event(BUFFER_EVENT_REBUFFER
, buffer_event_rebuffer_callback
);
2559 remove_event(BUFFER_EVENT_FINISHED
, buffer_event_finished_callback
);
2560 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffer_event_buffer_low_callback
);
2562 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2564 /* Update our state */
2566 play_status
= PLAY_STOPPED
;
2568 wipe_track_metadata(true);
2571 filling
= STATE_IDLE
;
2575 /* Pause the playback of the current track
2577 static void audio_on_pause(bool pause
)
2579 logf("%s(%s)", __func__
, pause
? "true" : "false");
2581 if (play_status
== PLAY_STOPPED
|| pause
== (play_status
== PLAY_PAUSED
))
2584 play_status
= pause
? PLAY_PAUSED
: PLAY_PLAYING
;
2586 if (!pause
&& codec_skip_pending
)
2588 /* Actually do the skip that is due - resets the status flag */
2589 audio_on_codec_complete(codec_skip_status
);
2592 bool do_fade
= global_settings
.fade_on_stop
;
2594 pcmbuf_fade(do_fade
, !pause
);
2596 if (!ff_rw_mode
&& !(do_fade
&& pause
))
2598 /* Not in ff/rw mode - can actually change the audio state now */
2599 pcmbuf_pause(pause
);
2603 /* Skip a certain number of tracks forwards or backwards
2605 static void audio_on_skip(void)
2609 /* Eat the delta to keep it synced, even if not playing */
2610 int toskip
= skip_offset
;
2613 logf("%s(): %d", __func__
, toskip
);
2617 if (play_status
== PLAY_STOPPED
)
2620 /* Force codec to abort this track */
2621 halt_decoding_track(true);
2623 /* Kill the ff/rw halt */
2627 automatic_skip
= false;
2629 /* If there was an auto skip in progress, there will be residual
2630 advancement of the playlist and/or track list so compensation will be
2631 required in order to end up in the right spot */
2632 int track_list_delta
= toskip
;
2633 int playlist_delta
= toskip
;
2635 if (skip_pending
!= TRACK_SKIP_NONE
)
2637 if (skip_pending
!= TRACK_SKIP_AUTO_END_PLAYLIST
)
2640 if (skip_pending
== TRACK_SKIP_AUTO_NEW_PLAYLIST
)
2644 audio_playlist_track_finish();
2645 skip_pending
= TRACK_SKIP_NONE
;
2647 /* Update the playlist current track now */
2649 while ((pl_retval
= playlist_next(playlist_delta
)) < 0)
2653 /* Some variety of fatal error while updating playlist */
2654 filling
= STATE_ENDED
;
2655 audio_stop_playback();
2659 /* Manual skip out of range (because the playlist wasn't updated
2660 yet by us and so the check in audio_skip returned 'ok') - bring
2662 int d
= toskip
< 0 ? 1 : -1;
2664 while (!playlist_check(playlist_delta
))
2666 if (playlist_delta
== d
)
2668 /* Had to move the opposite direction to correct, which is
2669 wrong - this is the end */
2670 filling
= STATE_ENDED
;
2671 audio_stop_playback();
2675 playlist_delta
+= d
;
2676 track_list_delta
+= d
;
2680 /* Adjust things by how much the playlist was manually moved */
2681 playlist_peek_offset
-= playlist_delta
;
2683 struct track_info
*info
= track_list_advance_current(track_list_delta
);
2684 int trackstat
= LOAD_TRACK_OK
;
2686 if (!info
|| info
->audio_hid
< 0)
2688 /* We don't know the next track thus we know we don't have it */
2689 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2692 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2695 /* Skip to the next/previous directory
2696 (Q_AUDIO_DIR_SKIP) */
2697 static void audio_on_dir_skip(int direction
)
2699 logf("%s(%d)", __func__
, direction
);
2705 if (play_status
== PLAY_STOPPED
)
2708 /* Force codec to abort this track */
2709 halt_decoding_track(true);
2711 /* Kill the ff/rw halt */
2715 automatic_skip
= false;
2717 audio_playlist_track_finish();
2719 /* Unless automatic and gapless, skips do not pend */
2720 skip_pending
= TRACK_SKIP_NONE
;
2722 /* Regardless of the return value we need to rebuffer. If it fails the old
2723 playlist will resume, else the next dir will start playing. */
2724 playlist_next_dir(direction
);
2726 wipe_track_metadata(false);
2728 int trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2730 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2732 /* The day the music died - finish-off whatever is playing and call it
2734 audio_monitor_end_of_playlist();
2738 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2741 /* Enter seek mode in order to start a seek
2742 (Q_AUDIO_PRE_FF_REWIND) */
2743 static void audio_on_pre_ff_rewind(void)
2745 logf("%s()", __func__
);
2747 if (play_status
== PLAY_STOPPED
|| ff_rw_mode
)
2752 audio_wait_fade_complete();
2754 if (play_status
== PLAY_PAUSED
)
2760 /* Seek the playback of the current track to the specified time
2761 (Q_AUDIO_FF_REWIND) */
2762 static void audio_on_ff_rewind(long time
)
2764 logf("%s(%ld)", __func__
, time
);
2766 if (play_status
== PLAY_STOPPED
)
2769 enum track_skip_type pending
= skip_pending
;
2773 case TRACK_SKIP_NONE
: /* The usual case */
2774 case TRACK_SKIP_AUTO
: /* Have to back it out (fun!) */
2775 case TRACK_SKIP_AUTO_END_PLAYLIST
: /* Still have the last codec used */
2777 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
2778 struct mp3entry
*ci_id3
= id3_get(CODEC_ID3
);
2780 automatic_skip
= false;
2782 /* Send event before clobbering the time */
2783 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2784 then skipping back to this track resumes properly. Something else
2785 should be sent. We're not _really_ finishing the track are we? */
2787 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
2789 id3
->elapsed
= time
;
2790 queue_reply(&audio_queue
, 1);
2792 bool haltres
= halt_decoding_track(pending
== TRACK_SKIP_AUTO
);
2794 /* Need this set in case ff/rw mode + error but _after_ the codec
2795 halt that will reset it */
2796 codec_seeking
= true;
2798 /* If in transition, key will have changed - sync to it */
2799 position_key
= pcmbuf_get_position_key();
2801 if (pending
== TRACK_SKIP_AUTO
)
2803 if (!track_list_advance_current(-1))
2805 /* Not in list - must rebuffer at the current playlist index */
2806 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1)
2809 /* Codec is stopped */
2815 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2816 rebuffer is needed */
2817 skip_pending
= TRACK_SKIP_NONE
;
2818 struct track_info
*cur_info
= track_list_current(0);
2820 /* Track must complete the loading _now_ since a codec and audio
2821 handle are needed in order to do the seek */
2822 if (cur_info
->audio_hid
< 0 &&
2823 audio_finish_load_track(cur_info
) != LOAD_TRACK_READY
)
2825 /* Call above should push any load sequence - no need for
2826 halt_decoding_track here if no skip was pending here because
2827 there would not be a codec started if no audio handle was yet
2832 if (pending
== TRACK_SKIP_AUTO
)
2834 if (!bufreadid3(cur_info
->id3_hid
, ci_id3
) ||
2835 !audio_init_codec(cur_info
, ci_id3
))
2837 /* We should have still been able to get it - skip it and move
2838 onto the next one - like it or not this track is broken */
2842 /* Set the codec API to the correct metadata and track info */
2843 ci
.audio_hid
= cur_info
->audio_hid
;
2844 ci
.filesize
= cur_info
->filesize
;
2845 buf_set_base_handle(cur_info
->audio_hid
);
2850 /* If codec must be (re)started, reset the offset */
2858 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2860 /* We cannot do this because the playlist must be reversed by one
2861 and it doesn't always return the same song when going backwards
2862 across boundaries as forwards (either because of randomization
2863 or inconsistency in deciding what the previous track should be),
2864 therefore the whole operation would often end up as nonsense -
2865 lock out seeking for a couple seconds */
2867 /* Sure as heck cancel seek mode too! */
2868 audio_ff_rewind_end();
2873 /* Won't see this */
2877 if (play_status
== PLAY_STOPPED
)
2879 /* Playback ended because of an error completing a track load */
2883 /* Always fake it as a codec start error which will handle mode
2884 cancellations and skip to the next track */
2885 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2888 /* Invalidates all but currently playing track
2890 static void audio_on_audio_flush(void)
2892 logf("%s", __func__
);
2894 if (track_list_empty())
2895 return; /* Nothing to flush out */
2897 switch (skip_pending
)
2899 case TRACK_SKIP_NONE
:
2900 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2901 /* Remove all but the currently playing track from the list and
2902 refill after that */
2903 track_list_clear(TRACK_LIST_KEEP_CURRENT
);
2904 playlist_peek_offset
= 0;
2905 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2906 audio_update_and_announce_next_track(NULL
);
2908 /* Ignore return since it's about the next track, not this one */
2909 audio_fill_file_buffer();
2911 if (skip_pending
== TRACK_SKIP_NONE
)
2914 /* There's now a track after this one now - convert to auto skip -
2915 no skip should pend right now because multiple flush messages can
2916 be fired which would cause a restart in the below cases */
2917 skip_pending
= TRACK_SKIP_NONE
;
2918 audio_clear_track_notifications();
2919 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_OK
);
2922 case TRACK_SKIP_AUTO
:
2923 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2924 /* Precisely removing what it already decoded for the next track is
2925 not possible so a restart is required in order to continue the
2926 currently playing track without the now invalid future track
2928 audio_start_playback(0, AUDIO_START_RESTART
);
2931 default: /* Nothing else is a state */
2936 #ifdef AUDIO_HAVE_RECORDING
2937 /* Load the requested encoder type
2938 (Q_AUDIO_LOAD_ENCODER) */
2939 static void audio_on_load_encoder(int afmt
)
2943 if (play_status
!= PLAY_STOPPED
)
2944 audio_stop_playback(); /* Can't load both types at once */
2946 codec_unload(); /* Encoder still loaded, stop and unload it */
2948 if (afmt
!= AFMT_UNKNOWN
)
2950 res
= codec_load(-1, afmt
| CODEC_TYPE_ENCODER
);
2952 codec_go(); /* These are run immediately */
2955 queue_reply(&audio_queue
, res
);
2957 #endif /* AUDIO_HAVE_RECORDING */
2959 static void audio_thread(void)
2961 struct queue_event ev
;
2971 case STATE_END_OF_PLAYLIST
:
2972 if (buf_get_watermark() == 0)
2974 /* End of buffering for now, let's calculate the watermark,
2975 register for a low buffer event and unboost */
2976 audio_update_filebuf_watermark(0);
2977 add_event(BUFFER_EVENT_BUFFER_LOW
, true,
2978 buffer_event_buffer_low_callback
);
2981 case STATE_FINISHED
:
2982 /* All data was buffered */
2987 if (audio_pcmbuf_track_change_scan())
2989 /* Transfer notification to audio queue event */
2990 ev
.id
= Q_AUDIO_TRACK_CHANGED
;
2995 /* If doing auto skip, poll pcmbuf track notifications a bit
2996 faster to promply detect the transition */
2997 queue_wait_w_tmo(&audio_queue
, &ev
,
2998 skip_pending
== TRACK_SKIP_NONE
?
3005 queue_wait(&audio_queue
, &ev
);
3007 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3010 #ifdef AUDIO_HAVE_RECORDING
3011 /* Must monitor the encoder message for recording so it can remove
3012 it if we process the insertion before it does. It cannot simply
3013 be removed from under recording however. */
3014 case Q_AUDIO_LOAD_ENCODER
:
3017 case SYS_USB_DISCONNECTED
:
3018 filling
= STATE_IDLE
;
3022 if (filling
== STATE_USB
)
3025 #endif /* CONFIG_PLATFORM */
3030 /** Codec and track change messages **/
3031 case Q_AUDIO_CODEC_COMPLETE
:
3032 /* Codec is done processing track and has gone idle */
3033 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev
.data
);
3034 audio_on_codec_complete(ev
.data
);
3037 case Q_AUDIO_CODEC_SEEK_COMPLETE
:
3038 /* Codec is done seeking */
3039 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
3040 audio_on_codec_seek_complete();
3043 case Q_AUDIO_TRACK_CHANGED
:
3044 /* PCM track change done */
3045 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3046 audio_on_track_changed();
3049 /** Control messages **/
3051 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3052 audio_start_playback(ev
.data
, 0);
3056 LOGFQUEUE("audio < Q_AUDIO_STOP");
3057 audio_stop_playback();
3059 queue_clear(&audio_queue
);
3063 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3064 audio_on_pause(ev
.data
);
3068 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3072 case Q_AUDIO_DIR_SKIP
:
3073 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3074 audio_on_dir_skip(ev
.data
);
3077 case Q_AUDIO_PRE_FF_REWIND
:
3078 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3079 audio_on_pre_ff_rewind();
3082 case Q_AUDIO_FF_REWIND
:
3083 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3084 audio_on_ff_rewind(ev
.data
);
3088 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev
.data
);
3089 audio_on_audio_flush();
3092 /** Buffering messages **/
3093 case Q_AUDIO_BUFFERING
:
3094 /* some buffering event */
3095 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev
.data
);
3096 audio_on_buffering(ev
.data
);
3099 case Q_AUDIO_FILL_BUFFER
:
3100 /* continue buffering next track */
3101 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3102 audio_on_fill_buffer();
3105 case Q_AUDIO_FINISH_LOAD_TRACK
:
3106 /* metadata is buffered */
3107 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3108 audio_on_finish_load_track(ev
.data
);
3111 case Q_AUDIO_HANDLE_FINISHED
:
3112 /* some other type is buffered */
3113 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3114 audio_on_handle_finished(ev
.data
);
3117 /** Miscellaneous messages **/
3118 case Q_AUDIO_REMAKE_AUDIO_BUFFER
:
3119 /* buffer needs to be reinitialized */
3120 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3121 audio_start_playback(0, AUDIO_START_RESTART
| AUDIO_START_NEWBUF
);
3124 #ifdef HAVE_DISK_STORAGE
3125 case Q_AUDIO_UPDATE_WATERMARK
:
3126 /* buffering watermark needs updating */
3127 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev
.data
);
3128 audio_update_filebuf_watermark(ev
.data
);
3130 #endif /* HAVE_DISK_STORAGE */
3132 #ifdef AUDIO_HAVE_RECORDING
3133 case Q_AUDIO_LOAD_ENCODER
:
3134 /* load an encoder for recording */
3135 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev
.data
);
3136 audio_on_load_encoder(ev
.data
);
3138 #endif /* AUDIO_HAVE_RECORDING */
3140 case SYS_USB_CONNECTED
:
3141 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3142 audio_stop_playback();
3143 #ifdef PLAYBACK_VOICE
3146 filling
= STATE_USB
;
3147 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3151 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3155 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3162 /* --- Buffering callbacks --- */
3164 /* Called when fullness is below the watermark level */
3165 static void buffer_event_buffer_low_callback(void *data
)
3167 logf("low buffer callback");
3168 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3169 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_BUFFER_LOW
);
3173 /* Called when handles must be discarded in order to buffer new data */
3174 static void buffer_event_rebuffer_callback(void *data
)
3176 logf("rebuffer callback");
3177 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3178 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_REBUFFER
);
3182 /* A handle has completed buffering and all required data is available */
3183 static void buffer_event_finished_callback(void *data
)
3185 int hid
= *(const int *)data
;
3186 const enum data_type htype
= buf_handle_data_type(hid
);
3188 logf("handle %d finished buffering (type:%u)", hid
, (unsigned)htype
);
3190 /* Limit queue traffic */
3194 /* The metadata handle for the last loaded track has been buffered.
3195 We can ask the audio thread to load the rest of the track's data. */
3196 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid
);
3197 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK
, hid
);
3200 case TYPE_PACKET_AUDIO
:
3201 /* Strip any useless trailing tags that are left. */
3204 case TYPE_ATOMIC_AUDIO
:
3205 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid
);
3206 audio_queue_post(Q_AUDIO_HANDLE_FINISHED
, hid
);
3210 /* Don't care to know about these */
3216 /** -- Codec callbacks -- **/
3218 /* Update elapsed time for next PCM insert */
3219 void audio_codec_update_elapsed(unsigned long elapsed
)
3221 #ifdef AB_REPEAT_ENABLE
3222 ab_position_report(elapsed
);
3224 /* Save in codec's id3 where it is used at next pcm insert */
3225 id3_get(CODEC_ID3
)->elapsed
= elapsed
;
3228 /* Update offset for next PCM insert */
3229 void audio_codec_update_offset(size_t offset
)
3231 /* Save in codec's id3 where it is used at next pcm insert */
3232 id3_get(CODEC_ID3
)->offset
= offset
;
3235 /* Codec has finished running */
3236 void audio_codec_complete(int status
)
3238 #ifdef AB_REPEAT_ENABLE
3239 if (status
>= CODEC_OK
)
3241 /* Normal automatic skip */
3242 ab_end_of_track_report();
3246 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status
);
3247 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, status
);
3250 /* Codec has finished seeking */
3251 void audio_codec_seek_complete(void)
3253 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_SEEK_COMPLETE");
3254 audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE
, 0);
3258 /** --- Pcmbuf callbacks --- **/
3260 /* Update the elapsed and offset from the information cached during the
3261 PCM buffer insert */
3262 void audio_pcmbuf_position_callback(unsigned long elapsed
, off_t offset
,
3265 if (key
== position_key
)
3267 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
3268 id3
->elapsed
= elapsed
;
3269 id3
->offset
= offset
;
3273 /* Synchronize position info to the codec's */
3274 void audio_pcmbuf_sync_position(void)
3276 audio_pcmbuf_position_callback(ci
.id3
->elapsed
, ci
.id3
->offset
,
3277 pcmbuf_get_position_key());
3280 /* Post message from pcmbuf that the end of the previous track has just
3282 void audio_pcmbuf_track_change(bool pcmbuf
)
3286 /* Notify of the change in special-purpose semaphore object */
3287 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3288 audio_pcmbuf_track_change_post();
3292 /* Safe to post directly to the queue */
3293 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3294 audio_queue_post(Q_AUDIO_TRACK_CHANGED
, 0);
3298 /* May pcmbuf start PCM playback when the buffer is full enough? */
3299 bool audio_pcmbuf_may_play(void)
3301 return play_status
== PLAY_PLAYING
&& !ff_rw_mode
;
3305 /** -- External interfaces -- **/
3307 /* Return the playback and recording status */
3308 int audio_status(void)
3310 unsigned int ret
= play_status
;
3312 #ifdef AUDIO_HAVE_RECORDING
3313 /* Do this here for constitency with mpeg.c version */
3314 ret
|= pcm_rec_status();
3320 /* Clear all accumulated audio errors for playback and recording */
3321 void audio_error_clear(void)
3323 #ifdef AUDIO_HAVE_RECORDING
3324 pcm_rec_error_clear();
3328 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3329 bool audio_peek_track(struct mp3entry
*id3
, int offset
)
3331 bool retval
= false;
3335 if (play_status
!= PLAY_STOPPED
)
3337 id3
->path
[0] = '\0'; /* Null path means it should be filled now */
3338 retval
= audio_get_track_metadata(offset
+ skip_offset
, id3
) &&
3339 id3
->path
[0] != '\0';
3347 /* Return the mp3entry for the currently playing track */
3348 struct mp3entry
* audio_current_track(void)
3350 struct mp3entry
*id3
;
3354 #ifdef AUDIO_FAST_SKIP_PREVIEW
3355 if (skip_offset
!= 0)
3357 /* This is a peekahead */
3358 id3
= id3_get(PLAYING_PEEK_ID3
);
3359 audio_peek_track(id3
, 0);
3365 id3
= id3_get(PLAYING_ID3
);
3366 audio_get_track_metadata(0, id3
);
3374 /* Obtains the mp3entry for the next track from the current */
3375 struct mp3entry
* audio_next_track(void)
3377 struct mp3entry
*id3
= id3_get(NEXTTRACK_ID3
);
3381 #ifdef AUDIO_FAST_SKIP_PREVIEW
3382 if (skip_offset
!= 0)
3384 /* This is a peekahead */
3385 if (!audio_peek_track(id3
, 1))
3392 if (!audio_get_track_metadata(1, id3
))
3401 /* Start playback at the specified offset */
3402 void audio_play(long offset
)
3406 #ifdef PLAYBACK_VOICE
3407 /* Truncate any existing voice output so we don't have spelling
3408 * etc. over the first part of the played track */
3409 talk_force_shutup();
3412 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
3413 audio_queue_send(Q_AUDIO_PLAY
, offset
);
3416 /* Stop playback if playing */
3417 void audio_stop(void)
3419 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3420 audio_queue_send(Q_AUDIO_STOP
, 0);
3423 /* Pause playback if playing */
3424 void audio_pause(void)
3426 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3427 audio_queue_send(Q_AUDIO_PAUSE
, true);
3430 /* This sends a stop message and the audio thread will dump all its
3431 subsequent messages */
3432 void audio_hard_stop(void)
3435 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3436 audio_queue_send(Q_AUDIO_STOP
, 1);
3437 #ifdef PLAYBACK_VOICE
3440 if (audiobuf_handle
> 0)
3441 audiobuf_handle
= core_free(audiobuf_handle
);
3444 /* Resume playback if paused */
3445 void audio_resume(void)
3447 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3448 audio_queue_send(Q_AUDIO_PAUSE
, false);
3451 /* Skip the specified number of tracks forward or backward from the current */
3452 void audio_skip(int offset
)
3456 /* If offset has to be backed-out to stay in range, no skip is done */
3457 int accum
= skip_offset
+ offset
;
3459 while (offset
!= 0 && !playlist_check(accum
))
3461 offset
+= offset
< 0 ? 1 : -1;
3462 accum
= skip_offset
+ offset
;
3467 /* Accumulate net manual skip count since the audio thread last
3469 skip_offset
= accum
;
3471 system_sound_play(SOUND_TRACK_SKIP
);
3473 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset
);
3475 #ifdef AUDIO_FAST_SKIP_PREVIEW
3476 /* Do this before posting so that the audio thread can correct us
3477 when things settle down - additionally, if audio gets a message
3478 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3479 handler a skip event with the correct info but doesn't skip */
3480 send_event(PLAYBACK_EVENT_TRACK_SKIP
, NULL
);
3481 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3483 /* Playback only needs the final state even if more than one is
3484 processed because it wasn't removed in time */
3485 queue_remove_from_head(&audio_queue
, Q_AUDIO_SKIP
);
3486 audio_queue_post(Q_AUDIO_SKIP
, 0);
3490 /* No more tracks */
3491 system_sound_play(SOUND_TRACK_NO_MORE
);
3497 /* Skip one track forward from the current */
3498 void audio_next(void)
3503 /* Skip one track backward from the current */
3504 void audio_prev(void)
3509 /* Move one directory forward */
3510 void audio_next_dir(void)
3512 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3513 audio_queue_post(Q_AUDIO_DIR_SKIP
, 1);
3516 /* Move one directory backward */
3517 void audio_prev_dir(void)
3519 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3520 audio_queue_post(Q_AUDIO_DIR_SKIP
, -1);
3523 /* Pause playback in order to start a seek that flushes the old audio */
3524 void audio_pre_ff_rewind(void)
3526 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3527 audio_queue_post(Q_AUDIO_PRE_FF_REWIND
, 0);
3530 /* Seek to the new time in the current track */
3531 void audio_ff_rewind(long time
)
3533 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3534 audio_queue_post(Q_AUDIO_FF_REWIND
, time
);
3537 /* Clear all but the currently playing track then rebuffer */
3538 void audio_flush_and_reload_tracks(void)
3540 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3541 audio_queue_post(Q_AUDIO_FLUSH
, 0);
3544 /* Return the pointer to the main audio buffer, optionally preserving
3546 unsigned char * audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
3550 if (audio_is_initialized
)
3554 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3556 if (buffer_size
== NULL
)
3558 /* Special case for talk_init to use since it already knows it's
3560 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3564 /* make sure buffer is freed and re-allocated to simplify code below
3565 * (audio_hard_stop() likely has done that already) */
3566 if (audiobuf_handle
> 0)
3567 audiobuf_handle
= core_free(audiobuf_handle
);
3569 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
3570 buf
= core_get_data(audiobuf_handle
);
3572 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
3573 || !talk_voice_required())
3575 logf("get buffer: talk, audio");
3576 /* Ok to use everything from audiobuf - voice is loaded,
3577 the talk buffer is not needed because voice isn't being used, or
3578 could be AUDIOBUF_STATE_TRASHED already. If state is
3579 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3580 written without the caller knowing what's going on. Changing certain
3581 settings may move it to a worse condition but the memory in use by
3582 something else will remain undisturbed.
3584 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
3586 talk_buffer_steal();
3587 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3592 logf("get buffer: audio");
3593 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3594 still AUDIOBUF_STATE_INITIALIZED */
3595 /* Skip talk buffer and move pcm buffer to end to maximize available
3596 contiguous memory - no audio running means voice will not need the
3598 size_t talkbuf_size
;
3599 buf
+= talkbuf_size
= talkbuf_init(buf
);
3600 filebuflen
-= talkbuf_size
;
3601 filebuflen
-= voicebuf_init(buf
+ filebuflen
);
3603 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
3606 *buffer_size
= filebuflen
;
3610 #ifdef HAVE_RECORDING
3611 /* Stop audio, voice and obtain all available buffer space */
3612 unsigned char * audio_get_recording_buffer(size_t *buffer_size
)
3615 return audio_get_buffer(true, buffer_size
);
3617 #endif /* HAVE_RECORDING */
3619 /* Restore audio buffer to a particular state (one more valid than the current
3621 bool audio_restore_playback(int type
)
3625 case AUDIO_WANT_PLAYBACK
:
3626 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
3627 audio_reset_buffer();
3629 case AUDIO_WANT_VOICE
:
3630 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
3631 audio_reset_buffer();
3639 /** --- Miscellaneous public interfaces --- **/
3641 #ifdef HAVE_ALBUMART
3642 /* Return which album art handle is current for the user in the given slot */
3643 int playback_current_aa_hid(int slot
)
3645 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3647 struct track_info
*info
= track_list_user_current(skip_offset
);
3649 if (!info
&& abs(skip_offset
) <= 1)
3651 /* Give the actual position a go */
3652 info
= track_list_user_current(0);
3656 return info
->aa_hid
[slot
];
3659 return ERR_HANDLE_NOT_FOUND
;
3662 /* Find an album art slot that doesn't match the dimensions of another that
3663 is already claimed - increment the use count if it is */
3664 int playback_claim_aa_slot(struct dim
*dim
)
3668 /* First try to find a slot already having the size to reuse it since we
3669 don't want albumart of the same size buffered multiple times */
3672 struct albumart_slot
*slot
= &albumart_slots
[i
];
3674 if (slot
->dim
.width
== dim
->width
&&
3675 slot
->dim
.height
== dim
->height
)
3682 /* Size is new, find a free slot */
3685 if (!albumart_slots
[i
].used
)
3687 albumart_slots
[i
].used
++;
3688 albumart_slots
[i
].dim
= *dim
;
3693 /* Sorry, no free slot */
3697 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3698 void playback_release_aa_slot(int slot
)
3700 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3702 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
3704 if (aa_slot
->used
> 0)
3708 #endif /* HAVE_ALBUMART */
3711 #ifdef HAVE_RECORDING
3712 /* Load an encoder and run it */
3713 bool audio_load_encoder(int afmt
)
3715 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3716 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
3717 return audio_queue_send(Q_AUDIO_LOAD_ENCODER
, afmt
) != 0;
3724 /* Stop an encoder and unload it */
3725 void audio_remove_encoder(void)
3727 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3728 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3729 audio_queue_send(Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
3732 #endif /* HAVE_RECORDING */
3734 /* Is an automatic skip in progress? If called outside transition callbacks,
3735 indicates the last skip type at the time it was processed and isn't very
3737 bool audio_automatic_skip(void)
3739 return automatic_skip
;
3742 /* Would normally calculate byte offset from an elapsed time but is not
3744 int audio_get_file_pos(void)
3749 /* Return the elapsed time of the track previous to the current */
3750 unsigned long audio_prev_elapsed(void)
3752 return prev_track_elapsed
;
3755 /* Return total file buffer length after accounting for the talk buf */
3756 size_t audio_get_filebuflen(void)
3758 return buf_length();
3761 /* How many tracks exist on the buffer - full or partial */
3762 int audio_track_count(void)
3763 __attribute__((alias("track_list_count")));
3765 /* Return total ringbuffer space occupied - ridx to widx */
3766 long audio_filebufused(void)
3772 /** -- Settings -- **/
3774 /* Enable or disable cuesheet support and allocate/don't allocate the
3775 extra associated resources */
3776 void audio_set_cuesheet(int enable
)
3778 if (play_status
== PLAY_STOPPED
|| !enable
!= !get_current_cuesheet())
3780 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3781 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3785 #ifdef HAVE_DISK_STORAGE
3786 /* Set the audio antiskip buffer margin by index */
3787 void audio_set_buffer_margin(int setting
)
3789 static const unsigned short lookup
[] =
3790 { 5, 15, 30, 60, 120, 180, 300, 600 };
3792 if ((unsigned)setting
>= ARRAYLEN(lookup
))
3795 logf("buffer margin: %u", (unsigned)lookup
[setting
]);
3797 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3798 (unsigned)lookup
[setting
]);
3799 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK
, lookup
[setting
]);
3801 #endif /* HAVE_DISK_STORAGE */
3803 #ifdef HAVE_CROSSFADE
3804 /* Take necessary steps to enable or disable the crossfade setting */
3805 void audio_set_crossfade(int enable
)
3807 /* Tell it the next setting to use */
3808 pcmbuf_request_crossfade_enable(enable
);
3810 /* Return if size hasn't changed or this is too early to determine
3811 which in the second case there's no way we could be playing
3813 if (!pcmbuf_is_same_size())
3815 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3816 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3819 #endif /* HAVE_CROSSFADE */
3822 /** -- Startup -- **/
3824 /* Initialize the audio system - called from init() in main.c */
3825 void audio_init(void)
3827 /* Can never do this twice */
3828 if (audio_is_initialized
)
3830 logf("audio: already initialized");
3834 logf("audio: initializing");
3836 /* Initialize queues before giving control elsewhere in case it likes
3837 to send messages. Thread creation will be delayed however so nothing
3838 starts running until ready if something yields such as talk_init. */
3839 queue_init(&audio_queue
, true);
3841 mutex_init(&id3_mutex
);
3845 codec_thread_init();
3847 /* This thread does buffer, so match its priority */
3848 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
3849 sizeof(audio_stack
), 0, audio_thread_name
3850 IF_PRIO(, MIN(PRIORITY_BUFFERING
, PRIORITY_USER_INTERFACE
))
3853 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
3856 #ifdef PLAYBACK_VOICE
3857 voice_thread_init();
3860 /* audio_reset_buffer must know the size of voice buffer so init
3864 #ifdef HAVE_CROSSFADE
3865 /* Set crossfade setting for next buffer init which should be about... */
3866 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
3869 /* Initialize the buffering system */
3872 /* ...now! Set up the buffers */
3873 audio_reset_buffer();
3875 /* Probably safe to say */
3876 audio_is_initialized
= true;
3878 sound_settings_apply();
3879 #ifdef HAVE_DISK_STORAGE
3880 audio_set_buffer_margin(global_settings
.buffer_margin
);