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 bool playing
= (audio_status() & AUDIO_STATUS_PLAY
) == AUDIO_STATUS_PLAY
;
859 /* There's one problem with stoping and resuming: If it happens in a too
860 * frequent fashion, the codecs lose the resume postion and playback
861 * begins from the beginning.
862 * To work around use queue_post() to effectively delay the resume in case
863 * we're called another time. However this has another problem: id3->offset
864 * gets zero since playback is stopped. Therefore, try to peek at the
865 * queue_post from the last call to get the correct offset. This also
866 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
868 bool play_queued
= queue_peek_ex(&audio_queue
, &ev
, QPEEK_REMOVE_EVENTS
, filter_list
);
870 if (playing
&& offset
> 0) /* current id3->offset is king */
873 /* don't call audio_hard_stop() as it frees this handle */
874 if (thread_self() == audio_thread_id
)
875 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
876 * if we're in the audio thread */
877 audio_stop_playback();
878 queue_clear(&audio_queue
);
881 audio_queue_send(Q_AUDIO_STOP
, 1);
882 #ifdef PLAYBACK_VOICE
885 /* we should be free to change the buffer now
886 * set final buffer size before calling audio_reset_buffer_noalloc()
887 * (now it's the total size, the call will subtract voice etc) */
889 switch (hints
& BUFLIB_SHRINK_POS_MASK
)
891 case BUFLIB_SHRINK_POS_BACK
:
892 core_shrink(handle
, start
, size
);
893 audio_reset_buffer_noalloc(start
);
895 case BUFLIB_SHRINK_POS_FRONT
:
896 core_shrink(handle
, start
+ wanted_size
, size
);
897 audio_reset_buffer_noalloc(start
+ wanted_size
);
900 if (playing
|| play_queued
)
902 /* post, to make subsequent calls not break the resume position */
903 audio_queue_post(Q_AUDIO_PLAY
, ev
.data
);
909 static struct buflib_callbacks ops
= {
910 .move_callback
= NULL
,
911 .shrink_callback
= shrink_callback
,
914 static void audio_reset_buffer(void)
916 if (audiobuf_handle
> 0)
918 core_free(audiobuf_handle
);
921 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
922 unsigned char *filebuf
= core_get_data(audiobuf_handle
);
924 audio_reset_buffer_noalloc(filebuf
);
927 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
928 static void audio_update_filebuf_watermark(int seconds
)
932 #ifdef HAVE_DISK_STORAGE
933 int spinup
= ata_spinup_time();
937 /* By current setting */
938 seconds
= buffer_margin
;
943 buffer_margin
= seconds
;
945 if (buf_get_watermark() == 0)
947 /* Write a watermark only if the audio thread already did so for
948 itself or it will fail to set the event and the watermark - if
949 it hasn't yet, it will use the new setting when it does */
955 seconds
+= (spinup
/ HZ
) + 1;
959 seconds
+= buffer_margin
;
965 /* Watermark is a function of the bitrate of the last track in the buffer */
966 struct mp3entry
*id3
= NULL
;
967 struct track_info
*info
= track_list_last(0);
970 id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
974 if (get_audio_base_data_type(id3
->codectype
) == TYPE_PACKET_AUDIO
)
976 bytes
= id3
->bitrate
* (1000/8) * seconds
;
980 /* Bitrate has no meaning to buffering margin for atomic audio -
981 rebuffer when it's the only track left unless it's the only
982 track that fits, in which case we should avoid constant buffer
984 if (track_list_count() > 1)
985 bytes
= info
->filesize
+ 1;
990 /* Then set the minimum - this should not occur anyway */
991 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
992 track_list
.start
, track_list
.current
, track_list
.end
);
995 /* Actually setting zero disables the notification and we use that
996 to detect that it has been reset */
997 buf_set_watermark(MAX(bytes
, 1));
998 logf("fwmark: %lu", (unsigned long)bytes
);
1002 /** -- Track change notification -- **/
1004 /* Check the pcmbuf track changes and return write the message into the event
1006 static inline bool audio_pcmbuf_track_change_scan(void)
1008 if (track_change
.out
!= track_change
.in
)
1017 /* Clear outstanding track change posts */
1018 static inline void audio_pcmbuf_track_change_clear(void)
1020 track_change
.out
= track_change
.in
;
1023 /* Post a track change notification - called by audio ISR */
1024 static inline void audio_pcmbuf_track_change_post(void)
1030 /** --- Helper functions --- **/
1032 /* Removes messages that might end up in the queue before or while processing
1033 a manual track change. Responding to them would be harmful since they
1034 belong to a previous track's playback period. Anything that would generate
1035 the stale messages must first be put into a state where it will not do so.
1037 static void audio_clear_track_notifications(void)
1039 static const long filter_list
[][2] =
1041 /* codec messages */
1042 { Q_AUDIO_CODEC_SEEK_COMPLETE
, Q_AUDIO_CODEC_COMPLETE
},
1043 /* track change messages */
1044 { Q_AUDIO_TRACK_CHANGED
, Q_AUDIO_TRACK_CHANGED
},
1047 const int filter_count
= ARRAYLEN(filter_list
) - 1;
1049 /* Remove any pcmbuf notifications */
1050 pcmbuf_monitor_track_change(false);
1051 audio_pcmbuf_track_change_clear();
1053 /* Scrub the audio queue of the old mold */
1054 while (queue_peek_ex(&audio_queue
, NULL
,
1055 filter_count
| QPEEK_REMOVE_EVENTS
,
1058 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1062 /* Takes actions based upon track load status codes */
1063 static void audio_handle_track_load_status(int trackstat
)
1067 case LOAD_TRACK_ERR_NO_MORE
:
1068 if (track_list_count() > 0)
1071 case LOAD_TRACK_ERR_START_CODEC
:
1072 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_ERROR
);
1080 /* Announce the end of playing the current track */
1081 static void audio_playlist_track_finish(void)
1083 struct mp3entry
*ply_id3
= id3_get(PLAYING_ID3
);
1084 struct mp3entry
*id3
= valid_mp3entry(ply_id3
);
1086 playlist_update_resume_info(filling
== STATE_ENDED
? NULL
: id3
);
1090 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
1091 prev_track_elapsed
= id3
->elapsed
;
1095 prev_track_elapsed
= 0;
1099 /* Announce the beginning of the new track */
1100 static void audio_playlist_track_change(void)
1102 struct mp3entry
*id3
= valid_mp3entry(id3_get(PLAYING_ID3
));
1105 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, id3
);
1107 position_key
= pcmbuf_get_position_key();
1109 playlist_update_resume_info(id3
);
1112 /* Change the data for the next track and send the event */
1113 static void audio_update_and_announce_next_track(const struct mp3entry
*id3_next
)
1115 id3_write_locked(NEXTTRACK_ID3
, id3_next
);
1116 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
,
1117 id3_get(NEXTTRACK_ID3
));
1120 /* Bring the user current mp3entry up to date and set a new offset for the
1121 buffered metadata */
1122 static void playing_id3_sync(struct track_info
*user_info
, off_t offset
)
1126 struct mp3entry
*id3
= bufgetid3(user_info
->id3_hid
);
1127 struct mp3entry
*playing_id3
= id3_get(PLAYING_ID3
);
1131 unsigned long e
= playing_id3
->elapsed
;
1132 unsigned long o
= playing_id3
->offset
;
1134 id3_write(PLAYING_ID3
, id3
);
1138 playing_id3
->elapsed
= e
;
1139 playing_id3
->offset
= o
;
1146 id3
->offset
= offset
;
1151 /* Wipe-out track metadata - current is optional */
1152 static void wipe_track_metadata(bool current
)
1157 id3_write(PLAYING_ID3
, NULL
);
1159 id3_write(NEXTTRACK_ID3
, NULL
);
1160 id3_write(UNBUFFERED_ID3
, NULL
);
1165 /* Called when buffering is completed on the last track handle */
1166 static void filling_is_finished(void)
1168 logf("last track finished buffering");
1170 /* There's no more to load or watch for */
1171 buf_set_watermark(0);
1172 filling
= STATE_FINISHED
;
1175 /* Stop the codec decoding or waiting for its data to be ready - returns
1176 'false' if the codec ended up stopped */
1177 static bool halt_decoding_track(bool stop
)
1179 /* If it was waiting for us to clear the buffer to make a rebuffer
1180 happen, it should cease otherwise codec_stop could deadlock waiting
1181 for the codec to go to its main loop - codec's request will now
1183 bool retval
= false;
1185 buf_signal_handle(ci
.audio_hid
, true);
1190 retval
= codec_pause();
1192 audio_clear_track_notifications();
1194 /* We now know it's idle and not waiting for buffered data */
1195 buf_signal_handle(ci
.audio_hid
, false);
1197 codec_skip_pending
= false;
1198 codec_seeking
= false;
1203 /* Wait for any in-progress fade to complete */
1204 static void audio_wait_fade_complete(void)
1206 /* Just loop until it's done */
1207 while (pcmbuf_fading())
1211 /* End the ff/rw mode */
1212 static void audio_ff_rewind_end(void)
1214 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1222 /* Clear the buffer */
1224 audio_pcmbuf_sync_position();
1227 if (play_status
!= PLAY_PAUSED
)
1229 /* Seeking-while-playing, resume PCM playback */
1230 pcmbuf_pause(false);
1235 /* Complete the codec seek */
1236 static void audio_complete_codec_seek(void)
1238 /* If a seek completed while paused, 'paused' is true.
1239 * If seeking from seek mode, 'ff_rw_mode' is true. */
1242 audio_ff_rewind_end();
1243 codec_seeking
= false; /* set _after_ the call! */
1245 /* else it's waiting and we must repond */
1248 /* Get the current cuesheet pointer */
1249 static inline struct cuesheet
* get_current_cuesheet(void)
1251 return audio_scratch_memory
->curr_cue
;
1254 /* Read the cuesheet from the buffer */
1255 static void buf_read_cuesheet(int handle_id
)
1257 struct cuesheet
*cue
= get_current_cuesheet();
1259 if (!cue
|| handle_id
< 0)
1262 bufread(handle_id
, sizeof (struct cuesheet
), cue
);
1265 /* Backend to peek/current/next track metadata interface functions -
1266 fill in the mp3entry with as much information as we may obtain about
1267 the track at the specified offset from the user current track -
1268 returns false if no information exists with us */
1269 static bool audio_get_track_metadata(int offset
, struct mp3entry
*id3
)
1271 if (play_status
== PLAY_STOPPED
)
1274 if (id3
->path
[0] != '\0')
1275 return true; /* Already filled */
1277 struct track_info
*info
= track_list_user_current(offset
);
1281 struct mp3entry
*ub_id3
= id3_get(UNBUFFERED_ID3
);
1283 if (offset
> 0 && track_list_user_current(offset
- 1))
1285 /* Try the unbuffered id3 since we're moving forward */
1286 if (ub_id3
->path
[0] != '\0')
1288 copy_mp3entry(id3
, ub_id3
);
1293 else if (bufreadid3(info
->id3_hid
, id3
))
1295 id3
->cuesheet
= NULL
;
1299 /* We didn't find the ID3 metadata, so we fill it with the little info we
1300 have and return that */
1302 char path
[MAX_PATH
+1];
1303 if (playlist_peek(offset
, path
, sizeof (path
)))
1305 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1306 /* Try to get it from the database */
1307 if (!tagcache_fill_tags(id3
, path
))
1310 /* By now, filename is the only source of info */
1311 fill_metadata_from_path(id3
, path
);
1322 /* Get a resume rewind adjusted offset from the ID3 */
1323 static unsigned long resume_rewind_adjusted_offset(const struct mp3entry
*id3
)
1325 unsigned long offset
= id3
->offset
;
1326 size_t resume_rewind
= global_settings
.resume_rewind
*
1327 id3
->bitrate
* (1000/8);
1329 if (offset
< resume_rewind
)
1332 offset
-= resume_rewind
;
1337 /* Get the codec into ram and initialize it - keep it if it's ready */
1338 static bool audio_init_codec(struct track_info
*track_info
,
1339 struct mp3entry
*track_id3
)
1341 int codt_loaded
= get_audio_base_codec_type(codec_loaded());
1342 int hid
= ERR_HANDLE_NOT_FOUND
;
1344 if (codt_loaded
!= AFMT_UNKNOWN
)
1346 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1348 if (codt
== codt_loaded
)
1350 /* Codec is the same base type */
1351 logf("Reusing prev. codec: %d", track_id3
->codectype
);
1352 #ifdef HAVE_CODEC_BUFFERING
1353 /* Close any buffered codec (we could have skipped directly to a
1354 format transistion that is the same format as the current track
1355 and the buffered one is no longer needed) */
1356 track_info_close_handle(&track_info
->codec_hid
);
1362 /* New codec - first make sure the old one's gone */
1363 logf("Removing prev. codec: %d", codt_loaded
);
1368 logf("New codec: %d/%d", track_id3
->codectype
, codec_loaded());
1370 #ifdef HAVE_CODEC_BUFFERING
1371 /* Codec thread will close the handle even if it fails and will load from
1372 storage if hid is not valid or the buffer load fails */
1373 hid
= track_info
->codec_hid
;
1374 track_info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
1377 return codec_load(hid
, track_id3
->codectype
);
1378 (void)track_info
; /* When codec buffering isn't supported */
1381 /* Start the codec for the current track scheduled to be decoded */
1382 static bool audio_start_codec(bool auto_skip
)
1384 struct track_info
*info
= track_list_current(0);
1385 struct mp3entry
*cur_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1390 buf_pin_handle(info
->id3_hid
, true);
1392 if (!audio_init_codec(info
, cur_id3
))
1394 buf_pin_handle(info
->id3_hid
, false);
1398 #ifdef HAVE_TAGCACHE
1399 bool autoresume_enable
= global_settings
.autoresume_enable
;
1401 if (autoresume_enable
&& !cur_id3
->offset
)
1403 /* Resume all manually selected tracks */
1404 bool resume
= !auto_skip
;
1406 /* Send the "buffer" event to obtain the resume position for the codec */
1407 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1411 /* Automatic skip - do further tests to see if we should just
1412 ignore any autoresume position */
1413 int autoresume_automatic
= global_settings
.autoresume_automatic
;
1415 switch (autoresume_automatic
)
1417 case AUTORESUME_NEXTTRACK_ALWAYS
:
1418 /* Just resume unconditionally */
1421 case AUTORESUME_NEXTTRACK_NEVER
:
1422 /* Force-rewind it */
1425 /* Not "never resume" - pass resume filter? */
1426 resume
= autoresumable(cur_id3
);
1431 cur_id3
->offset
= 0;
1433 logf("%s: Set offset for %s to %lX\n", __func__
,
1434 cur_id3
->title
, cur_id3
->offset
);
1436 #endif /* HAVE_TAGCACHE */
1438 /* Rewind the required amount - if an autoresume was done, this also rewinds
1439 that by the setting's amount
1441 It would be best to have bookkeeping about whether or not the track
1442 sounded or not since skipping to it or else skipping to it while paused
1443 and back again will cause accumulation of silent rewinds - that's not
1444 our job to track directly nor could it be in any reasonable way
1446 cur_id3
->offset
= resume_rewind_adjusted_offset(cur_id3
);
1448 /* Update the codec API with the metadata and track info */
1449 id3_write(CODEC_ID3
, cur_id3
);
1451 ci
.audio_hid
= info
->audio_hid
;
1452 ci
.filesize
= info
->filesize
;
1453 buf_set_base_handle(info
->audio_hid
);
1455 /* All required data is now available for the codec */
1458 #ifdef HAVE_TAGCACHE
1459 if (!autoresume_enable
|| cur_id3
->offset
)
1462 /* Send the "buffer" event now */
1463 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1466 buf_pin_handle(info
->id3_hid
, false);
1469 (void)auto_skip
; /* ifndef HAVE_TAGCACHE */
1473 /** --- Audio thread --- **/
1475 /* Load and parse a cuesheet for the file - returns false if the buffer
1477 static bool audio_load_cuesheet(struct track_info
*info
,
1478 struct mp3entry
*track_id3
)
1480 struct cuesheet
*cue
= get_current_cuesheet();
1481 track_id3
->cuesheet
= NULL
;
1483 if (cue
&& info
->cuesheet_hid
== ERR_HANDLE_NOT_FOUND
)
1485 /* If error other than a full buffer, then mark it "unsupported" to
1486 avoid reloading attempt */
1487 int hid
= ERR_UNSUPPORTED_TYPE
;
1488 struct cuesheet_file cue_file
;
1490 #ifdef HAVE_IO_PRIORITY
1491 buf_back_off_storage(true);
1493 if (look_for_cuesheet_file(track_id3
, &cue_file
))
1495 hid
= bufalloc(NULL
, sizeof (struct cuesheet
), TYPE_CUESHEET
);
1499 void *cuesheet
= NULL
;
1500 bufgetdata(hid
, sizeof (struct cuesheet
), &cuesheet
);
1502 if (parse_cuesheet(&cue_file
, (struct cuesheet
*)cuesheet
))
1504 /* Indicate cuesheet is present (while track remains
1506 track_id3
->cuesheet
= cue
;
1511 hid
= ERR_UNSUPPORTED_TYPE
;
1516 #ifdef HAVE_IO_PRIORITY
1517 buf_back_off_storage(false);
1519 if (hid
== ERR_BUFFER_FULL
)
1521 logf("buffer is full for now (%s)", __func__
);
1527 logf("Cuesheet loading failed");
1529 info
->cuesheet_hid
= hid
;
1536 #ifdef HAVE_ALBUMART
1537 /* Load any album art for the file - returns false if the buffer is full */
1538 static bool audio_load_albumart(struct track_info
*info
,
1539 struct mp3entry
*track_id3
)
1544 struct bufopen_bitmap_data user_data
;
1545 int *aa_hid
= &info
->aa_hid
[i
];
1546 int hid
= ERR_UNSUPPORTED_TYPE
;
1548 /* albumart_slots may change during a yield of bufopen,
1549 * but that's no problem */
1550 if (*aa_hid
>= 0 || *aa_hid
== ERR_UNSUPPORTED_TYPE
||
1551 !albumart_slots
[i
].used
)
1554 memset(&user_data
, 0, sizeof(user_data
));
1555 user_data
.dim
= &albumart_slots
[i
].dim
;
1557 #ifdef HAVE_IO_PRIORITY
1558 buf_back_off_storage(true);
1561 /* We can only decode jpeg for embedded AA */
1562 if (track_id3
->has_embedded_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1564 user_data
.embedded_albumart
= &track_id3
->albumart
;
1565 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1568 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1570 /* No embedded AA or it couldn't be loaded - try other sources */
1571 char path
[MAX_PATH
];
1573 if (find_albumart(track_id3
, path
, sizeof(path
),
1574 &albumart_slots
[i
].dim
))
1576 user_data
.embedded_albumart
= NULL
;
1577 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1581 #ifdef HAVE_IO_PRIORITY
1582 buf_back_off_storage(false);
1584 if (hid
== ERR_BUFFER_FULL
)
1586 logf("buffer is full for now (%s)", __func__
);
1591 /* If error other than a full buffer, then mark it "unsupported"
1592 to avoid reloading attempt */
1595 logf("Album art loading failed");
1596 hid
= ERR_UNSUPPORTED_TYPE
;
1605 #endif /* HAVE_ALBUMART */
1607 #ifdef HAVE_CODEC_BUFFERING
1608 /* Load a codec for the file onto the buffer - assumes we're working from the
1609 currently loading track - not called for the current track */
1610 static bool audio_buffer_codec(struct track_info
*track_info
,
1611 struct mp3entry
*track_id3
)
1613 /* This will not be the current track -> it cannot be the first and the
1614 current track cannot be ahead of buffering -> there is a previous
1615 track entry which is either current or ahead of the current */
1616 struct track_info
*prev_info
= track_list_last(-1);
1617 struct mp3entry
*prev_id3
= bufgetid3(prev_info
->id3_hid
);
1619 /* If the previous codec is the same as this one, there is no need to
1620 put another copy of it on the file buffer (in other words, only
1621 buffer codecs at format transitions) */
1624 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1625 int prev_codt
= get_audio_base_codec_type(prev_id3
->codectype
);
1627 if (codt
== prev_codt
)
1629 logf("Reusing prev. codec: %d", prev_id3
->codectype
);
1633 /* else just load it (harmless) */
1635 /* Load the codec onto the buffer if possible */
1636 const char *codec_fn
= get_codec_filename(track_id3
->codectype
);
1640 char codec_path
[MAX_PATH
+1]; /* Full path to codec */
1641 codec_get_full_path(codec_path
, codec_fn
);
1643 track_info
->codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1645 if (track_info
->codec_hid
>= 0)
1647 logf("Buffered codec: %d", afmt
);
1653 #endif /* HAVE_CODEC_BUFFERING */
1655 /* Load metadata for the next track (with bufopen). The rest of the track
1656 loading will be handled by audio_finish_load_track once the metadata has
1657 been actually loaded by the buffering thread.
1659 Each track is arranged in the buffer as follows:
1660 <id3|[cuesheet|][album art|][codec|]audio>
1662 The next will not be loaded until the previous succeeds if the buffer was
1663 full at the time. To put any metadata after audio would make those handles
1666 static int audio_load_track(void)
1668 if (in_progress_id3_hid
>= 0)
1670 /* There must be an info pointer if the in-progress id3 is even there */
1671 struct track_info
*info
= track_list_last(0);
1673 if (info
->id3_hid
== in_progress_id3_hid
)
1675 if (filling
== STATE_FILLING
)
1677 /* Haven't finished the metadata but the notification is
1678 anticipated to come soon */
1679 logf("%s(): in progress ok: %d". __func__
, info
->id3_hid
);
1680 return LOAD_TRACK_OK
;
1682 else if (filling
== STATE_FULL
)
1684 /* Buffer was full trying to complete the load after the
1685 metadata finished, so attempt to continue - older handles
1686 should have been cleared already */
1687 logf("%s(): finishing load: %d". __func__
, info
->id3_hid
);
1688 filling
= STATE_FILLING
;
1689 buffer_event_finished_callback(&info
->id3_hid
);
1690 return LOAD_TRACK_OK
;
1694 /* Some old, stray buffering message */
1695 logf("%s(): already in progress: %d". __func__
, info
->id3_hid
);
1696 return LOAD_TRACK_ERR_BUSY
;
1699 filling
= STATE_FILLING
;
1701 struct track_info
*info
= track_list_alloc_track();
1704 /* List is full so stop buffering tracks - however, attempt to obtain
1705 metadata as the unbuffered id3 */
1706 logf("No free tracks");
1707 filling
= STATE_FULL
;
1710 playlist_peek_offset
++;
1712 logf("Buffering track: s%u/c%u/e%u/p%d",
1713 track_list
.start
, track_list
.current
, track_list
.end
,
1714 playlist_peek_offset
);
1716 /* Get track name from current playlist read position */
1718 char name_buf
[MAX_PATH
+ 1];
1719 const char *trackname
;
1724 trackname
= playlist_peek(playlist_peek_offset
, name_buf
,
1730 /* Test for broken playlists by probing for the files */
1731 fd
= open(trackname
, O_RDONLY
);
1735 logf("Open failed");
1736 /* Skip invalid entry from playlist */
1737 playlist_skip_entry(NULL
, playlist_peek_offset
);
1739 /* Sync the playlist if it isn't finished */
1740 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1746 /* No track - exhausted the playlist entries */
1747 logf("End-of-playlist");
1748 id3_write_locked(UNBUFFERED_ID3
, NULL
);
1750 if (filling
!= STATE_FULL
)
1751 track_list_unalloc_track(); /* Free this entry */
1753 playlist_peek_offset
--; /* Maintain at last index */
1755 /* We can end up here after the real last track signals its completion
1756 and miss the transition to STATE_FINISHED esp. if dropping the last
1757 songs of a playlist late in their load (2nd stage) */
1758 info
= track_list_last(0);
1760 if (info
&& buf_handle_remaining(info
->audio_hid
) == 0)
1761 filling_is_finished();
1763 filling
= STATE_END_OF_PLAYLIST
;
1765 return LOAD_TRACK_ERR_NO_MORE
;
1768 /* Successfully opened the file - get track metadata */
1769 if (filling
== STATE_FULL
||
1770 (info
->id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
)) < 0)
1772 /* Buffer or track list is full */
1773 struct mp3entry
*ub_id3
;
1775 playlist_peek_offset
--;
1777 /* Load the metadata for the first unbuffered track */
1778 ub_id3
= id3_get(UNBUFFERED_ID3
);
1780 get_metadata(ub_id3
, fd
, trackname
);
1783 if (filling
!= STATE_FULL
)
1785 track_list_unalloc_track();
1786 filling
= STATE_FULL
;
1789 logf("%s: buffer is full for now (%u tracks)", __func__
,
1790 track_list_count());
1794 /* Successful load initiation */
1795 info
->filesize
= filesize(fd
);
1796 in_progress_id3_hid
= info
->id3_hid
; /* Remember what's in-progress */
1800 return LOAD_TRACK_OK
;
1803 /* Second part of the track loading: We now have the metadata available, so we
1804 can load the codec, the album art and finally the audio data.
1805 This is called on the audio thread after the buffering thread calls the
1806 buffering_handle_finished_callback callback. */
1807 static int audio_finish_load_track(struct track_info
*info
)
1809 int trackstat
= LOAD_TRACK_OK
;
1811 if (info
->id3_hid
!= in_progress_id3_hid
)
1813 /* We must not be here if not! */
1814 logf("%s: wrong track %d/%d", __func__
, info
->id3_hid
,
1815 in_progress_id3_hid
);
1816 return LOAD_TRACK_ERR_BUSY
;
1819 /* The current track for decoding (there is always one if the list is
1821 struct track_info
*cur_info
= track_list_current(0);
1822 struct mp3entry
*track_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1826 /* This is an error condition. Track cannot be played without valid
1827 metadata; skip the track. */
1828 logf("No metadata");
1829 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1830 goto audio_finish_load_track_exit
;
1833 /* Try to load a cuesheet for the track */
1834 if (!audio_load_cuesheet(info
, track_id3
))
1836 /* No space for cuesheet on buffer, not an error */
1837 filling
= STATE_FULL
;
1838 goto audio_finish_load_track_exit
;
1841 #ifdef HAVE_ALBUMART
1842 /* Try to load album art for the track */
1843 if (!audio_load_albumart(info
, track_id3
))
1845 /* No space for album art on buffer, not an error */
1846 filling
= STATE_FULL
;
1847 goto audio_finish_load_track_exit
;
1851 /* All handles available to external routines are ready - audio and codec
1852 information is private */
1854 if (info
== track_list_user_current(0))
1856 /* Send only when the track handles could not all be opened ahead of
1857 time for the user's current track - otherwise everything is ready
1858 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1859 send_event(PLAYBACK_EVENT_CUR_TRACK_READY
, id3_get(PLAYING_ID3
));
1862 #ifdef HAVE_CODEC_BUFFERING
1863 /* Try to buffer a codec for the track */
1864 if (info
!= cur_info
&& !audio_buffer_codec(info
, track_id3
))
1866 if (info
->codec_hid
== ERR_BUFFER_FULL
)
1868 /* No space for codec on buffer, not an error */
1869 filling
= STATE_FULL
;
1870 logf("buffer is full for now (%s)", __func__
);
1874 /* This is an error condition, either no codec was found, or
1875 reading the codec file failed part way through, either way,
1877 logf("No codec for: %s", track_id3
->path
);
1878 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1881 goto audio_finish_load_track_exit
;
1883 #endif /* HAVE_CODEC_BUFFERING */
1885 /** Finally, load the audio **/
1886 size_t file_offset
= 0;
1887 track_id3
->elapsed
= 0;
1889 if (track_id3
->offset
>= info
->filesize
)
1890 track_id3
->offset
= 0;
1892 logf("%s: set offset for %s to %lu\n", __func__
,
1893 id3
->title
, (unsigned long)offset
);
1895 /* Adjust for resume rewind so we know what to buffer - starting the codec
1896 calls it again, so we don't save it (and they shouldn't accumulate) */
1897 size_t offset
= resume_rewind_adjusted_offset(track_id3
);
1899 enum data_type audiotype
= get_audio_base_data_type(track_id3
->codectype
);
1901 if (audiotype
== TYPE_ATOMIC_AUDIO
)
1902 logf("Loading atomic %d", track_id3
->codectype
);
1904 if (format_buffers_with_offset(track_id3
->codectype
))
1906 /* This format can begin buffering from any point */
1907 file_offset
= offset
;
1910 logf("load track: %s", track_id3
->path
);
1912 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1914 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1915 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1919 /* No offset given or it is very minimal - begin at the first frame
1920 according to the metadata */
1921 file_offset
= track_id3
->first_frame_offset
;
1924 int hid
= bufopen(track_id3
->path
, file_offset
, audiotype
, NULL
);
1928 info
->audio_hid
= hid
;
1930 if (info
== cur_info
)
1932 /* This is the current track to decode - should be started now */
1933 trackstat
= LOAD_TRACK_READY
;
1938 /* Buffer could be full but not properly so if this is the only
1940 if (hid
== ERR_BUFFER_FULL
&& audio_track_count() > 1)
1942 filling
= STATE_FULL
;
1943 logf("Buffer is full for now (%s)", __func__
);
1947 /* Nothing to play if no audio handle - skip this */
1948 logf("Could not add audio data handle");
1949 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1953 audio_finish_load_track_exit
:
1954 if (trackstat
< LOAD_TRACK_OK
)
1956 playlist_skip_entry(NULL
, playlist_peek_offset
);
1957 track_info_close(info
);
1958 track_list_unalloc_track();
1960 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1963 playlist_peek_offset
--;
1966 if (filling
!= STATE_FULL
)
1968 /* Load next track - error or not */
1969 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
1970 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1971 audio_queue_post(Q_AUDIO_FILL_BUFFER
, 0);
1976 trackstat
= LOAD_TRACK_ERR_FINISH_FULL
;
1982 /* Start a new track load */
1983 static int audio_fill_file_buffer(void)
1985 if (play_status
== PLAY_STOPPED
)
1986 return LOAD_TRACK_ERR_FAILED
;
1988 trigger_cpu_boost();
1990 /* Must reset the buffer before use if trashed or voice only - voice
1991 file size shouldn't have changed so we can go straight from
1992 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1993 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1994 audio_reset_buffer();
1996 logf("Starting buffer fill");
1998 int trackstat
= audio_load_track();
2000 if (trackstat
>= LOAD_TRACK_OK
)
2002 if (track_list_current(0) == track_list_user_current(0))
2005 if (filling
== STATE_FULL
&& !track_list_user_current(1))
2007 /* There are no user tracks on the buffer after this therefore
2008 this is the next track */
2009 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3
));
2016 /* Discard unwanted tracks and start refill from after the specified playlist
2018 static int audio_reset_and_rebuffer(
2019 enum track_clear_action action
, int peek_offset
)
2021 logf("Forcing rebuffer: 0x%X, %d", flags
, peek_offset
);
2023 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2025 /* Remove unwanted tracks - caller must have ensured codec isn't using
2027 track_list_clear(action
);
2029 /* Refill at specified position (-1 starts at index offset 0) */
2030 playlist_peek_offset
= peek_offset
;
2032 /* Fill the buffer */
2033 return audio_fill_file_buffer();
2036 /* Handle buffering events
2037 (Q_AUDIO_BUFFERING) */
2038 static void audio_on_buffering(int event
)
2040 enum track_clear_action action
;
2043 if (track_list_empty())
2048 case BUFFER_EVENT_BUFFER_LOW
:
2049 if (filling
!= STATE_FULL
&& filling
!= STATE_END_OF_PLAYLIST
)
2050 return; /* Should be nothing left to fill */
2052 /* Clear old tracks and continue buffering where it left off */
2053 action
= TRACK_LIST_KEEP_NEW
;
2054 peek_offset
= playlist_peek_offset
;
2057 case BUFFER_EVENT_REBUFFER
:
2058 /* Remove all but the currently decoding track and redo buffering
2060 action
= TRACK_LIST_KEEP_CURRENT
;
2061 peek_offset
= (skip_pending
== TRACK_SKIP_AUTO
) ? 1 : 0;
2068 switch (skip_pending
)
2070 case TRACK_SKIP_NONE
:
2071 case TRACK_SKIP_AUTO
:
2072 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2073 audio_reset_and_rebuffer(action
, peek_offset
);
2076 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2077 /* Already finished */
2082 logf("Buffering call, inv. state: %d", (int)skip_pending
);
2086 /* Handle starting the next track load
2087 (Q_AUDIO_FILL_BUFFER) */
2088 static void audio_on_fill_buffer(void)
2090 audio_handle_track_load_status(audio_fill_file_buffer());
2093 /* Handle posted load track finish event
2094 (Q_AUDIO_FINISH_LOAD_TRACK) */
2095 static void audio_on_finish_load_track(int id3_hid
)
2097 struct track_info
*info
= track_list_last(0);
2099 if (!info
|| !buf_is_handle(id3_hid
))
2102 if (info
== track_list_user_current(1))
2104 /* Just loaded the metadata right after the current position */
2105 audio_update_and_announce_next_track(bufgetid3(info
->id3_hid
));
2108 if (audio_finish_load_track(info
) != LOAD_TRACK_READY
)
2109 return; /* Not current track */
2111 bool is_user_current
= info
== track_list_user_current(0);
2113 if (is_user_current
)
2116 buf_read_cuesheet(info
->cuesheet_hid
);
2119 if (audio_start_codec(automatic_skip
))
2121 if (is_user_current
)
2123 /* Be sure all tagtree info is synchronized; it will be needed for the
2124 track finish event - the sync will happen when finalizing a track
2126 bool was_valid
= valid_mp3entry(id3_get(PLAYING_ID3
));
2128 playing_id3_sync(info
, -1);
2132 /* Playing id3 hadn't been updated yet because no valid track
2133 was yet available - treat like the first track */
2134 audio_playlist_track_change();
2140 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2144 /* Called when handles other than metadata handles have finished buffering
2145 (Q_AUDIO_HANDLE_FINISHED) */
2146 static void audio_on_handle_finished(int hid
)
2148 /* Right now, only audio handles should end up calling this */
2149 if (filling
== STATE_END_OF_PLAYLIST
)
2151 struct track_info
*info
= track_list_last(0);
2153 /* Really we don't know which order the handles will actually complete
2154 to zero bytes remaining since another thread is doing it - be sure
2155 it's the right one */
2156 if (info
&& info
->audio_hid
== hid
)
2158 /* This was the last track in the playlist and we now have all the
2160 filling_is_finished();
2165 /* Called to make an outstanding track skip the current track and to send the
2166 transition events */
2167 static void audio_finalise_track_change(void)
2169 switch (skip_pending
)
2171 case TRACK_SKIP_NONE
: /* Manual skip */
2174 case TRACK_SKIP_AUTO
:
2175 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2177 int playlist_delta
= skip_pending
== TRACK_SKIP_AUTO
? 1 : 0;
2178 audio_playlist_track_finish();
2180 if (!playlist_peek(playlist_delta
, NULL
, 0))
2182 /* Track ended up rejected - push things ahead like the codec blew
2183 it (because it was never started and now we're here where it
2184 should have been decoding the next track by now) - next, a
2185 directory change or end of playback will most likely happen */
2186 skip_pending
= TRACK_SKIP_NONE
;
2187 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2191 if (!playlist_delta
)
2194 playlist_peek_offset
-= playlist_delta
;
2195 if (playlist_next(playlist_delta
) >= 0)
2197 /* What!? Disappear? Hopeless bleak despair */
2200 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2201 default: /* Invalid */
2202 filling
= STATE_ENDED
;
2203 audio_stop_playback();
2207 struct track_info
*info
= track_list_current(0);
2208 struct mp3entry
*track_id3
= NULL
;
2212 /* Update the current cuesheet if any and enabled */
2215 buf_read_cuesheet(info
->cuesheet_hid
);
2216 track_id3
= bufgetid3(info
->id3_hid
);
2219 id3_write(PLAYING_ID3
, track_id3
);
2221 /* The skip is technically over */
2222 skip_pending
= TRACK_SKIP_NONE
;
2224 /* Sync the next track information */
2225 info
= track_list_current(1);
2227 id3_write(NEXTTRACK_ID3
, info
? bufgetid3(info
->id3_hid
) :
2228 id3_get(UNBUFFERED_ID3
));
2232 audio_playlist_track_change();
2235 /* Actually begin a transition and take care of the codec change - may complete
2236 it now or ask pcmbuf for notification depending on the type */
2237 static void audio_begin_track_change(enum pcm_track_change_type type
,
2240 /* Even if the new track is bad, the old track must be finished off */
2241 pcmbuf_start_track_change(type
);
2243 bool auto_skip
= type
!= TRACK_CHANGE_MANUAL
;
2247 /* Manual track change happens now */
2248 audio_finalise_track_change();
2249 pcmbuf_sync_position_update();
2251 if (play_status
== PLAY_STOPPED
)
2252 return; /* Stopped us */
2255 if (trackstat
>= LOAD_TRACK_OK
)
2257 struct track_info
*info
= track_list_current(0);
2259 if (info
->audio_hid
< 0)
2262 /* Everything needed for the codec is ready - start it */
2263 if (audio_start_codec(auto_skip
))
2266 playing_id3_sync(info
, -1);
2270 trackstat
= LOAD_TRACK_ERR_START_CODEC
;
2273 audio_handle_track_load_status(trackstat
);
2276 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2277 static void audio_monitor_end_of_playlist(void)
2279 skip_pending
= TRACK_SKIP_AUTO_END_PLAYLIST
;
2280 filling
= STATE_ENDING
;
2281 pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA
);
2284 /* Codec has completed decoding the track
2285 (usually Q_AUDIO_CODEC_COMPLETE) */
2286 static void audio_on_codec_complete(int status
)
2288 logf("%s(%d)", __func__
, status
);
2290 if (play_status
== PLAY_STOPPED
)
2293 /* If it didn't notify us first, don't expect "seek complete" message
2294 since the codec can't post it now - do things like it would have
2296 audio_complete_codec_seek();
2298 if (play_status
== PLAY_PAUSED
|| skip_pending
!= TRACK_SKIP_NONE
)
2300 /* Old-hay on the ip-skay - codec has completed decoding
2302 Paused: We're not sounding it, so just remember that it happened
2303 and the resume will begin the transition
2305 Skipping: There was already a skip in progress, remember it and
2306 allow no further progress until the PCM from the previous
2309 codec_skip_pending
= true;
2310 codec_skip_status
= status
;
2314 codec_skip_pending
= false;
2316 int trackstat
= LOAD_TRACK_OK
;
2318 automatic_skip
= true;
2319 skip_pending
= TRACK_SKIP_AUTO
;
2321 /* Does this track have an entry allocated? */
2322 struct track_info
*info
= track_list_advance_current(1);
2324 if (!info
|| info
->audio_hid
< 0)
2326 bool end_of_playlist
= false;
2330 /* Track load is not complete - it might have stopped on a
2331 full buffer without reaching the audio handle or we just
2334 If this type is atomic and we couldn't get the audio,
2335 perhaps it would need to wrap to make the allocation and
2336 handles are in the way - to maximize the liklihood it can
2337 be allocated, clear all handles to reset the buffer and
2338 its indexes to 0 - for packet audio, this should not be an
2339 issue and a pointless full reload of all the track's
2340 metadata may be avoided */
2342 struct mp3entry
*track_id3
= bufgetid3(info
->id3_hid
);
2345 get_audio_base_data_type(track_id3
->codectype
)
2346 == TYPE_PACKET_AUDIO
)
2348 /* Continue filling after this track */
2349 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT
, 1);
2350 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2353 /* else rebuffer at this track; status applies to the track we
2356 else if (!playlist_peek(1, NULL
, 0))
2358 /* Play sequence is complete - directory change or other playlist
2359 resequencing - the playlist must now be advanced in order to
2360 continue since a peek ahead to the next track is not possible */
2361 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2362 end_of_playlist
= playlist_next(1) < 0;
2365 if (!end_of_playlist
)
2367 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
,
2368 skip_pending
== TRACK_SKIP_AUTO
? 0 : -1);
2370 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2372 /* Failed to find anything after all - do playlist switchover
2374 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2375 end_of_playlist
= playlist_next(1) < 0;
2379 if (end_of_playlist
)
2381 audio_monitor_end_of_playlist();
2386 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2389 /* Called when codec completes seek operation
2390 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2391 static void audio_on_codec_seek_complete(void)
2393 logf("%s()", __func__
);
2394 audio_complete_codec_seek();
2398 /* Called when PCM track change has completed
2399 (Q_AUDIO_TRACK_CHANGED) */
2400 static void audio_on_track_changed(void)
2402 /* Finish whatever is pending so that the WPS is in sync */
2403 audio_finalise_track_change();
2405 if (codec_skip_pending
)
2407 /* Codec got ahead completing a short track - complete the
2408 codec's skip and begin the next */
2409 codec_skip_pending
= false;
2410 audio_on_codec_complete(codec_skip_status
);
2414 /* Begin playback from an idle state, transition to a new playlist or
2415 invalidate the buffer and resume (if playing).
2416 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2417 static void audio_start_playback(size_t offset
, unsigned int flags
)
2419 enum play_status old_status
= play_status
;
2421 if (flags
& AUDIO_START_NEWBUF
)
2423 /* Mark the buffer dirty - if not playing, it will be reset next
2425 if (buffer_state
== AUDIOBUF_STATE_INITIALIZED
)
2426 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
2429 if (old_status
!= PLAY_STOPPED
)
2431 logf("%s(%lu): skipping", __func__
, (unsigned long)offset
);
2433 halt_decoding_track(true);
2435 automatic_skip
= false;
2438 if (flags
& AUDIO_START_RESTART
)
2440 /* Clear out some stuff to resume the current track where it
2443 offset
= id3_get(PLAYING_ID3
)->offset
;
2444 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2448 /* This is more-or-less treated as manual track transition */
2449 /* Save resume information for current track */
2450 audio_playlist_track_finish();
2451 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2453 /* Indicate manual track change */
2454 pcmbuf_start_track_change(TRACK_CHANGE_MANUAL
);
2455 wipe_track_metadata(true);
2458 /* Set after track finish event in case skip was in progress */
2459 skip_pending
= TRACK_SKIP_NONE
;
2463 if (flags
& AUDIO_START_RESTART
)
2464 return; /* Must already be playing */
2466 /* Cold playback start from a stopped state */
2467 logf("%s(%lu): starting", __func__
, offset
);
2469 /* Set audio parameters */
2470 #if INPUT_SRC_CAPS != 0
2471 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
2472 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
2474 #ifndef PLATFORM_HAS_VOLUME_CHANGE
2475 sound_set_volume(global_settings
.volume
);
2477 /* Be sure channel is audible */
2478 pcmbuf_fade(false, true);
2480 /* Update our state */
2481 play_status
= PLAY_PLAYING
;
2484 /* Codec's position should be available as soon as it knows it */
2485 position_key
= pcmbuf_get_position_key();
2486 pcmbuf_sync_position_update();
2488 /* Start fill from beginning of playlist */
2489 playlist_peek_offset
= -1;
2490 buf_set_base_handle(-1);
2492 /* Officially playing */
2493 queue_reply(&audio_queue
, 1);
2495 /* Add these now - finish event for the first id3 will most likely be sent
2497 add_event(BUFFER_EVENT_REBUFFER
, false, buffer_event_rebuffer_callback
);
2498 add_event(BUFFER_EVENT_FINISHED
, false, buffer_event_finished_callback
);
2500 if (old_status
== PLAY_STOPPED
)
2502 /* Send coldstart event */
2503 send_event(PLAYBACK_EVENT_START_PLAYBACK
, NULL
);
2506 /* Fill the buffer */
2507 int trackstat
= audio_fill_file_buffer();
2509 if (trackstat
>= LOAD_TRACK_OK
)
2511 /* This is the currently playing track - get metadata, stat */
2512 playing_id3_sync(track_list_current(0), offset
);
2514 if (valid_mp3entry(id3_get(PLAYING_ID3
)))
2516 /* Only if actually changing tracks... */
2517 if (!(flags
& AUDIO_START_RESTART
))
2518 audio_playlist_track_change();
2523 /* Found nothing playable */
2524 audio_handle_track_load_status(trackstat
);
2528 /* Stop playback and enter an idle state
2529 (usually Q_AUDIO_STOP) */
2530 static void audio_stop_playback(void)
2532 logf("%s()", __func__
);
2534 if (play_status
== PLAY_STOPPED
)
2537 bool do_fade
= global_settings
.fade_on_stop
&& filling
!= STATE_ENDED
;
2539 pcmbuf_fade(do_fade
, false);
2541 /* Wait for fade-out */
2542 audio_wait_fade_complete();
2544 /* Stop the codec and unload it */
2545 halt_decoding_track(true);
2549 /* Save resume information - "filling" might have been set to
2550 "STATE_ENDED" by caller in order to facilitate end of playlist */
2551 audio_playlist_track_finish();
2553 skip_pending
= TRACK_SKIP_NONE
;
2554 automatic_skip
= false;
2556 /* Close all tracks and mark them NULL */
2557 remove_event(BUFFER_EVENT_REBUFFER
, buffer_event_rebuffer_callback
);
2558 remove_event(BUFFER_EVENT_FINISHED
, buffer_event_finished_callback
);
2559 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffer_event_buffer_low_callback
);
2561 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2563 /* Update our state */
2565 play_status
= PLAY_STOPPED
;
2567 wipe_track_metadata(true);
2570 filling
= STATE_IDLE
;
2574 /* Pause the playback of the current track
2576 static void audio_on_pause(bool pause
)
2578 logf("%s(%s)", __func__
, pause
? "true" : "false");
2580 if (play_status
== PLAY_STOPPED
|| pause
== (play_status
== PLAY_PAUSED
))
2583 play_status
= pause
? PLAY_PAUSED
: PLAY_PLAYING
;
2585 if (!pause
&& codec_skip_pending
)
2587 /* Actually do the skip that is due - resets the status flag */
2588 audio_on_codec_complete(codec_skip_status
);
2591 bool do_fade
= global_settings
.fade_on_stop
;
2593 pcmbuf_fade(do_fade
, !pause
);
2595 if (!ff_rw_mode
&& !(do_fade
&& pause
))
2597 /* Not in ff/rw mode - can actually change the audio state now */
2598 pcmbuf_pause(pause
);
2602 /* Skip a certain number of tracks forwards or backwards
2604 static void audio_on_skip(void)
2608 /* Eat the delta to keep it synced, even if not playing */
2609 int toskip
= skip_offset
;
2612 logf("%s(): %d", __func__
, toskip
);
2616 if (play_status
== PLAY_STOPPED
)
2619 /* Force codec to abort this track */
2620 halt_decoding_track(true);
2622 /* Kill the ff/rw halt */
2626 automatic_skip
= false;
2628 /* If there was an auto skip in progress, there will be residual
2629 advancement of the playlist and/or track list so compensation will be
2630 required in order to end up in the right spot */
2631 int track_list_delta
= toskip
;
2632 int playlist_delta
= toskip
;
2634 if (skip_pending
!= TRACK_SKIP_NONE
)
2636 if (skip_pending
!= TRACK_SKIP_AUTO_END_PLAYLIST
)
2639 if (skip_pending
== TRACK_SKIP_AUTO_NEW_PLAYLIST
)
2643 audio_playlist_track_finish();
2644 skip_pending
= TRACK_SKIP_NONE
;
2646 /* Update the playlist current track now */
2647 while (playlist_next(playlist_delta
) < 0)
2649 /* Manual skip out of range (because the playlist wasn't updated
2650 yet by us and so the check in audio_skip returned 'ok') - bring
2652 int d
= toskip
< 0 ? 1 : -1;
2654 while (!playlist_check(playlist_delta
))
2656 if (playlist_delta
== d
)
2658 /* Had to move the opposite direction to correct, which is
2659 wrong - this is the end */
2660 filling
= STATE_ENDED
;
2661 audio_stop_playback();
2665 playlist_delta
+= d
;
2666 track_list_delta
+= d
;
2670 /* Adjust things by how much the playlist was manually moved */
2671 playlist_peek_offset
-= playlist_delta
;
2673 struct track_info
*info
= track_list_advance_current(track_list_delta
);
2674 int trackstat
= LOAD_TRACK_OK
;
2676 if (!info
|| info
->audio_hid
< 0)
2678 /* We don't know the next track thus we know we don't have it */
2679 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2682 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2685 /* Skip to the next/previous directory
2686 (Q_AUDIO_DIR_SKIP) */
2687 static void audio_on_dir_skip(int direction
)
2689 logf("%s(%d)", __func__
, direction
);
2695 if (play_status
== PLAY_STOPPED
)
2698 /* Force codec to abort this track */
2699 halt_decoding_track(true);
2701 /* Kill the ff/rw halt */
2705 automatic_skip
= false;
2707 audio_playlist_track_finish();
2709 /* Unless automatic and gapless, skips do not pend */
2710 skip_pending
= TRACK_SKIP_NONE
;
2712 /* Regardless of the return value we need to rebuffer. If it fails the old
2713 playlist will resume, else the next dir will start playing. */
2714 playlist_next_dir(direction
);
2716 wipe_track_metadata(false);
2718 int trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2720 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2722 /* The day the music died - finish-off whatever is playing and call it
2724 audio_monitor_end_of_playlist();
2728 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2731 /* Enter seek mode in order to start a seek
2732 (Q_AUDIO_PRE_FF_REWIND) */
2733 static void audio_on_pre_ff_rewind(void)
2735 logf("%s()", __func__
);
2737 if (play_status
== PLAY_STOPPED
|| ff_rw_mode
)
2742 audio_wait_fade_complete();
2744 if (play_status
== PLAY_PAUSED
)
2750 /* Seek the playback of the current track to the specified time
2751 (Q_AUDIO_FF_REWIND) */
2752 static void audio_on_ff_rewind(long time
)
2754 logf("%s(%ld)", __func__
, time
);
2756 if (play_status
== PLAY_STOPPED
)
2759 enum track_skip_type pending
= skip_pending
;
2763 case TRACK_SKIP_NONE
: /* The usual case */
2764 case TRACK_SKIP_AUTO
: /* Have to back it out (fun!) */
2765 case TRACK_SKIP_AUTO_END_PLAYLIST
: /* Still have the last codec used */
2767 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
2768 struct mp3entry
*ci_id3
= id3_get(CODEC_ID3
);
2770 automatic_skip
= false;
2772 /* Send event before clobbering the time */
2773 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2774 then skipping back to this track resumes properly. Something else
2775 should be sent. We're not _really_ finishing the track are we? */
2777 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
2779 id3
->elapsed
= time
;
2780 queue_reply(&audio_queue
, 1);
2782 bool haltres
= halt_decoding_track(pending
== TRACK_SKIP_AUTO
);
2784 /* Need this set in case ff/rw mode + error but _after_ the codec
2785 halt that will reset it */
2786 codec_seeking
= true;
2788 /* If in transition, key will have changed - sync to it */
2789 position_key
= pcmbuf_get_position_key();
2791 if (pending
== TRACK_SKIP_AUTO
)
2793 if (!track_list_advance_current(-1))
2795 /* Not in list - must rebuffer at the current playlist index */
2796 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1)
2799 /* Codec is stopped */
2805 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2806 rebuffer is needed */
2807 skip_pending
= TRACK_SKIP_NONE
;
2808 struct track_info
*cur_info
= track_list_current(0);
2810 /* Track must complete the loading _now_ since a codec and audio
2811 handle are needed in order to do the seek */
2812 if (cur_info
->audio_hid
< 0 &&
2813 audio_finish_load_track(cur_info
) != LOAD_TRACK_READY
)
2815 /* Call above should push any load sequence - no need for
2816 halt_decoding_track here if no skip was pending here because
2817 there would not be a codec started if no audio handle was yet
2822 if (pending
== TRACK_SKIP_AUTO
)
2824 if (!bufreadid3(cur_info
->id3_hid
, ci_id3
) ||
2825 !audio_init_codec(cur_info
, ci_id3
))
2827 /* We should have still been able to get it - skip it and move
2828 onto the next one - like it or not this track is broken */
2832 /* Set the codec API to the correct metadata and track info */
2833 ci
.audio_hid
= cur_info
->audio_hid
;
2834 ci
.filesize
= cur_info
->filesize
;
2835 buf_set_base_handle(cur_info
->audio_hid
);
2840 /* If codec must be (re)started, reset the offset */
2848 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2850 /* We cannot do this because the playlist must be reversed by one
2851 and it doesn't always return the same song when going backwards
2852 across boundaries as forwards (either because of randomization
2853 or inconsistency in deciding what the previous track should be),
2854 therefore the whole operation would often end up as nonsense -
2855 lock out seeking for a couple seconds */
2857 /* Sure as heck cancel seek mode too! */
2858 audio_ff_rewind_end();
2863 /* Won't see this */
2867 if (play_status
== PLAY_STOPPED
)
2869 /* Playback ended because of an error completing a track load */
2873 /* Always fake it as a codec start error which will handle mode
2874 cancellations and skip to the next track */
2875 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2878 /* Invalidates all but currently playing track
2880 static void audio_on_audio_flush(void)
2882 logf("%s", __func__
);
2884 if (track_list_empty())
2885 return; /* Nothing to flush out */
2887 switch (skip_pending
)
2889 case TRACK_SKIP_NONE
:
2890 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2891 /* Remove all but the currently playing track from the list and
2892 refill after that */
2893 track_list_clear(TRACK_LIST_KEEP_CURRENT
);
2894 playlist_peek_offset
= 0;
2895 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2896 audio_update_and_announce_next_track(NULL
);
2898 /* Ignore return since it's about the next track, not this one */
2899 audio_fill_file_buffer();
2901 if (skip_pending
== TRACK_SKIP_NONE
)
2904 /* There's now a track after this one now - convert to auto skip -
2905 no skip should pend right now because multiple flush messages can
2906 be fired which would cause a restart in the below cases */
2907 skip_pending
= TRACK_SKIP_NONE
;
2908 audio_clear_track_notifications();
2909 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_OK
);
2912 case TRACK_SKIP_AUTO
:
2913 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2914 /* Precisely removing what it already decoded for the next track is
2915 not possible so a restart is required in order to continue the
2916 currently playing track without the now invalid future track
2918 audio_start_playback(0, AUDIO_START_RESTART
);
2921 default: /* Nothing else is a state */
2926 #ifdef AUDIO_HAVE_RECORDING
2927 /* Load the requested encoder type
2928 (Q_AUDIO_LOAD_ENCODER) */
2929 static void audio_on_load_encoder(int afmt
)
2933 if (play_status
!= PLAY_STOPPED
)
2934 audio_stop_playback(); /* Can't load both types at once */
2936 codec_unload(); /* Encoder still loaded, stop and unload it */
2938 if (afmt
!= AFMT_UNKNOWN
)
2940 res
= codec_load(-1, afmt
| CODEC_TYPE_ENCODER
);
2942 codec_go(); /* These are run immediately */
2945 queue_reply(&audio_queue
, res
);
2947 #endif /* AUDIO_HAVE_RECORDING */
2949 static void audio_thread(void)
2951 struct queue_event ev
;
2961 case STATE_END_OF_PLAYLIST
:
2962 if (buf_get_watermark() == 0)
2964 /* End of buffering for now, let's calculate the watermark,
2965 register for a low buffer event and unboost */
2966 audio_update_filebuf_watermark(0);
2967 add_event(BUFFER_EVENT_BUFFER_LOW
, true,
2968 buffer_event_buffer_low_callback
);
2971 case STATE_FINISHED
:
2972 /* All data was buffered */
2977 if (audio_pcmbuf_track_change_scan())
2979 /* Transfer notification to audio queue event */
2980 ev
.id
= Q_AUDIO_TRACK_CHANGED
;
2985 /* If doing auto skip, poll pcmbuf track notifications a bit
2986 faster to promply detect the transition */
2987 queue_wait_w_tmo(&audio_queue
, &ev
,
2988 skip_pending
== TRACK_SKIP_NONE
?
2995 queue_wait(&audio_queue
, &ev
);
2997 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3000 #ifdef AUDIO_HAVE_RECORDING
3001 /* Must monitor the encoder message for recording so it can remove
3002 it if we process the insertion before it does. It cannot simply
3003 be removed from under recording however. */
3004 case Q_AUDIO_LOAD_ENCODER
:
3007 case SYS_USB_DISCONNECTED
:
3008 filling
= STATE_IDLE
;
3012 if (filling
== STATE_USB
)
3015 #endif /* CONFIG_PLATFORM */
3020 /** Codec and track change messages **/
3021 case Q_AUDIO_CODEC_COMPLETE
:
3022 /* Codec is done processing track and has gone idle */
3023 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev
.data
);
3024 audio_on_codec_complete(ev
.data
);
3027 case Q_AUDIO_CODEC_SEEK_COMPLETE
:
3028 /* Codec is done seeking */
3029 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
3030 audio_on_codec_seek_complete();
3033 case Q_AUDIO_TRACK_CHANGED
:
3034 /* PCM track change done */
3035 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3036 audio_on_track_changed();
3039 /** Control messages **/
3041 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3042 audio_start_playback(ev
.data
, 0);
3046 LOGFQUEUE("audio < Q_AUDIO_STOP");
3047 audio_stop_playback();
3049 queue_clear(&audio_queue
);
3053 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3054 audio_on_pause(ev
.data
);
3058 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3062 case Q_AUDIO_DIR_SKIP
:
3063 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3064 audio_on_dir_skip(ev
.data
);
3067 case Q_AUDIO_PRE_FF_REWIND
:
3068 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3069 audio_on_pre_ff_rewind();
3072 case Q_AUDIO_FF_REWIND
:
3073 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3074 audio_on_ff_rewind(ev
.data
);
3078 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev
.data
);
3079 audio_on_audio_flush();
3082 /** Buffering messages **/
3083 case Q_AUDIO_BUFFERING
:
3084 /* some buffering event */
3085 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev
.data
);
3086 audio_on_buffering(ev
.data
);
3089 case Q_AUDIO_FILL_BUFFER
:
3090 /* continue buffering next track */
3091 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3092 audio_on_fill_buffer();
3095 case Q_AUDIO_FINISH_LOAD_TRACK
:
3096 /* metadata is buffered */
3097 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3098 audio_on_finish_load_track(ev
.data
);
3101 case Q_AUDIO_HANDLE_FINISHED
:
3102 /* some other type is buffered */
3103 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3104 audio_on_handle_finished(ev
.data
);
3107 /** Miscellaneous messages **/
3108 case Q_AUDIO_REMAKE_AUDIO_BUFFER
:
3109 /* buffer needs to be reinitialized */
3110 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3111 audio_start_playback(0, AUDIO_START_RESTART
| AUDIO_START_NEWBUF
);
3114 #ifdef HAVE_DISK_STORAGE
3115 case Q_AUDIO_UPDATE_WATERMARK
:
3116 /* buffering watermark needs updating */
3117 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev
.data
);
3118 audio_update_filebuf_watermark(ev
.data
);
3120 #endif /* HAVE_DISK_STORAGE */
3122 #ifdef AUDIO_HAVE_RECORDING
3123 case Q_AUDIO_LOAD_ENCODER
:
3124 /* load an encoder for recording */
3125 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev
.data
);
3126 audio_on_load_encoder(ev
.data
);
3128 #endif /* AUDIO_HAVE_RECORDING */
3130 case SYS_USB_CONNECTED
:
3131 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3132 audio_stop_playback();
3133 #ifdef PLAYBACK_VOICE
3136 filling
= STATE_USB
;
3137 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3141 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3145 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3152 /* --- Buffering callbacks --- */
3154 /* Called when fullness is below the watermark level */
3155 static void buffer_event_buffer_low_callback(void *data
)
3157 logf("low buffer callback");
3158 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3159 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_BUFFER_LOW
);
3163 /* Called when handles must be discarded in order to buffer new data */
3164 static void buffer_event_rebuffer_callback(void *data
)
3166 logf("rebuffer callback");
3167 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3168 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_REBUFFER
);
3172 /* A handle has completed buffering and all required data is available */
3173 static void buffer_event_finished_callback(void *data
)
3175 int hid
= *(const int *)data
;
3176 const enum data_type htype
= buf_handle_data_type(hid
);
3178 logf("handle %d finished buffering (type:%u)", hid
, (unsigned)htype
);
3180 /* Limit queue traffic */
3184 /* The metadata handle for the last loaded track has been buffered.
3185 We can ask the audio thread to load the rest of the track's data. */
3186 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid
);
3187 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK
, hid
);
3190 case TYPE_PACKET_AUDIO
:
3191 /* Strip any useless trailing tags that are left. */
3194 case TYPE_ATOMIC_AUDIO
:
3195 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid
);
3196 audio_queue_post(Q_AUDIO_HANDLE_FINISHED
, hid
);
3200 /* Don't care to know about these */
3206 /** -- Codec callbacks -- **/
3208 /* Update elapsed time for next PCM insert */
3209 void audio_codec_update_elapsed(unsigned long elapsed
)
3211 #ifdef AB_REPEAT_ENABLE
3212 ab_position_report(elapsed
);
3214 /* Save in codec's id3 where it is used at next pcm insert */
3215 id3_get(CODEC_ID3
)->elapsed
= elapsed
;
3218 /* Update offset for next PCM insert */
3219 void audio_codec_update_offset(size_t offset
)
3221 /* Save in codec's id3 where it is used at next pcm insert */
3222 id3_get(CODEC_ID3
)->offset
= offset
;
3225 /* Codec has finished running */
3226 void audio_codec_complete(int status
)
3228 #ifdef AB_REPEAT_ENABLE
3229 if (status
>= CODEC_OK
)
3231 /* Normal automatic skip */
3232 ab_end_of_track_report();
3236 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status
);
3237 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, status
);
3240 /* Codec has finished seeking */
3241 void audio_codec_seek_complete(void)
3243 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_SEEK_COMPLETE");
3244 audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE
, 0);
3248 /** --- Pcmbuf callbacks --- **/
3250 /* Update the elapsed and offset from the information cached during the
3251 PCM buffer insert */
3252 void audio_pcmbuf_position_callback(unsigned long elapsed
, off_t offset
,
3255 if (key
== position_key
)
3257 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
3258 id3
->elapsed
= elapsed
;
3259 id3
->offset
= offset
;
3263 /* Synchronize position info to the codec's */
3264 void audio_pcmbuf_sync_position(void)
3266 audio_pcmbuf_position_callback(ci
.id3
->elapsed
, ci
.id3
->offset
,
3267 pcmbuf_get_position_key());
3270 /* Post message from pcmbuf that the end of the previous track has just
3272 void audio_pcmbuf_track_change(bool pcmbuf
)
3276 /* Notify of the change in special-purpose semaphore object */
3277 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3278 audio_pcmbuf_track_change_post();
3282 /* Safe to post directly to the queue */
3283 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3284 audio_queue_post(Q_AUDIO_TRACK_CHANGED
, 0);
3288 /* May pcmbuf start PCM playback when the buffer is full enough? */
3289 bool audio_pcmbuf_may_play(void)
3291 return play_status
== PLAY_PLAYING
&& !ff_rw_mode
;
3295 /** -- External interfaces -- **/
3297 /* Return the playback and recording status */
3298 int audio_status(void)
3300 unsigned int ret
= play_status
;
3302 #ifdef AUDIO_HAVE_RECORDING
3303 /* Do this here for constitency with mpeg.c version */
3304 ret
|= pcm_rec_status();
3310 /* Clear all accumulated audio errors for playback and recording */
3311 void audio_error_clear(void)
3313 #ifdef AUDIO_HAVE_RECORDING
3314 pcm_rec_error_clear();
3318 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3319 bool audio_peek_track(struct mp3entry
*id3
, int offset
)
3321 bool retval
= false;
3325 if (play_status
!= PLAY_STOPPED
)
3327 id3
->path
[0] = '\0'; /* Null path means it should be filled now */
3328 retval
= audio_get_track_metadata(offset
+ skip_offset
, id3
) &&
3329 id3
->path
[0] != '\0';
3337 /* Return the mp3entry for the currently playing track */
3338 struct mp3entry
* audio_current_track(void)
3340 struct mp3entry
*id3
;
3344 #ifdef AUDIO_FAST_SKIP_PREVIEW
3345 if (skip_offset
!= 0)
3347 /* This is a peekahead */
3348 id3
= id3_get(PLAYING_PEEK_ID3
);
3349 audio_peek_track(id3
, 0);
3355 id3
= id3_get(PLAYING_ID3
);
3356 audio_get_track_metadata(0, id3
);
3364 /* Obtains the mp3entry for the next track from the current */
3365 struct mp3entry
* audio_next_track(void)
3367 struct mp3entry
*id3
= id3_get(NEXTTRACK_ID3
);
3371 #ifdef AUDIO_FAST_SKIP_PREVIEW
3372 if (skip_offset
!= 0)
3374 /* This is a peekahead */
3375 if (!audio_peek_track(id3
, 1))
3382 if (!audio_get_track_metadata(1, id3
))
3391 /* Start playback at the specified offset */
3392 void audio_play(long offset
)
3396 #ifdef PLAYBACK_VOICE
3397 /* Truncate any existing voice output so we don't have spelling
3398 * etc. over the first part of the played track */
3399 talk_force_shutup();
3402 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
3403 audio_queue_send(Q_AUDIO_PLAY
, offset
);
3406 /* Stop playback if playing */
3407 void audio_stop(void)
3409 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3410 audio_queue_send(Q_AUDIO_STOP
, 0);
3413 /* Pause playback if playing */
3414 void audio_pause(void)
3416 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3417 audio_queue_send(Q_AUDIO_PAUSE
, true);
3420 /* This sends a stop message and the audio thread will dump all its
3421 subsequent messages */
3422 void audio_hard_stop(void)
3425 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3426 audio_queue_send(Q_AUDIO_STOP
, 1);
3427 #ifdef PLAYBACK_VOICE
3430 if (audiobuf_handle
> 0)
3431 audiobuf_handle
= core_free(audiobuf_handle
);
3434 /* Resume playback if paused */
3435 void audio_resume(void)
3437 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3438 audio_queue_send(Q_AUDIO_PAUSE
, false);
3441 /* Skip the specified number of tracks forward or backward from the current */
3442 void audio_skip(int offset
)
3446 /* If offset has to be backed-out to stay in range, no skip is done */
3447 int accum
= skip_offset
+ offset
;
3449 while (offset
!= 0 && !playlist_check(accum
))
3451 offset
+= offset
< 0 ? 1 : -1;
3452 accum
= skip_offset
+ offset
;
3457 /* Accumulate net manual skip count since the audio thread last
3459 skip_offset
= accum
;
3461 system_sound_play(SOUND_TRACK_SKIP
);
3463 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset
);
3465 #ifdef AUDIO_FAST_SKIP_PREVIEW
3466 /* Do this before posting so that the audio thread can correct us
3467 when things settle down - additionally, if audio gets a message
3468 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3469 handler a skip event with the correct info but doesn't skip */
3470 send_event(PLAYBACK_EVENT_TRACK_SKIP
, NULL
);
3471 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3473 /* Playback only needs the final state even if more than one is
3474 processed because it wasn't removed in time */
3475 queue_remove_from_head(&audio_queue
, Q_AUDIO_SKIP
);
3476 audio_queue_post(Q_AUDIO_SKIP
, 0);
3480 /* No more tracks */
3481 system_sound_play(SOUND_TRACK_NO_MORE
);
3487 /* Skip one track forward from the current */
3488 void audio_next(void)
3493 /* Skip one track backward from the current */
3494 void audio_prev(void)
3499 /* Move one directory forward */
3500 void audio_next_dir(void)
3502 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3503 audio_queue_post(Q_AUDIO_DIR_SKIP
, 1);
3506 /* Move one directory backward */
3507 void audio_prev_dir(void)
3509 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3510 audio_queue_post(Q_AUDIO_DIR_SKIP
, -1);
3513 /* Pause playback in order to start a seek that flushes the old audio */
3514 void audio_pre_ff_rewind(void)
3516 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3517 audio_queue_post(Q_AUDIO_PRE_FF_REWIND
, 0);
3520 /* Seek to the new time in the current track */
3521 void audio_ff_rewind(long time
)
3523 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3524 audio_queue_post(Q_AUDIO_FF_REWIND
, time
);
3527 /* Clear all but the currently playing track then rebuffer */
3528 void audio_flush_and_reload_tracks(void)
3530 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3531 audio_queue_post(Q_AUDIO_FLUSH
, 0);
3534 /* Return the pointer to the main audio buffer, optionally preserving
3536 unsigned char * audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
3540 if (audio_is_initialized
)
3544 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3546 if (buffer_size
== NULL
)
3548 /* Special case for talk_init to use since it already knows it's
3550 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3554 /* make sure buffer is freed and re-allocated to simplify code below
3555 * (audio_hard_stop() likely has done that already) */
3556 if (audiobuf_handle
> 0)
3557 audiobuf_handle
= core_free(audiobuf_handle
);
3559 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
3560 buf
= core_get_data(audiobuf_handle
);
3562 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
3563 || !talk_voice_required())
3565 logf("get buffer: talk, audio");
3566 /* Ok to use everything from audiobuf - voice is loaded,
3567 the talk buffer is not needed because voice isn't being used, or
3568 could be AUDIOBUF_STATE_TRASHED already. If state is
3569 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3570 written without the caller knowing what's going on. Changing certain
3571 settings may move it to a worse condition but the memory in use by
3572 something else will remain undisturbed.
3574 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
3576 talk_buffer_steal();
3577 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3582 logf("get buffer: audio");
3583 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3584 still AUDIOBUF_STATE_INITIALIZED */
3585 /* Skip talk buffer and move pcm buffer to end to maximize available
3586 contiguous memory - no audio running means voice will not need the
3588 size_t talkbuf_size
;
3589 buf
+= talkbuf_size
= talkbuf_init(buf
);
3590 filebuflen
-= talkbuf_size
;
3591 filebuflen
-= voicebuf_init(buf
+ filebuflen
);
3593 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
3596 *buffer_size
= filebuflen
;
3600 #ifdef HAVE_RECORDING
3601 /* Stop audio, voice and obtain all available buffer space */
3602 unsigned char * audio_get_recording_buffer(size_t *buffer_size
)
3605 return audio_get_buffer(true, buffer_size
);
3607 #endif /* HAVE_RECORDING */
3609 /* Restore audio buffer to a particular state (one more valid than the current
3611 bool audio_restore_playback(int type
)
3615 case AUDIO_WANT_PLAYBACK
:
3616 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
3617 audio_reset_buffer();
3619 case AUDIO_WANT_VOICE
:
3620 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
3621 audio_reset_buffer();
3629 /** --- Miscellaneous public interfaces --- **/
3631 #ifdef HAVE_ALBUMART
3632 /* Return which album art handle is current for the user in the given slot */
3633 int playback_current_aa_hid(int slot
)
3635 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3637 struct track_info
*info
= track_list_user_current(skip_offset
);
3639 if (!info
&& abs(skip_offset
) <= 1)
3641 /* Give the actual position a go */
3642 info
= track_list_user_current(0);
3646 return info
->aa_hid
[slot
];
3649 return ERR_HANDLE_NOT_FOUND
;
3652 /* Find an album art slot that doesn't match the dimensions of another that
3653 is already claimed - increment the use count if it is */
3654 int playback_claim_aa_slot(struct dim
*dim
)
3658 /* First try to find a slot already having the size to reuse it since we
3659 don't want albumart of the same size buffered multiple times */
3662 struct albumart_slot
*slot
= &albumart_slots
[i
];
3664 if (slot
->dim
.width
== dim
->width
&&
3665 slot
->dim
.height
== dim
->height
)
3672 /* Size is new, find a free slot */
3675 if (!albumart_slots
[i
].used
)
3677 albumart_slots
[i
].used
++;
3678 albumart_slots
[i
].dim
= *dim
;
3683 /* Sorry, no free slot */
3687 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3688 void playback_release_aa_slot(int slot
)
3690 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3692 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
3694 if (aa_slot
->used
> 0)
3698 #endif /* HAVE_ALBUMART */
3701 #ifdef HAVE_RECORDING
3702 /* Load an encoder and run it */
3703 bool audio_load_encoder(int afmt
)
3705 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3706 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
3707 return audio_queue_send(Q_AUDIO_LOAD_ENCODER
, afmt
) != 0;
3714 /* Stop an encoder and unload it */
3715 void audio_remove_encoder(void)
3717 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3718 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3719 audio_queue_send(Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
3722 #endif /* HAVE_RECORDING */
3724 /* Is an automatic skip in progress? If called outside transition callbacks,
3725 indicates the last skip type at the time it was processed and isn't very
3727 bool audio_automatic_skip(void)
3729 return automatic_skip
;
3732 /* Would normally calculate byte offset from an elapsed time but is not
3734 int audio_get_file_pos(void)
3739 /* Return the elapsed time of the track previous to the current */
3740 unsigned long audio_prev_elapsed(void)
3742 return prev_track_elapsed
;
3745 /* Return total file buffer length after accounting for the talk buf */
3746 size_t audio_get_filebuflen(void)
3748 return buf_length();
3751 /* How many tracks exist on the buffer - full or partial */
3752 int audio_track_count(void)
3753 __attribute__((alias("track_list_count")));
3755 /* Return total ringbuffer space occupied - ridx to widx */
3756 long audio_filebufused(void)
3762 /** -- Settings -- **/
3764 /* Enable or disable cuesheet support and allocate/don't allocate the
3765 extra associated resources */
3766 void audio_set_cuesheet(int enable
)
3768 if (play_status
== PLAY_STOPPED
|| !enable
!= !get_current_cuesheet())
3770 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3771 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3775 #ifdef HAVE_DISK_STORAGE
3776 /* Set the audio antiskip buffer margin by index */
3777 void audio_set_buffer_margin(int setting
)
3779 static const unsigned short lookup
[] =
3780 { 5, 15, 30, 60, 120, 180, 300, 600 };
3782 if ((unsigned)setting
>= ARRAYLEN(lookup
))
3785 logf("buffer margin: %u", (unsigned)lookup
[setting
]);
3787 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3788 (unsigned)lookup
[setting
]);
3789 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK
, lookup
[setting
]);
3791 #endif /* HAVE_DISK_STORAGE */
3793 #ifdef HAVE_CROSSFADE
3794 /* Take necessary steps to enable or disable the crossfade setting */
3795 void audio_set_crossfade(int enable
)
3797 /* Tell it the next setting to use */
3798 pcmbuf_request_crossfade_enable(enable
);
3800 /* Return if size hasn't changed or this is too early to determine
3801 which in the second case there's no way we could be playing
3803 if (!pcmbuf_is_same_size())
3805 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3806 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3809 #endif /* HAVE_CROSSFADE */
3812 /** -- Startup -- **/
3814 /* Initialize the audio system - called from init() in main.c */
3815 void audio_init(void)
3817 /* Can never do this twice */
3818 if (audio_is_initialized
)
3820 logf("audio: already initialized");
3824 logf("audio: initializing");
3826 /* Initialize queues before giving control elsewhere in case it likes
3827 to send messages. Thread creation will be delayed however so nothing
3828 starts running until ready if something yields such as talk_init. */
3829 queue_init(&audio_queue
, true);
3831 mutex_init(&id3_mutex
);
3835 codec_thread_init();
3837 /* This thread does buffer, so match its priority */
3838 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
3839 sizeof(audio_stack
), 0, audio_thread_name
3840 IF_PRIO(, MIN(PRIORITY_BUFFERING
, PRIORITY_USER_INTERFACE
))
3843 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
3846 #ifdef PLAYBACK_VOICE
3847 voice_thread_init();
3850 /* audio_reset_buffer must know the size of voice buffer so init
3854 #ifdef HAVE_CROSSFADE
3855 /* Set crossfade setting for next buffer init which should be about... */
3856 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
3859 /* Initialize the buffering system */
3862 /* ...now! Set up the buffers */
3863 audio_reset_buffer();
3865 /* Probably safe to say */
3866 audio_is_initialized
= true;
3868 sound_settings_apply();
3869 #ifdef HAVE_DISK_STORAGE
3870 audio_set_buffer_margin(global_settings
.buffer_margin
);