1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005-2007 Miika Pekkarinen
11 * Copyright (C) 2007-2008 Nicolas Pennequin
12 * Copyright (C) 2011 Michael Sevakis
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
27 #include "core_alloc.h"
32 #include "codec_thread.h"
33 #include "voice_thread.h"
36 #include "buffering.h"
49 #ifdef AUDIO_HAVE_RECORDING
50 #include "pcm_record.h"
53 #ifdef HAVE_LCD_BITMAP
59 /* TODO: The audio thread really is doing multitasking of acting like a
60 consumer and producer of tracks. It may be advantageous to better
61 logically separate the two functions. I won't go that far just yet. */
63 /* Internal support for voice playback */
64 #define PLAYBACK_VOICE
66 #if CONFIG_PLATFORM & PLATFORM_NATIVE
67 /* Application builds don't support direct code loading */
68 #define HAVE_CODEC_BUFFERING
71 /* Amount of guess-space to allow for codecs that must hunt and peck
72 * for their correct seek target, 32k seems a good size */
73 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
75 /* Define LOGF_ENABLE to enable logf output in this file */
76 /* #define LOGF_ENABLE */
79 /* Macros to enable logf for queues
80 logging on SYS_TIMEOUT can be disabled */
82 /* Define this for logf output of all queuing except SYS_TIMEOUT */
83 #define PLAYBACK_LOGQUEUES
84 /* Define this to logf SYS_TIMEOUT messages */
85 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
88 #ifdef PLAYBACK_LOGQUEUES
89 #define LOGFQUEUE logf
91 #define LOGFQUEUE(...)
94 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
95 #define LOGFQUEUE_SYS_TIMEOUT logf
97 #define LOGFQUEUE_SYS_TIMEOUT(...)
100 /* Variables are commented with the threads that use them:
101 * A=audio, C=codec, O=other. A suffix of "-" indicates that the variable is
102 * read but not updated on that thread. Audio is the only user unless otherwise
106 /** Miscellaneous **/
107 bool audio_is_initialized
= false; /* (A,O-) */
108 extern struct codec_api ci
; /* (A,C) */
110 /** Possible arrangements of the main buffer **/
111 static enum audio_buffer_state
113 AUDIOBUF_STATE_TRASHED
= -1, /* trashed; must be reset */
114 AUDIOBUF_STATE_INITIALIZED
= 0, /* voice+audio OR audio-only */
115 AUDIOBUF_STATE_VOICED_ONLY
= 1, /* voice-only */
116 } buffer_state
= AUDIOBUF_STATE_TRASHED
; /* (A,O) */
118 /** Main state control **/
119 static bool ff_rw_mode SHAREDBSS_ATTR
= false; /* Pre-ff-rewind mode (A,O-) */
124 PLAY_PLAYING
= AUDIO_STATUS_PLAY
,
125 PLAY_PAUSED
= AUDIO_STATUS_PLAY
| AUDIO_STATUS_PAUSE
,
126 } play_status
= PLAY_STOPPED
;
128 /* Sizeable things that only need exist during playback and not when stopped */
129 static struct audio_scratch_memory
131 struct mp3entry codec_id3
; /* (A,C) */
132 struct mp3entry unbuffered_id3
;
133 struct cuesheet
*curr_cue
; /* Will follow this structure */
134 } * audio_scratch_memory
= NULL
;
136 /* These are used to store the current, next and optionally the peek-ahead
137 * mp3entry's - this guarantees that the pointer returned by audio_current/
138 * next_track will be valid for the full duration of the currently playing
142 /* These are allocated statically */
145 #ifdef AUDIO_FAST_SKIP_PREVIEW
146 /* The real playing metadata must has to be protected since it contains
147 critical info for other features */
151 /* These go in the scratch memory */
152 UNBUFFERED_ID3
= ID3_TYPE_NUM_STATIC
,
155 static struct mp3entry static_id3_entries
[ID3_TYPE_NUM_STATIC
]; /* (A,O) */
157 /* Peeking functions can yield and mess us up */
158 static struct mutex id3_mutex SHAREDBSS_ATTR
; /* (A,O)*/
161 /** For Scrobbler support **/
163 /* Previous track elapsed time */
164 static unsigned long prev_track_elapsed
= 0; /* (A,O-) */
167 /** For album art support **/
168 #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
171 static struct albumart_slot
173 struct dim dim
; /* Holds width, height of the albumart */
174 int used
; /* Counter; increments if something uses it */
175 } albumart_slots
[MAX_MULTIPLE_AA
]; /* (A,O) */
177 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
178 #endif /* HAVE_ALBUMART */
181 /** Information used for tracking buffer fills **/
183 /* Buffer and thread state tracking */
184 static enum filling_state
186 STATE_IDLE
= 0, /* audio is stopped: nothing to do */
187 STATE_FILLING
, /* adding tracks to the buffer */
188 STATE_FULL
, /* can't add any more tracks */
189 STATE_END_OF_PLAYLIST
, /* all remaining tracks have been added */
190 STATE_FINISHED
, /* all remaining tracks are fully buffered */
191 STATE_ENDING
, /* audio playback is ending */
192 STATE_ENDED
, /* audio playback is done */
193 STATE_USB
, /* USB mode, ignore most messages */
194 } filling
= STATE_IDLE
;
196 /* Track info - holds information about each track in the buffer */
199 /* In per-track allocated order: */
200 int id3_hid
; /* Metadata handle ID */
201 int cuesheet_hid
; /* Parsed cuesheet handle ID */
203 int aa_hid
[MAX_MULTIPLE_AA
];/* Album art handle IDs */
205 #ifdef HAVE_CODEC_BUFFERING
206 int codec_hid
; /* Buffered codec handle ID */
208 int audio_hid
; /* Main audio data handle ID */
209 size_t filesize
; /* File total length on disk
210 TODO: This should be stored
212 id3 and would use less
216 /* Track list - holds info about all buffered tracks */
218 #define TRACK_LIST_LEN 128 /* Must be 2^int(+n) */
219 #elif MEMORYSIZE >= 16
220 #define TRACK_LIST_LEN 64
221 #elif MEMORYSIZE >= 8
222 #define TRACK_LIST_LEN 32
224 #define TRACK_LIST_LEN 16
227 #define TRACK_LIST_MASK (TRACK_LIST_LEN-1)
231 /* read, write and current are maintained unwrapped, limited only by the
232 unsigned int range and wrap-safe comparisons are used */
234 /* NOTE: there appears to be a bug in arm-elf-eabi-gcc 4.4.4 for ARMv4 where
235 if 'end' follows 'start' in this structure, track_list_count performs
236 'start - end' rather than 'end - start', giving negative count values...
237 so leave it this way for now! */
238 unsigned int end
; /* Next open position */
239 unsigned int start
; /* First track in list */
240 unsigned int current
; /* Currently decoding track */
241 struct track_info tracks
[TRACK_LIST_LEN
]; /* Buffered track information */
242 } track_list
; /* (A, O-) */
245 /* Playlist steps from playlist position to next track to be buffered */
246 static int playlist_peek_offset
= 0;
248 /* Metadata handle of track load in progress (meaning all handles have not
249 yet been opened for the track, id3 always exists or the track does not)
251 Tracks are keyed by their metadata handles if track list pointers are
252 insufficient to make comparisons */
253 static int in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
255 #ifdef HAVE_DISK_STORAGE
256 /* Buffer margin A.K.A. anti-skip buffer (in seconds) */
257 static size_t buffer_margin
= 5;
260 /* Values returned for track loading */
261 enum track_load_status
263 LOAD_TRACK_ERR_START_CODEC
= -6,
264 LOAD_TRACK_ERR_FINISH_FAILED
= -5,
265 LOAD_TRACK_ERR_FINISH_FULL
= -4,
266 LOAD_TRACK_ERR_BUSY
= -3,
267 LOAD_TRACK_ERR_NO_MORE
= -2,
268 LOAD_TRACK_ERR_FAILED
= -1,
270 LOAD_TRACK_READY
= 1,
273 /** Track change controls **/
275 /* What sort of skip is pending globally? */
278 /* Relative to what user is intended to see: */
279 /* Codec: +0, Track List: +0, Playlist: +0 */
280 TRACK_SKIP_NONE
= 0, /* no track skip */
281 /* Codec: +1, Track List: +1, Playlist: +0 */
282 TRACK_SKIP_AUTO
, /* codec-initiated skip */
283 /* Codec: +1, Track List: +1, Playlist: +1 */
284 TRACK_SKIP_AUTO_NEW_PLAYLIST
, /* codec-initiated skip is new playlist */
285 /* Codec: xx, Track List: +0, Playlist: +0 */
286 TRACK_SKIP_AUTO_END_PLAYLIST
, /* codec-initiated end of playlist */
287 /* Manual skip: Never pends */
288 TRACK_SKIP_MANUAL
, /* manual track skip */
289 /* Manual skip: Never pends */
290 TRACK_SKIP_DIR_CHANGE
, /* manual directory skip */
291 } skip_pending
= TRACK_SKIP_NONE
;
293 /* Note about TRACK_SKIP_AUTO_NEW_PLAYLIST:
294 Fixing playlist code to be able to peek into the first song of
295 the next playlist would fix any issues and this wouldn't need
296 to be a special case since pre-advancing the playlist would be
297 unneeded - it could be much more like TRACK_SKIP_AUTO and all
298 actions that require reversal during an in-progress transition
299 would work as expected */
301 /* Used to indicate status for the events. Must be separate to satisfy all
302 clients so the correct metadata is read when sending the change events
303 and also so that it is read correctly outside the events. */
304 static bool automatic_skip
= false; /* (A, O-) */
306 /* Pending manual track skip offset */
307 static int skip_offset
= 0; /* (A, O) */
309 /* Track change notification */
312 unsigned int in
; /* Number of pcmbuf posts (audio isr) */
313 unsigned int out
; /* Number of times audio has read the difference */
314 } track_change
= { 0, 0 };
317 /* Did the codec notify us it finished while we were paused or while still
318 in an automatic transition?
320 If paused, it is necessary to defer a codec-initiated skip until resuming
321 or else the track will move forward while not playing audio!
323 If in-progress, skips should not build-up ahead of where the WPS is when
324 really short tracks finish decoding.
326 If it is forgotten, it will be missed altogether and playback will just sit
327 there looking stupid and comatose until the user does something */
328 static bool codec_skip_pending
= false;
329 static int codec_skip_status
;
330 static bool codec_seeking
= false; /* Codec seeking ack expected? */
331 static unsigned int position_key
= 0;
334 static struct event_queue audio_queue SHAREDBSS_ATTR
;
337 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR
;
338 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
339 static const char audio_thread_name
[] = "audio";
340 static unsigned int audio_thread_id
= 0;
342 /* Forward declarations */
343 enum audio_start_playback_flags
345 AUDIO_START_RESTART
= 0x1, /* "Restart" playback (flush _all_ tracks) */
346 AUDIO_START_NEWBUF
= 0x2, /* Mark the audiobuffer as invalid */
349 static void audio_start_playback(size_t offset
, unsigned int flags
);
350 static void audio_stop_playback(void);
351 static void buffer_event_buffer_low_callback(void *data
);
352 static void buffer_event_rebuffer_callback(void *data
);
353 static void buffer_event_finished_callback(void *data
);
354 void audio_pcmbuf_sync_position(void);
357 /**************************************/
359 /** --- audio_queue helpers --- **/
360 static void audio_queue_post(long id
, intptr_t data
)
362 queue_post(&audio_queue
, id
, data
);
365 static intptr_t audio_queue_send(long id
, intptr_t data
)
367 return queue_send(&audio_queue
, id
, data
);
371 /** --- MP3Entry --- **/
373 /* Does the mp3entry have enough info for us to use it? */
374 static struct mp3entry
* valid_mp3entry(const struct mp3entry
*id3
)
376 return id3
&& (id3
->length
!= 0 || id3
->filesize
!= 0) &&
377 id3
->codectype
!= AFMT_UNKNOWN
? (struct mp3entry
*)id3
: NULL
;
380 /* Return a pointer to an mp3entry on the buffer, as it is */
381 static struct mp3entry
* bufgetid3(int handle_id
)
386 struct mp3entry
*id3
;
387 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
389 if (ret
!= sizeof(struct mp3entry
))
395 /* Read an mp3entry from the buffer, adjusted */
396 static bool bufreadid3(int handle_id
, struct mp3entry
*id3out
)
398 struct mp3entry
*id3
= bufgetid3(handle_id
);
402 copy_mp3entry(id3out
, id3
);
409 /* Lock the id3 mutex */
410 static void id3_mutex_lock(void)
412 mutex_lock(&id3_mutex
);
415 /* Unlock the id3 mutex */
416 static void id3_mutex_unlock(void)
418 mutex_unlock(&id3_mutex
);
421 /* Return one of the collection of mp3entry pointers - collect them all here */
422 static inline struct mp3entry
* id3_get(enum audio_id3_types id3_num
)
427 return &audio_scratch_memory
->unbuffered_id3
;
429 return &audio_scratch_memory
->codec_id3
;
431 return &static_id3_entries
[id3_num
];
435 /* Copy an mp3entry into one of the mp3 entries */
436 static void id3_write(enum audio_id3_types id3_num
,
437 const struct mp3entry
*id3_src
)
439 struct mp3entry
*dest_id3
= id3_get(id3_num
);
442 copy_mp3entry(dest_id3
, id3_src
);
444 wipe_mp3entry(dest_id3
);
447 /* Call id3_write "safely" because peek aheads can yield, even if the fast
448 preview isn't enabled */
449 static void id3_write_locked(enum audio_id3_types id3_num
,
450 const struct mp3entry
*id3_src
)
453 id3_write(id3_num
, id3_src
);
458 /** --- Track info --- **/
460 /* Close a handle and mark it invalid */
461 static void track_info_close_handle(int *hid_p
)
465 /* bufclose returns true if the handle is not found, or if it is closed
466 * successfully, so these checks are safe on non-existant handles */
470 /* Always reset to "no handle" in case it was something else */
471 *hid_p
= ERR_HANDLE_NOT_FOUND
;
474 /* Close all handles in a struct track_info and clear it */
475 static void track_info_close(struct track_info
*info
)
477 /* Close them in the order they are allocated on the buffer to speed up
478 the handle searching */
479 track_info_close_handle(&info
->id3_hid
);
480 track_info_close_handle(&info
->cuesheet_hid
);
484 track_info_close_handle(&info
->aa_hid
[i
]);
486 #ifdef HAVE_CODEC_BUFFERING
487 track_info_close_handle(&info
->codec_hid
);
489 track_info_close_handle(&info
->audio_hid
);
493 /* Invalidate all members to initial values - does not close handles */
494 static void track_info_wipe(struct track_info
* info
)
496 info
->id3_hid
= ERR_HANDLE_NOT_FOUND
;
497 info
->cuesheet_hid
= ERR_HANDLE_NOT_FOUND
;
501 info
->aa_hid
[i
] = ERR_HANDLE_NOT_FOUND
;
503 #ifdef HAVE_CODEC_BUFFERING
504 info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
506 info
->audio_hid
= ERR_HANDLE_NOT_FOUND
;
511 /** --- Track list --- **/
513 /* Initialize the track list */
514 static void track_list_init(void)
517 for (i
= 0; i
< TRACK_LIST_LEN
; i
++)
518 track_info_wipe(&track_list
.tracks
[i
]);
520 track_list
.start
= track_list
.end
= track_list
.current
;
523 /* Return number of items allocated in the list */
524 static unsigned int track_list_count(void)
526 return track_list
.end
- track_list
.start
;
529 /* Return true if the list is empty */
530 static inline bool track_list_empty(void)
532 return track_list
.end
== track_list
.start
;
535 /* Returns true if the list is holding the maximum number of items */
536 static bool track_list_full(void)
538 return track_list
.end
- track_list
.start
>= TRACK_LIST_LEN
;
541 /* Test if the index is within the allocated range */
542 static bool track_list_in_range(int pos
)
544 return (int)(pos
- track_list
.start
) >= 0 &&
545 (int)(pos
- track_list
.end
) < 0;
548 static struct track_info
* track_list_entry(int pos
)
550 return &track_list
.tracks
[pos
& TRACK_LIST_MASK
];
553 /* Return the info of the last allocation plus an offset, NULL if result is
555 static struct track_info
* track_list_last(int offset
)
557 /* Last is before the end since the end isn't inclusive */
558 unsigned int pos
= track_list
.end
+ offset
- 1;
560 if (!track_list_in_range(pos
))
563 return track_list_entry(pos
);
566 /* Allocate space at the end for another track if not full */
567 static struct track_info
* track_list_alloc_track(void)
569 if (track_list_full())
572 return track_list_entry(track_list
.end
++);
575 /* Remove the last track entry allocated in order to support backing out
577 static void track_list_unalloc_track(void)
579 if (track_list_empty())
584 if (track_list
.current
== track_list
.end
&&
585 track_list
.current
!= track_list
.start
)
587 /* Current _must_ remain within bounds */
588 track_list
.current
--;
592 /* Return current track plus an offset, NULL if result is out of bounds */
593 static struct track_info
* track_list_current(int offset
)
595 unsigned int pos
= track_list
.current
+ offset
;
597 if (!track_list_in_range(pos
))
600 return track_list_entry(pos
);
603 /* Return current based upon what's intended that the user sees - not
604 necessarily where decoding is taking place */
605 static struct track_info
* track_list_user_current(int offset
)
607 if (skip_pending
== TRACK_SKIP_AUTO
||
608 skip_pending
== TRACK_SKIP_AUTO_NEW_PLAYLIST
)
613 return track_list_current(offset
);
616 /* Advance current track by an offset, return false if result is out of
618 static struct track_info
* track_list_advance_current(int offset
)
620 unsigned int pos
= track_list
.current
+ offset
;
622 if (!track_list_in_range(pos
))
625 track_list
.current
= pos
;
626 return track_list_entry(pos
);
629 /* Clear tracks in the list, optionally preserving the current track -
630 returns 'false' if the operation was changed */
631 enum track_clear_action
633 TRACK_LIST_CLEAR_ALL
= 0, /* Clear all tracks */
634 TRACK_LIST_KEEP_CURRENT
, /* Keep current only; clear before + after */
635 TRACK_LIST_KEEP_NEW
/* Keep current and those that follow */
638 static void track_list_clear(enum track_clear_action action
)
640 logf("%s(%d)", __func__
, (int)action
);
642 /* Don't care now since rebuffering is imminent */
643 buf_set_watermark(0);
645 if (action
!= TRACK_LIST_CLEAR_ALL
)
647 struct track_info
*cur
= track_list_current(0);
649 if (!cur
|| cur
->id3_hid
< 0)
650 action
= TRACK_LIST_CLEAR_ALL
; /* Nothing worthwhile keeping */
653 /* Noone should see this progressing */
654 int start
= track_list
.start
;
655 int current
= track_list
.current
;
656 int end
= track_list
.end
;
658 track_list
.start
= current
;
662 case TRACK_LIST_CLEAR_ALL
:
663 /* Result: .start = .current, .end = .current */
664 track_list
.end
= current
;
667 case TRACK_LIST_KEEP_CURRENT
:
668 /* Result: .start = .current, .end = .current + 1 */
669 track_list
.end
= current
+ 1;
672 case TRACK_LIST_KEEP_NEW
:
673 /* Result: .start = .current, .end = .end */
678 /* Close all open handles in the range except the for the current track
679 if preserving that */
682 if (action
!= TRACK_LIST_KEEP_CURRENT
|| start
!= current
)
684 struct track_info
*info
=
685 &track_list
.tracks
[start
& TRACK_LIST_MASK
];
687 /* If this is the in-progress load, abort it */
688 if (in_progress_id3_hid
>= 0 &&
689 info
->id3_hid
== in_progress_id3_hid
)
691 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
694 track_info_close(info
);
702 /** --- Audio buffer -- **/
704 /* What size is needed for the scratch buffer? */
705 static size_t scratch_mem_size(void)
707 size_t size
= sizeof (struct audio_scratch_memory
);
709 if (global_settings
.cuesheet
)
710 size
+= sizeof (struct cuesheet
);
715 /* Initialize the memory area where data is stored that is only used when
716 playing audio and anything depending upon it */
717 static void scratch_mem_init(void *mem
)
719 audio_scratch_memory
= (struct audio_scratch_memory
*)mem
;
720 id3_write_locked(UNBUFFERED_ID3
, NULL
);
721 id3_write(CODEC_ID3
, NULL
);
722 ci
.id3
= id3_get(CODEC_ID3
);
723 audio_scratch_memory
->curr_cue
= NULL
;
725 if (global_settings
.cuesheet
)
727 audio_scratch_memory
->curr_cue
=
728 SKIPBYTES((struct cuesheet
*)audio_scratch_memory
,
729 sizeof (struct audio_scratch_memory
));
733 static int audiobuf_handle
;
734 #define AUDIO_BUFFER_RESERVE (256*1024)
735 static size_t filebuflen
;
738 size_t audio_buffer_size(void)
740 if (audiobuf_handle
> 0)
741 return filebuflen
- AUDIO_BUFFER_RESERVE
;
745 size_t audio_buffer_available(void)
748 size_t core_size
= core_available();
749 if (audiobuf_handle
> 0) /* if allocated return what we can give */
750 size
= filebuflen
- AUDIO_BUFFER_RESERVE
- 128;
751 return MAX(core_size
, size
);
754 /* Set up the audio buffer for playback
755 * filebuflen must be pre-initialized with the maximum size */
756 static void audio_reset_buffer_noalloc(void* filebuf
)
759 * Layout audio buffer as follows:
760 * [[|TALK]|SCRATCH|BUFFERING|PCM|[VOICE|]]
763 /* see audio_get_recording_buffer if this is modified */
764 logf("%s()", __func__
);
766 /* If the setup of anything allocated before the file buffer is
767 changed, do check the adjustments after the buffer_alloc call
768 as it will likely be affected and need sliding over */
770 /* Initially set up file buffer as all space available */
773 /* Subtract whatever voice needs */
774 allocsize
= talkbuf_init(filebuf
);
775 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
776 if (allocsize
> filebuflen
)
779 filebuf
+= allocsize
;
780 filebuflen
-= allocsize
;
782 if (talk_voice_required())
784 /* Need a space for voice PCM output */
785 allocsize
= voicebuf_init(filebuf
+ filebuflen
);
787 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
788 if (allocsize
> filebuflen
)
791 filebuflen
-= allocsize
;
794 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
795 allocsize
= pcmbuf_init(filebuf
+ filebuflen
);
797 /* Make sure filebuflen is a pointer sized multiple after adjustment */
798 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
799 if (allocsize
> filebuflen
)
802 filebuflen
-= allocsize
;
805 allocsize
= scratch_mem_size();
806 if (allocsize
> filebuflen
)
809 scratch_mem_init(filebuf
);
810 filebuf
+= allocsize
;
811 filebuflen
-= allocsize
;
813 buffering_reset(filebuf
, filebuflen
);
815 /* Clear any references to the file buffer */
816 buffer_state
= AUDIOBUF_STATE_INITIALIZED
;
818 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
819 /* Make sure everything adds up - yes, some info is a bit redundant but
820 aids viewing and the summation of certain variables should add up to
821 the location of others. */
823 logf("fbuf: %08X", (unsigned)filebuf
);
824 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
825 logf("sbuf: %08X", (unsigned)audio_scratch_memory
);
826 logf("sbufe: %08X", (unsigned)(audio_scratch_memory
+ allocsize
));
833 panicf("%s(): EOM (%zu > %zu)", __func__
, allocsize
, filebuflen
);
836 /* Buffer must not move. */
837 static int shrink_callback(int handle
, unsigned hints
, void* start
, size_t old_size
)
839 struct queue_event ev
;
840 static const long filter_list
[][2] =
843 { Q_AUDIO_PLAY
, Q_AUDIO_PLAY
},
845 /* filebuflen is, at this point, the buffering.c buffer size,
846 * i.e. the audiobuf except voice, scratch mem, pcm, ... */
847 ssize_t extradata_size
= old_size
- filebuflen
;
848 /* check what buflib requests */
849 size_t wanted_size
= (hints
& BUFLIB_SHRINK_SIZE_MASK
);
850 ssize_t size
= (ssize_t
)old_size
- wanted_size
;
851 /* keep at least 256K for the buffering */
852 if ((size
- extradata_size
) < AUDIO_BUFFER_RESERVE
)
853 return BUFLIB_CB_CANNOT_SHRINK
;
856 /* TODO: Do it without stopping playback, if possible */
857 long offset
= audio_current_track()->offset
;
858 /* resume if playing */
859 bool playing
= (audio_status() == AUDIO_STATUS_PLAY
);
860 /* There's one problem with stoping and resuming: If it happens in a too
861 * frequent fashion, the codecs lose the resume postion and playback
862 * begins from the beginning.
863 * To work around use queue_post() to effectively delay the resume in case
864 * we're called another time. However this has another problem: id3->offset
865 * gets zero since playback is stopped. Therefore, try to peek at the
866 * queue_post from the last call to get the correct offset. This also
867 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
869 bool play_queued
= queue_peek_ex(&audio_queue
, &ev
, QPEEK_REMOVE_EVENTS
, filter_list
);
871 if (playing
&& offset
> 0) /* current id3->offset is king */
874 /* don't call audio_hard_stop() as it frees this handle */
875 if (thread_self() == audio_thread_id
)
876 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
877 * if we're in the audio thread */
878 audio_stop_playback();
879 queue_clear(&audio_queue
);
882 audio_queue_send(Q_AUDIO_STOP
, 1);
883 #ifdef PLAYBACK_VOICE
886 /* we should be free to change the buffer now
887 * set final buffer size before calling audio_reset_buffer_noalloc()
888 * (now it's the total size, the call will subtract voice etc) */
890 switch (hints
& BUFLIB_SHRINK_POS_MASK
)
892 case BUFLIB_SHRINK_POS_BACK
:
893 core_shrink(handle
, start
, size
);
894 audio_reset_buffer_noalloc(start
);
896 case BUFLIB_SHRINK_POS_FRONT
:
897 core_shrink(handle
, start
+ wanted_size
, size
);
898 audio_reset_buffer_noalloc(start
+ wanted_size
);
901 if (playing
|| play_queued
)
903 /* post, to make subsequent calls not break the resume position */
904 audio_queue_post(Q_AUDIO_PLAY
, ev
.data
);
910 static struct buflib_callbacks ops
= {
911 .move_callback
= NULL
,
912 .shrink_callback
= shrink_callback
,
915 static void audio_reset_buffer(void)
917 if (audiobuf_handle
> 0)
919 core_free(audiobuf_handle
);
922 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
923 unsigned char *filebuf
= core_get_data(audiobuf_handle
);
925 audio_reset_buffer_noalloc(filebuf
);
928 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
929 static void audio_update_filebuf_watermark(int seconds
)
933 #ifdef HAVE_DISK_STORAGE
934 int spinup
= ata_spinup_time();
938 /* By current setting */
939 seconds
= buffer_margin
;
944 buffer_margin
= seconds
;
946 if (buf_get_watermark() == 0)
948 /* Write a watermark only if the audio thread already did so for
949 itself or it will fail to set the event and the watermark - if
950 it hasn't yet, it will use the new setting when it does */
956 seconds
+= (spinup
/ HZ
) + 1;
960 seconds
+= buffer_margin
;
966 /* Watermark is a function of the bitrate of the last track in the buffer */
967 struct mp3entry
*id3
= NULL
;
968 struct track_info
*info
= track_list_last(0);
971 id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
975 if (!rbcodec_format_is_atomic(id3
->codectype
))
977 bytes
= id3
->bitrate
* (1000/8) * seconds
;
981 /* Bitrate has no meaning to buffering margin for atomic audio -
982 rebuffer when it's the only track left unless it's the only
983 track that fits, in which case we should avoid constant buffer
985 if (track_list_count() > 1)
986 bytes
= info
->filesize
+ 1;
991 /* Then set the minimum - this should not occur anyway */
992 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
993 track_list
.start
, track_list
.current
, track_list
.end
);
996 /* Actually setting zero disables the notification and we use that
997 to detect that it has been reset */
998 buf_set_watermark(MAX(bytes
, 1));
999 logf("fwmark: %lu", (unsigned long)bytes
);
1003 /** -- Track change notification -- **/
1005 /* Check the pcmbuf track changes and return write the message into the event
1007 static inline bool audio_pcmbuf_track_change_scan(void)
1009 if (track_change
.out
!= track_change
.in
)
1018 /* Clear outstanding track change posts */
1019 static inline void audio_pcmbuf_track_change_clear(void)
1021 track_change
.out
= track_change
.in
;
1024 /* Post a track change notification - called by audio ISR */
1025 static inline void audio_pcmbuf_track_change_post(void)
1031 /** --- Helper functions --- **/
1033 /* Removes messages that might end up in the queue before or while processing
1034 a manual track change. Responding to them would be harmful since they
1035 belong to a previous track's playback period. Anything that would generate
1036 the stale messages must first be put into a state where it will not do so.
1038 static void audio_clear_track_notifications(void)
1040 static const long filter_list
[][2] =
1042 /* codec messages */
1043 { Q_AUDIO_CODEC_SEEK_COMPLETE
, Q_AUDIO_CODEC_COMPLETE
},
1044 /* track change messages */
1045 { Q_AUDIO_TRACK_CHANGED
, Q_AUDIO_TRACK_CHANGED
},
1048 const int filter_count
= ARRAYLEN(filter_list
) - 1;
1050 /* Remove any pcmbuf notifications */
1051 pcmbuf_monitor_track_change(false);
1052 audio_pcmbuf_track_change_clear();
1054 /* Scrub the audio queue of the old mold */
1055 while (queue_peek_ex(&audio_queue
, NULL
,
1056 filter_count
| QPEEK_REMOVE_EVENTS
,
1059 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1063 /* Takes actions based upon track load status codes */
1064 static void audio_handle_track_load_status(int trackstat
)
1068 case LOAD_TRACK_ERR_NO_MORE
:
1069 if (track_list_count() > 0)
1072 case LOAD_TRACK_ERR_START_CODEC
:
1073 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_ERROR
);
1081 /* Announce the end of playing the current track */
1082 static void audio_playlist_track_finish(void)
1084 struct mp3entry
*ply_id3
= id3_get(PLAYING_ID3
);
1085 struct mp3entry
*id3
= valid_mp3entry(ply_id3
);
1087 playlist_update_resume_info(filling
== STATE_ENDED
? NULL
: id3
);
1091 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
1092 prev_track_elapsed
= id3
->elapsed
;
1096 prev_track_elapsed
= 0;
1100 /* Announce the beginning of the new track */
1101 static void audio_playlist_track_change(void)
1103 struct mp3entry
*id3
= valid_mp3entry(id3_get(PLAYING_ID3
));
1106 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, id3
);
1108 position_key
= pcmbuf_get_position_key();
1110 playlist_update_resume_info(id3
);
1113 /* Change the data for the next track and send the event */
1114 static void audio_update_and_announce_next_track(const struct mp3entry
*id3_next
)
1116 id3_write_locked(NEXTTRACK_ID3
, id3_next
);
1117 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
,
1118 id3_get(NEXTTRACK_ID3
));
1121 /* Bring the user current mp3entry up to date and set a new offset for the
1122 buffered metadata */
1123 static void playing_id3_sync(struct track_info
*user_info
, off_t offset
)
1127 struct mp3entry
*id3
= bufgetid3(user_info
->id3_hid
);
1128 struct mp3entry
*playing_id3
= id3_get(PLAYING_ID3
);
1132 unsigned long e
= playing_id3
->elapsed
;
1133 unsigned long o
= playing_id3
->offset
;
1135 id3_write(PLAYING_ID3
, id3
);
1139 playing_id3
->elapsed
= e
;
1140 playing_id3
->offset
= o
;
1147 id3
->offset
= offset
;
1152 /* Wipe-out track metadata - current is optional */
1153 static void wipe_track_metadata(bool current
)
1158 id3_write(PLAYING_ID3
, NULL
);
1160 id3_write(NEXTTRACK_ID3
, NULL
);
1161 id3_write(UNBUFFERED_ID3
, NULL
);
1166 /* Called when buffering is completed on the last track handle */
1167 static void filling_is_finished(void)
1169 logf("last track finished buffering");
1171 /* There's no more to load or watch for */
1172 buf_set_watermark(0);
1173 filling
= STATE_FINISHED
;
1176 /* Stop the codec decoding or waiting for its data to be ready - returns
1177 'false' if the codec ended up stopped */
1178 static bool halt_decoding_track(bool stop
)
1180 /* If it was waiting for us to clear the buffer to make a rebuffer
1181 happen, it should cease otherwise codec_stop could deadlock waiting
1182 for the codec to go to its main loop - codec's request will now
1184 bool retval
= false;
1186 buf_signal_handle(ci
.audio_hid
, true);
1191 retval
= codec_pause();
1193 audio_clear_track_notifications();
1195 /* We now know it's idle and not waiting for buffered data */
1196 buf_signal_handle(ci
.audio_hid
, false);
1198 codec_skip_pending
= false;
1199 codec_seeking
= false;
1204 /* Wait for any in-progress fade to complete */
1205 static void audio_wait_fade_complete(void)
1207 /* Just loop until it's done */
1208 while (pcmbuf_fading())
1212 /* End the ff/rw mode */
1213 static void audio_ff_rewind_end(void)
1215 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1223 /* Clear the buffer */
1225 audio_pcmbuf_sync_position();
1228 if (play_status
!= PLAY_PAUSED
)
1230 /* Seeking-while-playing, resume PCM playback */
1231 pcmbuf_pause(false);
1236 /* Complete the codec seek */
1237 static void audio_complete_codec_seek(void)
1239 /* If a seek completed while paused, 'paused' is true.
1240 * If seeking from seek mode, 'ff_rw_mode' is true. */
1243 audio_ff_rewind_end();
1244 codec_seeking
= false; /* set _after_ the call! */
1246 /* else it's waiting and we must repond */
1249 /* Get the current cuesheet pointer */
1250 static inline struct cuesheet
* get_current_cuesheet(void)
1252 return audio_scratch_memory
->curr_cue
;
1255 /* Read the cuesheet from the buffer */
1256 static void buf_read_cuesheet(int handle_id
)
1258 struct cuesheet
*cue
= get_current_cuesheet();
1260 if (!cue
|| handle_id
< 0)
1263 bufread(handle_id
, sizeof (struct cuesheet
), cue
);
1266 /* Backend to peek/current/next track metadata interface functions -
1267 fill in the mp3entry with as much information as we may obtain about
1268 the track at the specified offset from the user current track -
1269 returns false if no information exists with us */
1270 static bool audio_get_track_metadata(int offset
, struct mp3entry
*id3
)
1272 if (play_status
== PLAY_STOPPED
)
1275 if (id3
->path
[0] != '\0')
1276 return true; /* Already filled */
1278 struct track_info
*info
= track_list_user_current(offset
);
1282 struct mp3entry
*ub_id3
= id3_get(UNBUFFERED_ID3
);
1284 if (offset
> 0 && track_list_user_current(offset
- 1))
1286 /* Try the unbuffered id3 since we're moving forward */
1287 if (ub_id3
->path
[0] != '\0')
1289 copy_mp3entry(id3
, ub_id3
);
1294 else if (bufreadid3(info
->id3_hid
, id3
))
1296 id3
->cuesheet
= NULL
;
1300 /* We didn't find the ID3 metadata, so we fill it with the little info we
1301 have and return that */
1303 char path
[MAX_PATH
+1];
1304 if (playlist_peek(offset
, path
, sizeof (path
)))
1306 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1307 /* Try to get it from the database */
1308 if (!tagcache_fill_tags(id3
, path
))
1311 /* By now, filename is the only source of info */
1312 fill_metadata_from_path(id3
, path
);
1323 /* Get a resume rewind adjusted offset from the ID3 */
1324 static unsigned long resume_rewind_adjusted_offset(const struct mp3entry
*id3
)
1326 unsigned long offset
= id3
->offset
;
1327 size_t resume_rewind
= global_settings
.resume_rewind
*
1328 id3
->bitrate
* (1000/8);
1330 if (offset
< resume_rewind
)
1333 offset
-= resume_rewind
;
1338 /* Get the codec into ram and initialize it - keep it if it's ready */
1339 static bool audio_init_codec(struct track_info
*track_info
,
1340 struct mp3entry
*track_id3
)
1342 int codt_loaded
= get_audio_base_codec_type(codec_loaded());
1343 int hid
= ERR_HANDLE_NOT_FOUND
;
1345 if (codt_loaded
!= AFMT_UNKNOWN
)
1347 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1349 if (codt
== codt_loaded
)
1351 /* Codec is the same base type */
1352 logf("Reusing prev. codec: %d", track_id3
->codectype
);
1353 #ifdef HAVE_CODEC_BUFFERING
1354 /* Close any buffered codec (we could have skipped directly to a
1355 format transistion that is the same format as the current track
1356 and the buffered one is no longer needed) */
1357 track_info_close_handle(&track_info
->codec_hid
);
1363 /* New codec - first make sure the old one's gone */
1364 logf("Removing prev. codec: %d", codt_loaded
);
1369 logf("New codec: %d/%d", track_id3
->codectype
, codec_loaded());
1371 #ifdef HAVE_CODEC_BUFFERING
1372 /* Codec thread will close the handle even if it fails and will load from
1373 storage if hid is not valid or the buffer load fails */
1374 hid
= track_info
->codec_hid
;
1375 track_info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
1378 return codec_load(hid
, track_id3
->codectype
);
1379 (void)track_info
; /* When codec buffering isn't supported */
1382 /* Start the codec for the current track scheduled to be decoded */
1383 static bool audio_start_codec(bool auto_skip
)
1385 struct track_info
*info
= track_list_current(0);
1386 struct mp3entry
*cur_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1391 buf_pin_handle(info
->id3_hid
, true);
1393 if (!audio_init_codec(info
, cur_id3
))
1395 buf_pin_handle(info
->id3_hid
, false);
1399 #ifdef HAVE_TAGCACHE
1400 bool autoresume_enable
= global_settings
.autoresume_enable
;
1402 if (autoresume_enable
&& !cur_id3
->offset
)
1404 /* Resume all manually selected tracks */
1405 bool resume
= !auto_skip
;
1407 /* Send the "buffer" event to obtain the resume position for the codec */
1408 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1412 /* Automatic skip - do further tests to see if we should just
1413 ignore any autoresume position */
1414 int autoresume_automatic
= global_settings
.autoresume_automatic
;
1416 switch (autoresume_automatic
)
1418 case AUTORESUME_NEXTTRACK_ALWAYS
:
1419 /* Just resume unconditionally */
1422 case AUTORESUME_NEXTTRACK_NEVER
:
1423 /* Force-rewind it */
1426 /* Not "never resume" - pass resume filter? */
1427 resume
= autoresumable(cur_id3
);
1432 cur_id3
->offset
= 0;
1434 logf("%s: Set offset for %s to %lX\n", __func__
,
1435 cur_id3
->title
, cur_id3
->offset
);
1437 #endif /* HAVE_TAGCACHE */
1439 /* Rewind the required amount - if an autoresume was done, this also rewinds
1440 that by the setting's amount
1442 It would be best to have bookkeeping about whether or not the track
1443 sounded or not since skipping to it or else skipping to it while paused
1444 and back again will cause accumulation of silent rewinds - that's not
1445 our job to track directly nor could it be in any reasonable way
1447 cur_id3
->offset
= resume_rewind_adjusted_offset(cur_id3
);
1449 /* Update the codec API with the metadata and track info */
1450 id3_write(CODEC_ID3
, cur_id3
);
1452 ci
.audio_hid
= info
->audio_hid
;
1453 ci
.filesize
= info
->filesize
;
1454 buf_set_base_handle(info
->audio_hid
);
1456 /* All required data is now available for the codec */
1459 #ifdef HAVE_TAGCACHE
1460 if (!autoresume_enable
|| cur_id3
->offset
)
1463 /* Send the "buffer" event now */
1464 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1467 buf_pin_handle(info
->id3_hid
, false);
1470 (void)auto_skip
; /* ifndef HAVE_TAGCACHE */
1474 /** --- Audio thread --- **/
1476 /* Load and parse a cuesheet for the file - returns false if the buffer
1478 static bool audio_load_cuesheet(struct track_info
*info
,
1479 struct mp3entry
*track_id3
)
1481 struct cuesheet
*cue
= get_current_cuesheet();
1482 track_id3
->cuesheet
= NULL
;
1484 if (cue
&& info
->cuesheet_hid
== ERR_HANDLE_NOT_FOUND
)
1486 /* If error other than a full buffer, then mark it "unsupported" to
1487 avoid reloading attempt */
1488 int hid
= ERR_UNSUPPORTED_TYPE
;
1489 struct cuesheet_file cue_file
;
1491 #ifdef HAVE_IO_PRIORITY
1492 buf_back_off_storage(true);
1494 if (look_for_cuesheet_file(track_id3
, &cue_file
))
1496 hid
= bufalloc(NULL
, sizeof (struct cuesheet
), TYPE_CUESHEET
);
1500 void *cuesheet
= NULL
;
1501 bufgetdata(hid
, sizeof (struct cuesheet
), &cuesheet
);
1503 if (parse_cuesheet(&cue_file
, (struct cuesheet
*)cuesheet
))
1505 /* Indicate cuesheet is present (while track remains
1507 track_id3
->cuesheet
= cue
;
1512 hid
= ERR_UNSUPPORTED_TYPE
;
1517 #ifdef HAVE_IO_PRIORITY
1518 buf_back_off_storage(false);
1520 if (hid
== ERR_BUFFER_FULL
)
1522 logf("buffer is full for now (%s)", __func__
);
1528 logf("Cuesheet loading failed");
1530 info
->cuesheet_hid
= hid
;
1537 #ifdef HAVE_ALBUMART
1538 /* Load any album art for the file - returns false if the buffer is full */
1539 static bool audio_load_albumart(struct track_info
*info
,
1540 struct mp3entry
*track_id3
)
1545 struct bufopen_bitmap_data user_data
;
1546 int *aa_hid
= &info
->aa_hid
[i
];
1547 int hid
= ERR_UNSUPPORTED_TYPE
;
1549 /* albumart_slots may change during a yield of bufopen,
1550 * but that's no problem */
1551 if (*aa_hid
>= 0 || *aa_hid
== ERR_UNSUPPORTED_TYPE
||
1552 !albumart_slots
[i
].used
)
1555 memset(&user_data
, 0, sizeof(user_data
));
1556 user_data
.dim
= &albumart_slots
[i
].dim
;
1558 #ifdef HAVE_IO_PRIORITY
1559 buf_back_off_storage(true);
1562 /* We can only decode jpeg for embedded AA */
1563 if (track_id3
->has_embedded_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1565 user_data
.embedded_albumart
= &track_id3
->albumart
;
1566 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1569 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1571 /* No embedded AA or it couldn't be loaded - try other sources */
1572 char path
[MAX_PATH
];
1574 if (find_albumart(track_id3
, path
, sizeof(path
),
1575 &albumart_slots
[i
].dim
))
1577 user_data
.embedded_albumart
= NULL
;
1578 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1582 #ifdef HAVE_IO_PRIORITY
1583 buf_back_off_storage(false);
1585 if (hid
== ERR_BUFFER_FULL
)
1587 logf("buffer is full for now (%s)", __func__
);
1592 /* If error other than a full buffer, then mark it "unsupported"
1593 to avoid reloading attempt */
1596 logf("Album art loading failed");
1597 hid
= ERR_UNSUPPORTED_TYPE
;
1606 #endif /* HAVE_ALBUMART */
1608 #ifdef HAVE_CODEC_BUFFERING
1609 /* Load a codec for the file onto the buffer - assumes we're working from the
1610 currently loading track - not called for the current track */
1611 static bool audio_buffer_codec(struct track_info
*track_info
,
1612 struct mp3entry
*track_id3
)
1614 /* This will not be the current track -> it cannot be the first and the
1615 current track cannot be ahead of buffering -> there is a previous
1616 track entry which is either current or ahead of the current */
1617 struct track_info
*prev_info
= track_list_last(-1);
1618 struct mp3entry
*prev_id3
= bufgetid3(prev_info
->id3_hid
);
1620 /* If the previous codec is the same as this one, there is no need to
1621 put another copy of it on the file buffer (in other words, only
1622 buffer codecs at format transitions) */
1625 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1626 int prev_codt
= get_audio_base_codec_type(prev_id3
->codectype
);
1628 if (codt
== prev_codt
)
1630 logf("Reusing prev. codec: %d", prev_id3
->codectype
);
1634 /* else just load it (harmless) */
1636 /* Load the codec onto the buffer if possible */
1637 const char *codec_fn
= get_codec_filename(track_id3
->codectype
);
1641 char codec_path
[MAX_PATH
+1]; /* Full path to codec */
1642 codec_get_full_path(codec_path
, codec_fn
);
1644 track_info
->codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1646 if (track_info
->codec_hid
>= 0)
1648 logf("Buffered codec: %d", afmt
);
1654 #endif /* HAVE_CODEC_BUFFERING */
1656 /* Load metadata for the next track (with bufopen). The rest of the track
1657 loading will be handled by audio_finish_load_track once the metadata has
1658 been actually loaded by the buffering thread.
1660 Each track is arranged in the buffer as follows:
1661 <id3|[cuesheet|][album art|][codec|]audio>
1663 The next will not be loaded until the previous succeeds if the buffer was
1664 full at the time. To put any metadata after audio would make those handles
1667 static int audio_load_track(void)
1669 if (in_progress_id3_hid
>= 0)
1671 /* There must be an info pointer if the in-progress id3 is even there */
1672 struct track_info
*info
= track_list_last(0);
1674 if (info
->id3_hid
== in_progress_id3_hid
)
1676 if (filling
== STATE_FILLING
)
1678 /* Haven't finished the metadata but the notification is
1679 anticipated to come soon */
1680 logf("%s(): in progress ok: %d". __func__
, info
->id3_hid
);
1681 return LOAD_TRACK_OK
;
1683 else if (filling
== STATE_FULL
)
1685 /* Buffer was full trying to complete the load after the
1686 metadata finished, so attempt to continue - older handles
1687 should have been cleared already */
1688 logf("%s(): finishing load: %d". __func__
, info
->id3_hid
);
1689 filling
= STATE_FILLING
;
1690 buffer_event_finished_callback(&info
->id3_hid
);
1691 return LOAD_TRACK_OK
;
1695 /* Some old, stray buffering message */
1696 logf("%s(): already in progress: %d". __func__
, info
->id3_hid
);
1697 return LOAD_TRACK_ERR_BUSY
;
1700 filling
= STATE_FILLING
;
1702 struct track_info
*info
= track_list_alloc_track();
1705 /* List is full so stop buffering tracks - however, attempt to obtain
1706 metadata as the unbuffered id3 */
1707 logf("No free tracks");
1708 filling
= STATE_FULL
;
1711 playlist_peek_offset
++;
1713 logf("Buffering track: s%u/c%u/e%u/p%d",
1714 track_list
.start
, track_list
.current
, track_list
.end
,
1715 playlist_peek_offset
);
1717 /* Get track name from current playlist read position */
1719 char name_buf
[MAX_PATH
+ 1];
1720 const char *trackname
;
1725 trackname
= playlist_peek(playlist_peek_offset
, name_buf
,
1731 /* Test for broken playlists by probing for the files */
1732 fd
= open(trackname
, O_RDONLY
);
1736 logf("Open failed");
1737 /* Skip invalid entry from playlist */
1738 playlist_skip_entry(NULL
, playlist_peek_offset
);
1740 /* Sync the playlist if it isn't finished */
1741 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1747 /* No track - exhausted the playlist entries */
1748 logf("End-of-playlist");
1749 id3_write_locked(UNBUFFERED_ID3
, NULL
);
1751 if (filling
!= STATE_FULL
)
1752 track_list_unalloc_track(); /* Free this entry */
1754 playlist_peek_offset
--; /* Maintain at last index */
1756 /* We can end up here after the real last track signals its completion
1757 and miss the transition to STATE_FINISHED esp. if dropping the last
1758 songs of a playlist late in their load (2nd stage) */
1759 info
= track_list_last(0);
1761 if (info
&& buf_handle_remaining(info
->audio_hid
) == 0)
1762 filling_is_finished();
1764 filling
= STATE_END_OF_PLAYLIST
;
1766 return LOAD_TRACK_ERR_NO_MORE
;
1769 /* Successfully opened the file - get track metadata */
1770 if (filling
== STATE_FULL
||
1771 (info
->id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
)) < 0)
1773 /* Buffer or track list is full */
1774 struct mp3entry
*ub_id3
;
1776 playlist_peek_offset
--;
1778 /* Load the metadata for the first unbuffered track */
1779 ub_id3
= id3_get(UNBUFFERED_ID3
);
1781 get_metadata(ub_id3
, fd
, trackname
);
1784 if (filling
!= STATE_FULL
)
1786 track_list_unalloc_track();
1787 filling
= STATE_FULL
;
1790 logf("%s: buffer is full for now (%u tracks)", __func__
,
1791 track_list_count());
1795 /* Successful load initiation */
1796 info
->filesize
= filesize(fd
);
1797 in_progress_id3_hid
= info
->id3_hid
; /* Remember what's in-progress */
1801 return LOAD_TRACK_OK
;
1804 /* Second part of the track loading: We now have the metadata available, so we
1805 can load the codec, the album art and finally the audio data.
1806 This is called on the audio thread after the buffering thread calls the
1807 buffering_handle_finished_callback callback. */
1808 static int audio_finish_load_track(struct track_info
*info
)
1810 int trackstat
= LOAD_TRACK_OK
;
1812 if (info
->id3_hid
!= in_progress_id3_hid
)
1814 /* We must not be here if not! */
1815 logf("%s: wrong track %d/%d", __func__
, info
->id3_hid
,
1816 in_progress_id3_hid
);
1817 return LOAD_TRACK_ERR_BUSY
;
1820 /* The current track for decoding (there is always one if the list is
1822 struct track_info
*cur_info
= track_list_current(0);
1823 struct mp3entry
*track_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1827 /* This is an error condition. Track cannot be played without valid
1828 metadata; skip the track. */
1829 logf("No metadata");
1830 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1831 goto audio_finish_load_track_exit
;
1834 /* Try to load a cuesheet for the track */
1835 if (!audio_load_cuesheet(info
, track_id3
))
1837 /* No space for cuesheet on buffer, not an error */
1838 filling
= STATE_FULL
;
1839 goto audio_finish_load_track_exit
;
1842 #ifdef HAVE_ALBUMART
1843 /* Try to load album art for the track */
1844 if (!audio_load_albumart(info
, track_id3
))
1846 /* No space for album art on buffer, not an error */
1847 filling
= STATE_FULL
;
1848 goto audio_finish_load_track_exit
;
1852 /* All handles available to external routines are ready - audio and codec
1853 information is private */
1855 if (info
== track_list_user_current(0))
1857 /* Send only when the track handles could not all be opened ahead of
1858 time for the user's current track - otherwise everything is ready
1859 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1860 send_event(PLAYBACK_EVENT_CUR_TRACK_READY
, id3_get(PLAYING_ID3
));
1863 #ifdef HAVE_CODEC_BUFFERING
1864 /* Try to buffer a codec for the track */
1865 if (info
!= cur_info
&& !audio_buffer_codec(info
, track_id3
))
1867 if (info
->codec_hid
== ERR_BUFFER_FULL
)
1869 /* No space for codec on buffer, not an error */
1870 filling
= STATE_FULL
;
1871 logf("buffer is full for now (%s)", __func__
);
1875 /* This is an error condition, either no codec was found, or
1876 reading the codec file failed part way through, either way,
1878 logf("No codec for: %s", track_id3
->path
);
1879 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1882 goto audio_finish_load_track_exit
;
1884 #endif /* HAVE_CODEC_BUFFERING */
1886 /** Finally, load the audio **/
1887 size_t file_offset
= 0;
1888 track_id3
->elapsed
= 0;
1890 if (track_id3
->offset
>= info
->filesize
)
1891 track_id3
->offset
= 0;
1893 logf("%s: set offset for %s to %lu\n", __func__
,
1894 id3
->title
, (unsigned long)offset
);
1896 /* Adjust for resume rewind so we know what to buffer - starting the codec
1897 calls it again, so we don't save it (and they shouldn't accumulate) */
1898 size_t offset
= resume_rewind_adjusted_offset(track_id3
);
1900 enum data_type audiotype
= rbcodec_format_is_atomic(track_id3
->codectype
) ?
1901 TYPE_ATOMIC_AUDIO
: TYPE_PACKET_AUDIO
;
1903 if (audiotype
== TYPE_ATOMIC_AUDIO
)
1904 logf("Loading atomic %d", track_id3
->codectype
);
1906 if (format_buffers_with_offset(track_id3
->codectype
))
1908 /* This format can begin buffering from any point */
1909 file_offset
= offset
;
1912 logf("load track: %s", track_id3
->path
);
1914 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1916 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1917 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1921 /* No offset given or it is very minimal - begin at the first frame
1922 according to the metadata */
1923 file_offset
= track_id3
->first_frame_offset
;
1926 int hid
= bufopen(track_id3
->path
, file_offset
, audiotype
, NULL
);
1930 info
->audio_hid
= hid
;
1932 if (info
== cur_info
)
1934 /* This is the current track to decode - should be started now */
1935 trackstat
= LOAD_TRACK_READY
;
1940 /* Buffer could be full but not properly so if this is the only
1942 if (hid
== ERR_BUFFER_FULL
&& audio_track_count() > 1)
1944 filling
= STATE_FULL
;
1945 logf("Buffer is full for now (%s)", __func__
);
1949 /* Nothing to play if no audio handle - skip this */
1950 logf("Could not add audio data handle");
1951 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1955 audio_finish_load_track_exit
:
1956 if (trackstat
< LOAD_TRACK_OK
)
1958 playlist_skip_entry(NULL
, playlist_peek_offset
);
1959 track_info_close(info
);
1960 track_list_unalloc_track();
1962 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1965 playlist_peek_offset
--;
1968 if (filling
!= STATE_FULL
)
1970 /* Load next track - error or not */
1971 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
1972 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1973 audio_queue_post(Q_AUDIO_FILL_BUFFER
, 0);
1978 trackstat
= LOAD_TRACK_ERR_FINISH_FULL
;
1984 /* Start a new track load */
1985 static int audio_fill_file_buffer(void)
1987 if (play_status
== PLAY_STOPPED
)
1988 return LOAD_TRACK_ERR_FAILED
;
1990 trigger_cpu_boost();
1992 /* Must reset the buffer before use if trashed or voice only - voice
1993 file size shouldn't have changed so we can go straight from
1994 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1995 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1996 audio_reset_buffer();
1998 logf("Starting buffer fill");
2000 int trackstat
= audio_load_track();
2002 if (trackstat
>= LOAD_TRACK_OK
)
2004 if (track_list_current(0) == track_list_user_current(0))
2007 if (filling
== STATE_FULL
&& !track_list_user_current(1))
2009 /* There are no user tracks on the buffer after this therefore
2010 this is the next track */
2011 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3
));
2018 /* Discard unwanted tracks and start refill from after the specified playlist
2020 static int audio_reset_and_rebuffer(
2021 enum track_clear_action action
, int peek_offset
)
2023 logf("Forcing rebuffer: 0x%X, %d", flags
, peek_offset
);
2025 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2027 /* Remove unwanted tracks - caller must have ensured codec isn't using
2029 track_list_clear(action
);
2031 /* Refill at specified position (-1 starts at index offset 0) */
2032 playlist_peek_offset
= peek_offset
;
2034 /* Fill the buffer */
2035 return audio_fill_file_buffer();
2038 /* Handle buffering events
2039 (Q_AUDIO_BUFFERING) */
2040 static void audio_on_buffering(int event
)
2042 enum track_clear_action action
;
2045 if (track_list_empty())
2050 case BUFFER_EVENT_BUFFER_LOW
:
2051 if (filling
!= STATE_FULL
&& filling
!= STATE_END_OF_PLAYLIST
)
2052 return; /* Should be nothing left to fill */
2054 /* Clear old tracks and continue buffering where it left off */
2055 action
= TRACK_LIST_KEEP_NEW
;
2056 peek_offset
= playlist_peek_offset
;
2059 case BUFFER_EVENT_REBUFFER
:
2060 /* Remove all but the currently decoding track and redo buffering
2062 action
= TRACK_LIST_KEEP_CURRENT
;
2063 peek_offset
= (skip_pending
== TRACK_SKIP_AUTO
) ? 1 : 0;
2070 switch (skip_pending
)
2072 case TRACK_SKIP_NONE
:
2073 case TRACK_SKIP_AUTO
:
2074 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2075 audio_reset_and_rebuffer(action
, peek_offset
);
2078 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2079 /* Already finished */
2084 logf("Buffering call, inv. state: %d", (int)skip_pending
);
2088 /* Handle starting the next track load
2089 (Q_AUDIO_FILL_BUFFER) */
2090 static void audio_on_fill_buffer(void)
2092 audio_handle_track_load_status(audio_fill_file_buffer());
2095 /* Handle posted load track finish event
2096 (Q_AUDIO_FINISH_LOAD_TRACK) */
2097 static void audio_on_finish_load_track(int id3_hid
)
2099 struct track_info
*info
= track_list_last(0);
2101 if (!info
|| !buf_is_handle(id3_hid
))
2104 if (info
== track_list_user_current(1))
2106 /* Just loaded the metadata right after the current position */
2107 audio_update_and_announce_next_track(bufgetid3(info
->id3_hid
));
2110 if (audio_finish_load_track(info
) != LOAD_TRACK_READY
)
2111 return; /* Not current track */
2113 bool is_user_current
= info
== track_list_user_current(0);
2115 if (is_user_current
)
2118 buf_read_cuesheet(info
->cuesheet_hid
);
2121 if (audio_start_codec(automatic_skip
))
2123 if (is_user_current
)
2125 /* Be sure all tagtree info is synchronized; it will be needed for the
2126 track finish event - the sync will happen when finalizing a track
2128 bool was_valid
= valid_mp3entry(id3_get(PLAYING_ID3
));
2130 playing_id3_sync(info
, -1);
2134 /* Playing id3 hadn't been updated yet because no valid track
2135 was yet available - treat like the first track */
2136 audio_playlist_track_change();
2142 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2146 /* Called when handles other than metadata handles have finished buffering
2147 (Q_AUDIO_HANDLE_FINISHED) */
2148 static void audio_on_handle_finished(int hid
)
2150 /* Right now, only audio handles should end up calling this */
2151 if (filling
== STATE_END_OF_PLAYLIST
)
2153 struct track_info
*info
= track_list_last(0);
2155 /* Really we don't know which order the handles will actually complete
2156 to zero bytes remaining since another thread is doing it - be sure
2157 it's the right one */
2158 if (info
&& info
->audio_hid
== hid
)
2160 /* This was the last track in the playlist and we now have all the
2162 filling_is_finished();
2167 /* Called to make an outstanding track skip the current track and to send the
2168 transition events */
2169 static void audio_finalise_track_change(void)
2171 switch (skip_pending
)
2173 case TRACK_SKIP_NONE
: /* Manual skip */
2176 case TRACK_SKIP_AUTO
:
2177 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2179 int playlist_delta
= skip_pending
== TRACK_SKIP_AUTO
? 1 : 0;
2180 audio_playlist_track_finish();
2182 if (!playlist_peek(playlist_delta
, NULL
, 0))
2184 /* Track ended up rejected - push things ahead like the codec blew
2185 it (because it was never started and now we're here where it
2186 should have been decoding the next track by now) - next, a
2187 directory change or end of playback will most likely happen */
2188 skip_pending
= TRACK_SKIP_NONE
;
2189 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2193 if (!playlist_delta
)
2196 playlist_peek_offset
-= playlist_delta
;
2197 if (playlist_next(playlist_delta
) >= 0)
2199 /* What!? Disappear? Hopeless bleak despair */
2202 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2203 default: /* Invalid */
2204 filling
= STATE_ENDED
;
2205 audio_stop_playback();
2209 struct track_info
*info
= track_list_current(0);
2210 struct mp3entry
*track_id3
= NULL
;
2214 /* Update the current cuesheet if any and enabled */
2217 buf_read_cuesheet(info
->cuesheet_hid
);
2218 track_id3
= bufgetid3(info
->id3_hid
);
2221 id3_write(PLAYING_ID3
, track_id3
);
2223 /* The skip is technically over */
2224 skip_pending
= TRACK_SKIP_NONE
;
2226 /* Sync the next track information */
2227 info
= track_list_current(1);
2229 id3_write(NEXTTRACK_ID3
, info
? bufgetid3(info
->id3_hid
) :
2230 id3_get(UNBUFFERED_ID3
));
2234 audio_playlist_track_change();
2237 /* Actually begin a transition and take care of the codec change - may complete
2238 it now or ask pcmbuf for notification depending on the type */
2239 static void audio_begin_track_change(enum pcm_track_change_type type
,
2242 /* Even if the new track is bad, the old track must be finished off */
2243 pcmbuf_start_track_change(type
);
2245 bool auto_skip
= type
!= TRACK_CHANGE_MANUAL
;
2249 /* Manual track change happens now */
2250 audio_finalise_track_change();
2251 pcmbuf_sync_position_update();
2253 if (play_status
== PLAY_STOPPED
)
2254 return; /* Stopped us */
2257 if (trackstat
>= LOAD_TRACK_OK
)
2259 struct track_info
*info
= track_list_current(0);
2261 if (info
->audio_hid
< 0)
2264 /* Everything needed for the codec is ready - start it */
2265 if (audio_start_codec(auto_skip
))
2268 playing_id3_sync(info
, -1);
2272 trackstat
= LOAD_TRACK_ERR_START_CODEC
;
2275 audio_handle_track_load_status(trackstat
);
2278 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2279 static void audio_monitor_end_of_playlist(void)
2281 skip_pending
= TRACK_SKIP_AUTO_END_PLAYLIST
;
2282 filling
= STATE_ENDING
;
2283 pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA
);
2286 /* Codec has completed decoding the track
2287 (usually Q_AUDIO_CODEC_COMPLETE) */
2288 static void audio_on_codec_complete(int status
)
2290 logf("%s(%d)", __func__
, status
);
2292 if (play_status
== PLAY_STOPPED
)
2295 /* If it didn't notify us first, don't expect "seek complete" message
2296 since the codec can't post it now - do things like it would have
2298 audio_complete_codec_seek();
2300 if (play_status
== PLAY_PAUSED
|| skip_pending
!= TRACK_SKIP_NONE
)
2302 /* Old-hay on the ip-skay - codec has completed decoding
2304 Paused: We're not sounding it, so just remember that it happened
2305 and the resume will begin the transition
2307 Skipping: There was already a skip in progress, remember it and
2308 allow no further progress until the PCM from the previous
2311 codec_skip_pending
= true;
2312 codec_skip_status
= status
;
2316 codec_skip_pending
= false;
2318 int trackstat
= LOAD_TRACK_OK
;
2320 automatic_skip
= true;
2321 skip_pending
= TRACK_SKIP_AUTO
;
2323 /* Does this track have an entry allocated? */
2324 struct track_info
*info
= track_list_advance_current(1);
2326 if (!info
|| info
->audio_hid
< 0)
2328 bool end_of_playlist
= false;
2332 /* Track load is not complete - it might have stopped on a
2333 full buffer without reaching the audio handle or we just
2336 If this type is atomic and we couldn't get the audio,
2337 perhaps it would need to wrap to make the allocation and
2338 handles are in the way - to maximize the liklihood it can
2339 be allocated, clear all handles to reset the buffer and
2340 its indexes to 0 - for packet audio, this should not be an
2341 issue and a pointless full reload of all the track's
2342 metadata may be avoided */
2344 struct mp3entry
*track_id3
= bufgetid3(info
->id3_hid
);
2346 if (track_id3
&& !rbcodec_format_is_atomic(track_id3
->codectype
))
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 */
2648 while ((pl_retval
= playlist_next(playlist_delta
)) < 0)
2652 /* Some variety of fatal error while updating playlist */
2653 filling
= STATE_ENDED
;
2654 audio_stop_playback();
2658 /* Manual skip out of range (because the playlist wasn't updated
2659 yet by us and so the check in audio_skip returned 'ok') - bring
2661 int d
= toskip
< 0 ? 1 : -1;
2663 while (!playlist_check(playlist_delta
))
2665 if (playlist_delta
== d
)
2667 /* Had to move the opposite direction to correct, which is
2668 wrong - this is the end */
2669 filling
= STATE_ENDED
;
2670 audio_stop_playback();
2674 playlist_delta
+= d
;
2675 track_list_delta
+= d
;
2679 /* Adjust things by how much the playlist was manually moved */
2680 playlist_peek_offset
-= playlist_delta
;
2682 struct track_info
*info
= track_list_advance_current(track_list_delta
);
2683 int trackstat
= LOAD_TRACK_OK
;
2685 if (!info
|| info
->audio_hid
< 0)
2687 /* We don't know the next track thus we know we don't have it */
2688 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2691 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2694 /* Skip to the next/previous directory
2695 (Q_AUDIO_DIR_SKIP) */
2696 static void audio_on_dir_skip(int direction
)
2698 logf("%s(%d)", __func__
, direction
);
2704 if (play_status
== PLAY_STOPPED
)
2707 /* Force codec to abort this track */
2708 halt_decoding_track(true);
2710 /* Kill the ff/rw halt */
2714 automatic_skip
= false;
2716 audio_playlist_track_finish();
2718 /* Unless automatic and gapless, skips do not pend */
2719 skip_pending
= TRACK_SKIP_NONE
;
2721 /* Regardless of the return value we need to rebuffer. If it fails the old
2722 playlist will resume, else the next dir will start playing. */
2723 playlist_next_dir(direction
);
2725 wipe_track_metadata(false);
2727 int trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2729 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2731 /* The day the music died - finish-off whatever is playing and call it
2733 audio_monitor_end_of_playlist();
2737 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2740 /* Enter seek mode in order to start a seek
2741 (Q_AUDIO_PRE_FF_REWIND) */
2742 static void audio_on_pre_ff_rewind(void)
2744 logf("%s()", __func__
);
2746 if (play_status
== PLAY_STOPPED
|| ff_rw_mode
)
2751 audio_wait_fade_complete();
2753 if (play_status
== PLAY_PAUSED
)
2759 /* Seek the playback of the current track to the specified time
2760 (Q_AUDIO_FF_REWIND) */
2761 static void audio_on_ff_rewind(long time
)
2763 logf("%s(%ld)", __func__
, time
);
2765 if (play_status
== PLAY_STOPPED
)
2768 enum track_skip_type pending
= skip_pending
;
2772 case TRACK_SKIP_NONE
: /* The usual case */
2773 case TRACK_SKIP_AUTO
: /* Have to back it out (fun!) */
2774 case TRACK_SKIP_AUTO_END_PLAYLIST
: /* Still have the last codec used */
2776 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
2777 struct mp3entry
*ci_id3
= id3_get(CODEC_ID3
);
2779 automatic_skip
= false;
2781 /* Send event before clobbering the time */
2782 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2783 then skipping back to this track resumes properly. Something else
2784 should be sent. We're not _really_ finishing the track are we? */
2786 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
2788 id3
->elapsed
= time
;
2789 queue_reply(&audio_queue
, 1);
2791 bool haltres
= halt_decoding_track(pending
== TRACK_SKIP_AUTO
);
2793 /* Need this set in case ff/rw mode + error but _after_ the codec
2794 halt that will reset it */
2795 codec_seeking
= true;
2797 /* If in transition, key will have changed - sync to it */
2798 position_key
= pcmbuf_get_position_key();
2800 if (pending
== TRACK_SKIP_AUTO
)
2802 if (!track_list_advance_current(-1))
2804 /* Not in list - must rebuffer at the current playlist index */
2805 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1)
2808 /* Codec is stopped */
2814 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2815 rebuffer is needed */
2816 skip_pending
= TRACK_SKIP_NONE
;
2817 struct track_info
*cur_info
= track_list_current(0);
2819 /* Track must complete the loading _now_ since a codec and audio
2820 handle are needed in order to do the seek */
2821 if (cur_info
->audio_hid
< 0 &&
2822 audio_finish_load_track(cur_info
) != LOAD_TRACK_READY
)
2824 /* Call above should push any load sequence - no need for
2825 halt_decoding_track here if no skip was pending here because
2826 there would not be a codec started if no audio handle was yet
2831 if (pending
== TRACK_SKIP_AUTO
)
2833 if (!bufreadid3(cur_info
->id3_hid
, ci_id3
) ||
2834 !audio_init_codec(cur_info
, ci_id3
))
2836 /* We should have still been able to get it - skip it and move
2837 onto the next one - like it or not this track is broken */
2841 /* Set the codec API to the correct metadata and track info */
2842 ci
.audio_hid
= cur_info
->audio_hid
;
2843 ci
.filesize
= cur_info
->filesize
;
2844 buf_set_base_handle(cur_info
->audio_hid
);
2849 /* If codec must be (re)started, reset the offset */
2857 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2859 /* We cannot do this because the playlist must be reversed by one
2860 and it doesn't always return the same song when going backwards
2861 across boundaries as forwards (either because of randomization
2862 or inconsistency in deciding what the previous track should be),
2863 therefore the whole operation would often end up as nonsense -
2864 lock out seeking for a couple seconds */
2866 /* Sure as heck cancel seek mode too! */
2867 audio_ff_rewind_end();
2872 /* Won't see this */
2876 if (play_status
== PLAY_STOPPED
)
2878 /* Playback ended because of an error completing a track load */
2882 /* Always fake it as a codec start error which will handle mode
2883 cancellations and skip to the next track */
2884 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2887 /* Invalidates all but currently playing track
2889 static void audio_on_audio_flush(void)
2891 logf("%s", __func__
);
2893 if (track_list_empty())
2894 return; /* Nothing to flush out */
2896 switch (skip_pending
)
2898 case TRACK_SKIP_NONE
:
2899 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2900 /* Remove all but the currently playing track from the list and
2901 refill after that */
2902 track_list_clear(TRACK_LIST_KEEP_CURRENT
);
2903 playlist_peek_offset
= 0;
2904 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2905 audio_update_and_announce_next_track(NULL
);
2907 /* Ignore return since it's about the next track, not this one */
2908 audio_fill_file_buffer();
2910 if (skip_pending
== TRACK_SKIP_NONE
)
2913 /* There's now a track after this one now - convert to auto skip -
2914 no skip should pend right now because multiple flush messages can
2915 be fired which would cause a restart in the below cases */
2916 skip_pending
= TRACK_SKIP_NONE
;
2917 audio_clear_track_notifications();
2918 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_OK
);
2921 case TRACK_SKIP_AUTO
:
2922 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2923 /* Precisely removing what it already decoded for the next track is
2924 not possible so a restart is required in order to continue the
2925 currently playing track without the now invalid future track
2927 audio_start_playback(0, AUDIO_START_RESTART
);
2930 default: /* Nothing else is a state */
2935 #ifdef AUDIO_HAVE_RECORDING
2936 /* Load the requested encoder type
2937 (Q_AUDIO_LOAD_ENCODER) */
2938 static void audio_on_load_encoder(int afmt
)
2942 if (play_status
!= PLAY_STOPPED
)
2943 audio_stop_playback(); /* Can't load both types at once */
2945 codec_unload(); /* Encoder still loaded, stop and unload it */
2947 if (afmt
!= AFMT_UNKNOWN
)
2949 res
= codec_load(-1, afmt
| CODEC_TYPE_ENCODER
);
2951 codec_go(); /* These are run immediately */
2954 queue_reply(&audio_queue
, res
);
2956 #endif /* AUDIO_HAVE_RECORDING */
2958 static void audio_thread(void)
2960 struct queue_event ev
;
2970 case STATE_END_OF_PLAYLIST
:
2971 if (buf_get_watermark() == 0)
2973 /* End of buffering for now, let's calculate the watermark,
2974 register for a low buffer event and unboost */
2975 audio_update_filebuf_watermark(0);
2976 add_event(BUFFER_EVENT_BUFFER_LOW
, true,
2977 buffer_event_buffer_low_callback
);
2980 case STATE_FINISHED
:
2981 /* All data was buffered */
2986 if (audio_pcmbuf_track_change_scan())
2988 /* Transfer notification to audio queue event */
2989 ev
.id
= Q_AUDIO_TRACK_CHANGED
;
2994 /* If doing auto skip, poll pcmbuf track notifications a bit
2995 faster to promply detect the transition */
2996 queue_wait_w_tmo(&audio_queue
, &ev
,
2997 skip_pending
== TRACK_SKIP_NONE
?
3004 queue_wait(&audio_queue
, &ev
);
3006 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3009 #ifdef AUDIO_HAVE_RECORDING
3010 /* Must monitor the encoder message for recording so it can remove
3011 it if we process the insertion before it does. It cannot simply
3012 be removed from under recording however. */
3013 case Q_AUDIO_LOAD_ENCODER
:
3016 case SYS_USB_DISCONNECTED
:
3017 filling
= STATE_IDLE
;
3021 if (filling
== STATE_USB
)
3024 #endif /* CONFIG_PLATFORM */
3029 /** Codec and track change messages **/
3030 case Q_AUDIO_CODEC_COMPLETE
:
3031 /* Codec is done processing track and has gone idle */
3032 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev
.data
);
3033 audio_on_codec_complete(ev
.data
);
3036 case Q_AUDIO_CODEC_SEEK_COMPLETE
:
3037 /* Codec is done seeking */
3038 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
3039 audio_on_codec_seek_complete();
3042 case Q_AUDIO_TRACK_CHANGED
:
3043 /* PCM track change done */
3044 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3045 audio_on_track_changed();
3048 /** Control messages **/
3050 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3051 audio_start_playback(ev
.data
, 0);
3055 LOGFQUEUE("audio < Q_AUDIO_STOP");
3056 audio_stop_playback();
3058 queue_clear(&audio_queue
);
3062 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3063 audio_on_pause(ev
.data
);
3067 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3071 case Q_AUDIO_DIR_SKIP
:
3072 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3073 audio_on_dir_skip(ev
.data
);
3076 case Q_AUDIO_PRE_FF_REWIND
:
3077 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3078 audio_on_pre_ff_rewind();
3081 case Q_AUDIO_FF_REWIND
:
3082 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3083 audio_on_ff_rewind(ev
.data
);
3087 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev
.data
);
3088 audio_on_audio_flush();
3091 /** Buffering messages **/
3092 case Q_AUDIO_BUFFERING
:
3093 /* some buffering event */
3094 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev
.data
);
3095 audio_on_buffering(ev
.data
);
3098 case Q_AUDIO_FILL_BUFFER
:
3099 /* continue buffering next track */
3100 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3101 audio_on_fill_buffer();
3104 case Q_AUDIO_FINISH_LOAD_TRACK
:
3105 /* metadata is buffered */
3106 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3107 audio_on_finish_load_track(ev
.data
);
3110 case Q_AUDIO_HANDLE_FINISHED
:
3111 /* some other type is buffered */
3112 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3113 audio_on_handle_finished(ev
.data
);
3116 /** Miscellaneous messages **/
3117 case Q_AUDIO_REMAKE_AUDIO_BUFFER
:
3118 /* buffer needs to be reinitialized */
3119 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3120 audio_start_playback(0, AUDIO_START_RESTART
| AUDIO_START_NEWBUF
);
3123 #ifdef HAVE_DISK_STORAGE
3124 case Q_AUDIO_UPDATE_WATERMARK
:
3125 /* buffering watermark needs updating */
3126 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev
.data
);
3127 audio_update_filebuf_watermark(ev
.data
);
3129 #endif /* HAVE_DISK_STORAGE */
3131 #ifdef AUDIO_HAVE_RECORDING
3132 case Q_AUDIO_LOAD_ENCODER
:
3133 /* load an encoder for recording */
3134 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev
.data
);
3135 audio_on_load_encoder(ev
.data
);
3137 #endif /* AUDIO_HAVE_RECORDING */
3139 case SYS_USB_CONNECTED
:
3140 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3141 audio_stop_playback();
3142 #ifdef PLAYBACK_VOICE
3145 filling
= STATE_USB
;
3146 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3150 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3154 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3161 /* --- Buffering callbacks --- */
3163 /* Called when fullness is below the watermark level */
3164 static void buffer_event_buffer_low_callback(void *data
)
3166 logf("low buffer callback");
3167 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3168 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_BUFFER_LOW
);
3172 /* Called when handles must be discarded in order to buffer new data */
3173 static void buffer_event_rebuffer_callback(void *data
)
3175 logf("rebuffer callback");
3176 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3177 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_REBUFFER
);
3181 /* A handle has completed buffering and all required data is available */
3182 static void buffer_event_finished_callback(void *data
)
3184 int hid
= *(const int *)data
;
3185 const enum data_type htype
= buf_handle_data_type(hid
);
3187 logf("handle %d finished buffering (type:%u)", hid
, (unsigned)htype
);
3189 /* Limit queue traffic */
3193 /* The metadata handle for the last loaded track has been buffered.
3194 We can ask the audio thread to load the rest of the track's data. */
3195 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid
);
3196 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK
, hid
);
3199 case TYPE_PACKET_AUDIO
:
3200 /* Strip any useless trailing tags that are left. */
3203 case TYPE_ATOMIC_AUDIO
:
3204 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid
);
3205 audio_queue_post(Q_AUDIO_HANDLE_FINISHED
, hid
);
3209 /* Don't care to know about these */
3215 /** -- Codec callbacks -- **/
3217 /* Update elapsed time for next PCM insert */
3218 void audio_codec_update_elapsed(unsigned long elapsed
)
3220 #ifdef AB_REPEAT_ENABLE
3221 ab_position_report(elapsed
);
3223 /* Save in codec's id3 where it is used at next pcm insert */
3224 id3_get(CODEC_ID3
)->elapsed
= elapsed
;
3227 /* Update offset for next PCM insert */
3228 void audio_codec_update_offset(size_t offset
)
3230 /* Save in codec's id3 where it is used at next pcm insert */
3231 id3_get(CODEC_ID3
)->offset
= offset
;
3234 /* Codec has finished running */
3235 void audio_codec_complete(int status
)
3237 #ifdef AB_REPEAT_ENABLE
3238 if (status
>= CODEC_OK
)
3240 /* Normal automatic skip */
3241 ab_end_of_track_report();
3245 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status
);
3246 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, status
);
3249 /* Codec has finished seeking */
3250 void audio_codec_seek_complete(void)
3252 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_SEEK_COMPLETE");
3253 audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE
, 0);
3257 /** --- Pcmbuf callbacks --- **/
3259 /* Update the elapsed and offset from the information cached during the
3260 PCM buffer insert */
3261 void audio_pcmbuf_position_callback(unsigned long elapsed
, off_t offset
,
3264 if (key
== position_key
)
3266 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
3267 id3
->elapsed
= elapsed
;
3268 id3
->offset
= offset
;
3272 /* Synchronize position info to the codec's */
3273 void audio_pcmbuf_sync_position(void)
3275 audio_pcmbuf_position_callback(ci
.id3
->elapsed
, ci
.id3
->offset
,
3276 pcmbuf_get_position_key());
3279 /* Post message from pcmbuf that the end of the previous track has just
3281 void audio_pcmbuf_track_change(bool pcmbuf
)
3285 /* Notify of the change in special-purpose semaphore object */
3286 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3287 audio_pcmbuf_track_change_post();
3291 /* Safe to post directly to the queue */
3292 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3293 audio_queue_post(Q_AUDIO_TRACK_CHANGED
, 0);
3297 /* May pcmbuf start PCM playback when the buffer is full enough? */
3298 bool audio_pcmbuf_may_play(void)
3300 return play_status
== PLAY_PLAYING
&& !ff_rw_mode
;
3304 /** -- External interfaces -- **/
3306 /* Return the playback and recording status */
3307 int audio_status(void)
3309 unsigned int ret
= play_status
;
3311 #ifdef AUDIO_HAVE_RECORDING
3312 /* Do this here for constitency with mpeg.c version */
3313 ret
|= pcm_rec_status();
3319 /* Clear all accumulated audio errors for playback and recording */
3320 void audio_error_clear(void)
3322 #ifdef AUDIO_HAVE_RECORDING
3323 pcm_rec_error_clear();
3327 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3328 bool audio_peek_track(struct mp3entry
*id3
, int offset
)
3330 bool retval
= false;
3334 if (play_status
!= PLAY_STOPPED
)
3336 id3
->path
[0] = '\0'; /* Null path means it should be filled now */
3337 retval
= audio_get_track_metadata(offset
+ skip_offset
, id3
) &&
3338 id3
->path
[0] != '\0';
3346 /* Return the mp3entry for the currently playing track */
3347 struct mp3entry
* audio_current_track(void)
3349 struct mp3entry
*id3
;
3353 #ifdef AUDIO_FAST_SKIP_PREVIEW
3354 if (skip_offset
!= 0)
3356 /* This is a peekahead */
3357 id3
= id3_get(PLAYING_PEEK_ID3
);
3358 audio_peek_track(id3
, 0);
3364 id3
= id3_get(PLAYING_ID3
);
3365 audio_get_track_metadata(0, id3
);
3373 /* Obtains the mp3entry for the next track from the current */
3374 struct mp3entry
* audio_next_track(void)
3376 struct mp3entry
*id3
= id3_get(NEXTTRACK_ID3
);
3380 #ifdef AUDIO_FAST_SKIP_PREVIEW
3381 if (skip_offset
!= 0)
3383 /* This is a peekahead */
3384 if (!audio_peek_track(id3
, 1))
3391 if (!audio_get_track_metadata(1, id3
))
3400 /* Start playback at the specified offset */
3401 void audio_play(long offset
)
3405 #ifdef PLAYBACK_VOICE
3406 /* Truncate any existing voice output so we don't have spelling
3407 * etc. over the first part of the played track */
3408 talk_force_shutup();
3411 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
3412 audio_queue_send(Q_AUDIO_PLAY
, offset
);
3415 /* Stop playback if playing */
3416 void audio_stop(void)
3418 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3419 audio_queue_send(Q_AUDIO_STOP
, 0);
3422 /* Pause playback if playing */
3423 void audio_pause(void)
3425 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3426 audio_queue_send(Q_AUDIO_PAUSE
, true);
3429 /* This sends a stop message and the audio thread will dump all its
3430 subsequent messages */
3431 void audio_hard_stop(void)
3434 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3435 audio_queue_send(Q_AUDIO_STOP
, 1);
3436 #ifdef PLAYBACK_VOICE
3439 if (audiobuf_handle
> 0)
3440 audiobuf_handle
= core_free(audiobuf_handle
);
3443 /* Resume playback if paused */
3444 void audio_resume(void)
3446 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3447 audio_queue_send(Q_AUDIO_PAUSE
, false);
3450 /* Skip the specified number of tracks forward or backward from the current */
3451 void audio_skip(int offset
)
3455 /* If offset has to be backed-out to stay in range, no skip is done */
3456 int accum
= skip_offset
+ offset
;
3458 while (offset
!= 0 && !playlist_check(accum
))
3460 offset
+= offset
< 0 ? 1 : -1;
3461 accum
= skip_offset
+ offset
;
3466 /* Accumulate net manual skip count since the audio thread last
3468 skip_offset
= accum
;
3470 system_sound_play(SOUND_TRACK_SKIP
);
3472 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset
);
3474 #ifdef AUDIO_FAST_SKIP_PREVIEW
3475 /* Do this before posting so that the audio thread can correct us
3476 when things settle down - additionally, if audio gets a message
3477 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3478 handler a skip event with the correct info but doesn't skip */
3479 send_event(PLAYBACK_EVENT_TRACK_SKIP
, NULL
);
3480 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3482 /* Playback only needs the final state even if more than one is
3483 processed because it wasn't removed in time */
3484 queue_remove_from_head(&audio_queue
, Q_AUDIO_SKIP
);
3485 audio_queue_post(Q_AUDIO_SKIP
, 0);
3489 /* No more tracks */
3490 system_sound_play(SOUND_TRACK_NO_MORE
);
3496 /* Skip one track forward from the current */
3497 void audio_next(void)
3502 /* Skip one track backward from the current */
3503 void audio_prev(void)
3508 /* Move one directory forward */
3509 void audio_next_dir(void)
3511 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3512 audio_queue_post(Q_AUDIO_DIR_SKIP
, 1);
3515 /* Move one directory backward */
3516 void audio_prev_dir(void)
3518 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3519 audio_queue_post(Q_AUDIO_DIR_SKIP
, -1);
3522 /* Pause playback in order to start a seek that flushes the old audio */
3523 void audio_pre_ff_rewind(void)
3525 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3526 audio_queue_post(Q_AUDIO_PRE_FF_REWIND
, 0);
3529 /* Seek to the new time in the current track */
3530 void audio_ff_rewind(long time
)
3532 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3533 audio_queue_post(Q_AUDIO_FF_REWIND
, time
);
3536 /* Clear all but the currently playing track then rebuffer */
3537 void audio_flush_and_reload_tracks(void)
3539 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3540 audio_queue_post(Q_AUDIO_FLUSH
, 0);
3543 /* Return the pointer to the main audio buffer, optionally preserving
3545 unsigned char * audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
3549 if (audio_is_initialized
)
3553 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3555 if (buffer_size
== NULL
)
3557 /* Special case for talk_init to use since it already knows it's
3559 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3563 /* make sure buffer is freed and re-allocated to simplify code below
3564 * (audio_hard_stop() likely has done that already) */
3565 if (audiobuf_handle
> 0)
3566 audiobuf_handle
= core_free(audiobuf_handle
);
3568 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
3569 buf
= core_get_data(audiobuf_handle
);
3571 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
3572 || !talk_voice_required())
3574 logf("get buffer: talk, audio");
3575 /* Ok to use everything from audiobuf - voice is loaded,
3576 the talk buffer is not needed because voice isn't being used, or
3577 could be AUDIOBUF_STATE_TRASHED already. If state is
3578 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3579 written without the caller knowing what's going on. Changing certain
3580 settings may move it to a worse condition but the memory in use by
3581 something else will remain undisturbed.
3583 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
3585 talk_buffer_steal();
3586 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3591 logf("get buffer: audio");
3592 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3593 still AUDIOBUF_STATE_INITIALIZED */
3594 /* Skip talk buffer and move pcm buffer to end to maximize available
3595 contiguous memory - no audio running means voice will not need the
3597 size_t talkbuf_size
;
3598 buf
+= talkbuf_size
= talkbuf_init(buf
);
3599 filebuflen
-= talkbuf_size
;
3600 filebuflen
-= voicebuf_init(buf
+ filebuflen
);
3602 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
3605 *buffer_size
= filebuflen
;
3609 #ifdef HAVE_RECORDING
3610 /* Stop audio, voice and obtain all available buffer space */
3611 unsigned char * audio_get_recording_buffer(size_t *buffer_size
)
3614 return audio_get_buffer(true, buffer_size
);
3616 #endif /* HAVE_RECORDING */
3618 /* Restore audio buffer to a particular state (one more valid than the current
3620 bool audio_restore_playback(int type
)
3624 case AUDIO_WANT_PLAYBACK
:
3625 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
3626 audio_reset_buffer();
3628 case AUDIO_WANT_VOICE
:
3629 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
3630 audio_reset_buffer();
3638 /** --- Miscellaneous public interfaces --- **/
3640 #ifdef HAVE_ALBUMART
3641 /* Return which album art handle is current for the user in the given slot */
3642 int playback_current_aa_hid(int slot
)
3644 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3646 struct track_info
*info
= track_list_user_current(skip_offset
);
3648 if (!info
&& abs(skip_offset
) <= 1)
3650 /* Give the actual position a go */
3651 info
= track_list_user_current(0);
3655 return info
->aa_hid
[slot
];
3658 return ERR_HANDLE_NOT_FOUND
;
3661 /* Find an album art slot that doesn't match the dimensions of another that
3662 is already claimed - increment the use count if it is */
3663 int playback_claim_aa_slot(struct dim
*dim
)
3667 /* First try to find a slot already having the size to reuse it since we
3668 don't want albumart of the same size buffered multiple times */
3671 struct albumart_slot
*slot
= &albumart_slots
[i
];
3673 if (slot
->dim
.width
== dim
->width
&&
3674 slot
->dim
.height
== dim
->height
)
3681 /* Size is new, find a free slot */
3684 if (!albumart_slots
[i
].used
)
3686 albumart_slots
[i
].used
++;
3687 albumart_slots
[i
].dim
= *dim
;
3692 /* Sorry, no free slot */
3696 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3697 void playback_release_aa_slot(int slot
)
3699 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3701 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
3703 if (aa_slot
->used
> 0)
3707 #endif /* HAVE_ALBUMART */
3710 #ifdef HAVE_RECORDING
3711 /* Load an encoder and run it */
3712 bool audio_load_encoder(int afmt
)
3714 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3715 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
3716 return audio_queue_send(Q_AUDIO_LOAD_ENCODER
, afmt
) != 0;
3723 /* Stop an encoder and unload it */
3724 void audio_remove_encoder(void)
3726 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3727 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3728 audio_queue_send(Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
3731 #endif /* HAVE_RECORDING */
3733 /* Is an automatic skip in progress? If called outside transition callbacks,
3734 indicates the last skip type at the time it was processed and isn't very
3736 bool audio_automatic_skip(void)
3738 return automatic_skip
;
3741 /* Would normally calculate byte offset from an elapsed time but is not
3743 int audio_get_file_pos(void)
3748 /* Return the elapsed time of the track previous to the current */
3749 unsigned long audio_prev_elapsed(void)
3751 return prev_track_elapsed
;
3754 /* Return total file buffer length after accounting for the talk buf */
3755 size_t audio_get_filebuflen(void)
3757 return buf_length();
3760 /* How many tracks exist on the buffer - full or partial */
3761 int audio_track_count(void)
3762 __attribute__((alias("track_list_count")));
3764 /* Return total ringbuffer space occupied - ridx to widx */
3765 long audio_filebufused(void)
3771 /** -- Settings -- **/
3773 /* Enable or disable cuesheet support and allocate/don't allocate the
3774 extra associated resources */
3775 void audio_set_cuesheet(int enable
)
3777 if (play_status
== PLAY_STOPPED
|| !enable
!= !get_current_cuesheet())
3779 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3780 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3784 #ifdef HAVE_DISK_STORAGE
3785 /* Set the audio antiskip buffer margin by index */
3786 void audio_set_buffer_margin(int setting
)
3788 static const unsigned short lookup
[] =
3789 { 5, 15, 30, 60, 120, 180, 300, 600 };
3791 if ((unsigned)setting
>= ARRAYLEN(lookup
))
3794 logf("buffer margin: %u", (unsigned)lookup
[setting
]);
3796 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3797 (unsigned)lookup
[setting
]);
3798 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK
, lookup
[setting
]);
3800 #endif /* HAVE_DISK_STORAGE */
3802 #ifdef HAVE_CROSSFADE
3803 /* Take necessary steps to enable or disable the crossfade setting */
3804 void audio_set_crossfade(int enable
)
3806 /* Tell it the next setting to use */
3807 pcmbuf_request_crossfade_enable(enable
);
3809 /* Return if size hasn't changed or this is too early to determine
3810 which in the second case there's no way we could be playing
3812 if (!pcmbuf_is_same_size())
3814 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3815 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3818 #endif /* HAVE_CROSSFADE */
3821 /** -- Startup -- **/
3823 /* Initialize the audio system - called from init() in main.c */
3824 void audio_init(void)
3826 /* Can never do this twice */
3827 if (audio_is_initialized
)
3829 logf("audio: already initialized");
3833 logf("audio: initializing");
3835 /* Initialize queues before giving control elsewhere in case it likes
3836 to send messages. Thread creation will be delayed however so nothing
3837 starts running until ready if something yields such as talk_init. */
3838 queue_init(&audio_queue
, true);
3840 mutex_init(&id3_mutex
);
3844 codec_thread_init();
3846 /* This thread does buffer, so match its priority */
3847 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
3848 sizeof(audio_stack
), 0, audio_thread_name
3849 IF_PRIO(, MIN(PRIORITY_BUFFERING
, PRIORITY_USER_INTERFACE
))
3852 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
3855 #ifdef PLAYBACK_VOICE
3856 voice_thread_init();
3859 /* audio_reset_buffer must know the size of voice buffer so init
3863 #ifdef HAVE_CROSSFADE
3864 /* Set crossfade setting for next buffer init which should be about... */
3865 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
3868 /* Initialize the buffering system */
3871 /* ...now! Set up the buffers */
3872 audio_reset_buffer();
3874 /* Probably safe to say */
3875 audio_is_initialized
= true;
3877 sound_settings_apply();
3878 #ifdef HAVE_DISK_STORAGE
3879 audio_set_buffer_margin(global_settings
.buffer_margin
);