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(
757 void *filebuf
, enum audio_buffer_state state
)
760 * Layout audio buffer as follows:
761 * [[|TALK]|SCRATCH|BUFFERING|PCM]
764 /* see audio_get_recording_buffer if this is modified */
765 logf("%s()", __func__
);
767 /* If the setup of anything allocated before the file buffer is
768 changed, do check the adjustments after the buffer_alloc call
769 as it will likely be affected and need sliding over */
771 /* Initially set up file buffer as all space available */
774 /* Subtract whatever voice needs (we're called when promoting
776 allocsize
= talkbuf_init(filebuf
);
777 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
778 if (allocsize
> filebuflen
)
781 filebuf
+= allocsize
;
782 filebuflen
-= allocsize
;
784 if (state
== AUDIOBUF_STATE_INITIALIZED
)
786 /* Subtract whatever the pcm buffer says it used plus the guard
788 allocsize
= pcmbuf_init(filebuf
+ filebuflen
);
790 /* Make sure filebuflen is a pointer sized multiple after
792 allocsize
= ALIGN_UP(allocsize
, sizeof (intptr_t));
793 if (allocsize
> filebuflen
)
796 filebuflen
-= allocsize
;
799 allocsize
= scratch_mem_size();
800 if (allocsize
> filebuflen
)
803 scratch_mem_init(filebuf
);
804 filebuf
+= allocsize
;
805 filebuflen
-= allocsize
;
807 buffering_reset(filebuf
, filebuflen
);
810 buffer_state
= state
;
812 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
813 /* Make sure everything adds up - yes, some info is a bit redundant but
814 aids viewing and the summation of certain variables should add up to
815 the location of others. */
817 logf("fbuf: %08X", (unsigned)filebuf
);
818 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
819 logf("sbuf: %08X", (unsigned)audio_scratch_memory
);
820 logf("sbufe: %08X", (unsigned)(audio_scratch_memory
+ allocsize
));
827 panicf("%s(): EOM (%zu > %zu)", __func__
, allocsize
, filebuflen
);
830 /* Buffer must not move. */
831 static int shrink_callback(int handle
, unsigned hints
, void* start
, size_t old_size
)
833 struct queue_event ev
;
834 static const long filter_list
[][2] =
837 { Q_AUDIO_PLAY
, Q_AUDIO_PLAY
},
839 /* filebuflen is, at this point, the buffering.c buffer size,
840 * i.e. the audiobuf except voice, scratch mem, pcm, ... */
841 ssize_t extradata_size
= old_size
- filebuflen
;
842 /* check what buflib requests */
843 size_t wanted_size
= (hints
& BUFLIB_SHRINK_SIZE_MASK
);
844 ssize_t size
= (ssize_t
)old_size
- wanted_size
;
845 /* keep at least 256K for the buffering */
846 if ((size
- extradata_size
) < AUDIO_BUFFER_RESERVE
)
847 return BUFLIB_CB_CANNOT_SHRINK
;
850 /* TODO: Do it without stopping playback, if possible */
851 long offset
= audio_current_track()->offset
;
852 /* resume if playing */
853 bool playing
= (audio_status() == AUDIO_STATUS_PLAY
);
854 /* There's one problem with stoping and resuming: If it happens in a too
855 * frequent fashion, the codecs lose the resume postion and playback
856 * begins from the beginning.
857 * To work around use queue_post() to effectively delay the resume in case
858 * we're called another time. However this has another problem: id3->offset
859 * gets zero since playback is stopped. Therefore, try to peek at the
860 * queue_post from the last call to get the correct offset. This also
861 * lets us conviniently remove the queue event so Q_AUDIO_PLAY is only
863 bool play_queued
= queue_peek_ex(&audio_queue
, &ev
, QPEEK_REMOVE_EVENTS
, filter_list
);
865 if (playing
&& offset
> 0) /* current id3->offset is king */
868 /* don't call audio_hard_stop() as it frees this handle */
869 if (thread_self() == audio_thread_id
)
870 { /* inline case Q_AUDIO_STOP (audio_hard_stop() response
871 * if we're in the audio thread */
872 audio_stop_playback();
873 queue_clear(&audio_queue
);
876 audio_queue_send(Q_AUDIO_STOP
, 1);
877 #ifdef PLAYBACK_VOICE
880 /* we should be free to change the buffer now
881 * set final buffer size before calling audio_reset_buffer_noalloc()
882 * (now it's the total size, the call will subtract voice etc) */
884 switch (hints
& BUFLIB_SHRINK_POS_MASK
)
886 case BUFLIB_SHRINK_POS_BACK
:
887 core_shrink(handle
, start
, size
);
888 audio_reset_buffer_noalloc(start
, buffer_state
);
890 case BUFLIB_SHRINK_POS_FRONT
:
891 core_shrink(handle
, start
+ wanted_size
, size
);
892 audio_reset_buffer_noalloc(start
+ wanted_size
,
896 if (playing
|| play_queued
)
898 /* post, to make subsequent calls not break the resume position */
899 audio_queue_post(Q_AUDIO_PLAY
, ev
.data
);
905 static struct buflib_callbacks ops
= {
906 .move_callback
= NULL
,
907 .shrink_callback
= shrink_callback
,
910 static void audio_reset_buffer(enum audio_buffer_state state
)
912 if (audiobuf_handle
> 0)
914 core_free(audiobuf_handle
);
917 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
918 unsigned char *filebuf
= core_get_data(audiobuf_handle
);
920 audio_reset_buffer_noalloc(filebuf
, state
);
923 /* Set the buffer margin to begin rebuffering when 'seconds' from empty */
924 static void audio_update_filebuf_watermark(int seconds
)
928 #ifdef HAVE_DISK_STORAGE
929 int spinup
= ata_spinup_time();
933 /* By current setting */
934 seconds
= buffer_margin
;
939 buffer_margin
= seconds
;
941 if (buf_get_watermark() == 0)
943 /* Write a watermark only if the audio thread already did so for
944 itself or it will fail to set the event and the watermark - if
945 it hasn't yet, it will use the new setting when it does */
951 seconds
+= (spinup
/ HZ
) + 1;
955 seconds
+= buffer_margin
;
961 /* Watermark is a function of the bitrate of the last track in the buffer */
962 struct mp3entry
*id3
= NULL
;
963 struct track_info
*info
= track_list_last(0);
966 id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
970 if (!rbcodec_format_is_atomic(id3
->codectype
))
972 bytes
= id3
->bitrate
* (1000/8) * seconds
;
976 /* Bitrate has no meaning to buffering margin for atomic audio -
977 rebuffer when it's the only track left unless it's the only
978 track that fits, in which case we should avoid constant buffer
980 if (track_list_count() > 1)
981 bytes
= info
->filesize
+ 1;
986 /* Then set the minimum - this should not occur anyway */
987 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
988 track_list
.start
, track_list
.current
, track_list
.end
);
991 /* Actually setting zero disables the notification and we use that
992 to detect that it has been reset */
993 buf_set_watermark(MAX(bytes
, 1));
994 logf("fwmark: %lu", (unsigned long)bytes
);
998 /** -- Track change notification -- **/
1000 /* Check the pcmbuf track changes and return write the message into the event
1002 static inline bool audio_pcmbuf_track_change_scan(void)
1004 if (track_change
.out
!= track_change
.in
)
1013 /* Clear outstanding track change posts */
1014 static inline void audio_pcmbuf_track_change_clear(void)
1016 track_change
.out
= track_change
.in
;
1019 /* Post a track change notification - called by audio ISR */
1020 static inline void audio_pcmbuf_track_change_post(void)
1026 /** --- Helper functions --- **/
1028 /* Removes messages that might end up in the queue before or while processing
1029 a manual track change. Responding to them would be harmful since they
1030 belong to a previous track's playback period. Anything that would generate
1031 the stale messages must first be put into a state where it will not do so.
1033 static void audio_clear_track_notifications(void)
1035 static const long filter_list
[][2] =
1037 /* codec messages */
1038 { Q_AUDIO_CODEC_SEEK_COMPLETE
, Q_AUDIO_CODEC_COMPLETE
},
1039 /* track change messages */
1040 { Q_AUDIO_TRACK_CHANGED
, Q_AUDIO_TRACK_CHANGED
},
1043 const int filter_count
= ARRAYLEN(filter_list
) - 1;
1045 /* Remove any pcmbuf notifications */
1046 pcmbuf_monitor_track_change(false);
1047 audio_pcmbuf_track_change_clear();
1049 /* Scrub the audio queue of the old mold */
1050 while (queue_peek_ex(&audio_queue
, NULL
,
1051 filter_count
| QPEEK_REMOVE_EVENTS
,
1054 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
1058 /* Takes actions based upon track load status codes */
1059 static void audio_handle_track_load_status(int trackstat
)
1063 case LOAD_TRACK_ERR_NO_MORE
:
1064 if (track_list_count() > 0)
1067 case LOAD_TRACK_ERR_START_CODEC
:
1068 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_ERROR
);
1076 /* Announce the end of playing the current track */
1077 static void audio_playlist_track_finish(void)
1079 struct mp3entry
*ply_id3
= id3_get(PLAYING_ID3
);
1080 struct mp3entry
*id3
= valid_mp3entry(ply_id3
);
1082 playlist_update_resume_info(filling
== STATE_ENDED
? NULL
: id3
);
1086 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
1087 prev_track_elapsed
= id3
->elapsed
;
1091 prev_track_elapsed
= 0;
1095 /* Announce the beginning of the new track */
1096 static void audio_playlist_track_change(void)
1098 struct mp3entry
*id3
= valid_mp3entry(id3_get(PLAYING_ID3
));
1101 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, id3
);
1103 position_key
= pcmbuf_get_position_key();
1105 playlist_update_resume_info(id3
);
1108 /* Change the data for the next track and send the event */
1109 static void audio_update_and_announce_next_track(const struct mp3entry
*id3_next
)
1111 id3_write_locked(NEXTTRACK_ID3
, id3_next
);
1112 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
,
1113 id3_get(NEXTTRACK_ID3
));
1116 /* Bring the user current mp3entry up to date and set a new offset for the
1117 buffered metadata */
1118 static void playing_id3_sync(struct track_info
*user_info
, off_t offset
)
1122 struct mp3entry
*id3
= bufgetid3(user_info
->id3_hid
);
1123 struct mp3entry
*playing_id3
= id3_get(PLAYING_ID3
);
1127 unsigned long e
= playing_id3
->elapsed
;
1128 unsigned long o
= playing_id3
->offset
;
1130 id3_write(PLAYING_ID3
, id3
);
1134 playing_id3
->elapsed
= e
;
1135 playing_id3
->offset
= o
;
1142 id3
->offset
= offset
;
1147 /* Wipe-out track metadata - current is optional */
1148 static void wipe_track_metadata(bool current
)
1153 id3_write(PLAYING_ID3
, NULL
);
1155 id3_write(NEXTTRACK_ID3
, NULL
);
1156 id3_write(UNBUFFERED_ID3
, NULL
);
1161 /* Called when buffering is completed on the last track handle */
1162 static void filling_is_finished(void)
1164 logf("last track finished buffering");
1166 /* There's no more to load or watch for */
1167 buf_set_watermark(0);
1168 filling
= STATE_FINISHED
;
1171 /* Stop the codec decoding or waiting for its data to be ready - returns
1172 'false' if the codec ended up stopped */
1173 static bool halt_decoding_track(bool stop
)
1175 /* If it was waiting for us to clear the buffer to make a rebuffer
1176 happen, it should cease otherwise codec_stop could deadlock waiting
1177 for the codec to go to its main loop - codec's request will now
1179 bool retval
= false;
1181 buf_signal_handle(ci
.audio_hid
, true);
1186 retval
= codec_pause();
1188 audio_clear_track_notifications();
1190 /* We now know it's idle and not waiting for buffered data */
1191 buf_signal_handle(ci
.audio_hid
, false);
1193 codec_skip_pending
= false;
1194 codec_seeking
= false;
1199 /* Wait for any in-progress fade to complete */
1200 static void audio_wait_fade_complete(void)
1202 /* Just loop until it's done */
1203 while (pcmbuf_fading())
1207 /* End the ff/rw mode */
1208 static void audio_ff_rewind_end(void)
1210 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1218 /* Clear the buffer */
1220 audio_pcmbuf_sync_position();
1223 if (play_status
!= PLAY_PAUSED
)
1225 /* Seeking-while-playing, resume PCM playback */
1226 pcmbuf_pause(false);
1231 /* Complete the codec seek */
1232 static void audio_complete_codec_seek(void)
1234 /* If a seek completed while paused, 'paused' is true.
1235 * If seeking from seek mode, 'ff_rw_mode' is true. */
1238 audio_ff_rewind_end();
1239 codec_seeking
= false; /* set _after_ the call! */
1241 /* else it's waiting and we must repond */
1244 /* Get the current cuesheet pointer */
1245 static inline struct cuesheet
* get_current_cuesheet(void)
1247 return audio_scratch_memory
->curr_cue
;
1250 /* Read the cuesheet from the buffer */
1251 static void buf_read_cuesheet(int handle_id
)
1253 struct cuesheet
*cue
= get_current_cuesheet();
1255 if (!cue
|| handle_id
< 0)
1258 bufread(handle_id
, sizeof (struct cuesheet
), cue
);
1261 /* Backend to peek/current/next track metadata interface functions -
1262 fill in the mp3entry with as much information as we may obtain about
1263 the track at the specified offset from the user current track -
1264 returns false if no information exists with us */
1265 static bool audio_get_track_metadata(int offset
, struct mp3entry
*id3
)
1267 if (play_status
== PLAY_STOPPED
)
1270 if (id3
->path
[0] != '\0')
1271 return true; /* Already filled */
1273 struct track_info
*info
= track_list_user_current(offset
);
1277 struct mp3entry
*ub_id3
= id3_get(UNBUFFERED_ID3
);
1279 if (offset
> 0 && track_list_user_current(offset
- 1))
1281 /* Try the unbuffered id3 since we're moving forward */
1282 if (ub_id3
->path
[0] != '\0')
1284 copy_mp3entry(id3
, ub_id3
);
1289 else if (bufreadid3(info
->id3_hid
, id3
))
1291 id3
->cuesheet
= NULL
;
1295 /* We didn't find the ID3 metadata, so we fill it with the little info we
1296 have and return that */
1298 char path
[MAX_PATH
+1];
1299 if (playlist_peek(offset
, path
, sizeof (path
)))
1301 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1302 /* Try to get it from the database */
1303 if (!tagcache_fill_tags(id3
, path
))
1306 /* By now, filename is the only source of info */
1307 fill_metadata_from_path(id3
, path
);
1318 /* Get a resume rewind adjusted offset from the ID3 */
1319 static unsigned long resume_rewind_adjusted_offset(const struct mp3entry
*id3
)
1321 unsigned long offset
= id3
->offset
;
1322 size_t resume_rewind
= global_settings
.resume_rewind
*
1323 id3
->bitrate
* (1000/8);
1325 if (offset
< resume_rewind
)
1328 offset
-= resume_rewind
;
1333 /* Get the codec into ram and initialize it - keep it if it's ready */
1334 static bool audio_init_codec(struct track_info
*track_info
,
1335 struct mp3entry
*track_id3
)
1337 int codt_loaded
= get_audio_base_codec_type(codec_loaded());
1338 int hid
= ERR_HANDLE_NOT_FOUND
;
1340 if (codt_loaded
!= AFMT_UNKNOWN
)
1342 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1344 if (codt
== codt_loaded
)
1346 /* Codec is the same base type */
1347 logf("Reusing prev. codec: %d", track_id3
->codectype
);
1348 #ifdef HAVE_CODEC_BUFFERING
1349 /* Close any buffered codec (we could have skipped directly to a
1350 format transistion that is the same format as the current track
1351 and the buffered one is no longer needed) */
1352 track_info_close_handle(&track_info
->codec_hid
);
1358 /* New codec - first make sure the old one's gone */
1359 logf("Removing prev. codec: %d", codt_loaded
);
1364 logf("New codec: %d/%d", track_id3
->codectype
, codec_loaded());
1366 #ifdef HAVE_CODEC_BUFFERING
1367 /* Codec thread will close the handle even if it fails and will load from
1368 storage if hid is not valid or the buffer load fails */
1369 hid
= track_info
->codec_hid
;
1370 track_info
->codec_hid
= ERR_HANDLE_NOT_FOUND
;
1373 return codec_load(hid
, track_id3
->codectype
);
1374 (void)track_info
; /* When codec buffering isn't supported */
1377 #ifdef HAVE_TAGCACHE
1378 /* Check settings for whether the file should be autoresumed */
1379 enum { AUTORESUMABLE_UNKNOWN
= 0, AUTORESUMABLE_TRUE
, AUTORESUMABLE_FALSE
};
1380 static bool autoresumable(struct mp3entry
*id3
)
1386 if (id3
->autoresumable
) /* result cached? */
1387 return id3
->autoresumable
== AUTORESUMABLE_TRUE
;
1389 is_resumable
= false;
1393 for (path
= global_settings
.autoresume_paths
;
1394 *path
; /* search terms left? */
1397 if (*path
== ':') /* Skip empty search patterns */
1400 /* FIXME: As soon as strcspn or strchrnul are made available in
1401 the core, the following can be made more efficient. */
1402 endp
= strchr(path
, ':');
1408 /* Note: At this point, len is always > 0 */
1410 if (strncasecmp(id3
->path
, path
, len
) == 0)
1412 /* Full directory-name matches only. Trailing '/' in
1414 if (id3
->path
[len
] == '/' || id3
->path
[len
- 1] == '/')
1416 is_resumable
= true;
1425 id3
->autoresumable
=
1426 is_resumable
? AUTORESUMABLE_TRUE
: AUTORESUMABLE_FALSE
;
1428 logf("autoresumable: %s is%s resumable",
1429 id3
->path
, is_resumable
? "" : " not");
1431 return is_resumable
;
1433 #endif /* HAVE_TAGCACHE */
1435 /* Start the codec for the current track scheduled to be decoded */
1436 static bool audio_start_codec(bool auto_skip
)
1438 struct track_info
*info
= track_list_current(0);
1439 struct mp3entry
*cur_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1444 buf_pin_handle(info
->id3_hid
, true);
1446 if (!audio_init_codec(info
, cur_id3
))
1448 buf_pin_handle(info
->id3_hid
, false);
1452 #ifdef HAVE_TAGCACHE
1453 bool autoresume_enable
= global_settings
.autoresume_enable
;
1455 if (autoresume_enable
&& !cur_id3
->offset
)
1457 /* Resume all manually selected tracks */
1458 bool resume
= !auto_skip
;
1460 /* Send the "buffer" event to obtain the resume position for the codec */
1461 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1465 /* Automatic skip - do further tests to see if we should just
1466 ignore any autoresume position */
1467 int autoresume_automatic
= global_settings
.autoresume_automatic
;
1469 switch (autoresume_automatic
)
1471 case AUTORESUME_NEXTTRACK_ALWAYS
:
1472 /* Just resume unconditionally */
1475 case AUTORESUME_NEXTTRACK_NEVER
:
1476 /* Force-rewind it */
1479 /* Not "never resume" - pass resume filter? */
1480 resume
= autoresumable(cur_id3
);
1485 cur_id3
->offset
= 0;
1487 logf("%s: Set offset for %s to %lX\n", __func__
,
1488 cur_id3
->title
, cur_id3
->offset
);
1490 #endif /* HAVE_TAGCACHE */
1492 /* Rewind the required amount - if an autoresume was done, this also rewinds
1493 that by the setting's amount
1495 It would be best to have bookkeeping about whether or not the track
1496 sounded or not since skipping to it or else skipping to it while paused
1497 and back again will cause accumulation of silent rewinds - that's not
1498 our job to track directly nor could it be in any reasonable way
1500 cur_id3
->offset
= resume_rewind_adjusted_offset(cur_id3
);
1502 /* Update the codec API with the metadata and track info */
1503 id3_write(CODEC_ID3
, cur_id3
);
1505 ci
.audio_hid
= info
->audio_hid
;
1506 ci
.filesize
= info
->filesize
;
1507 buf_set_base_handle(info
->audio_hid
);
1509 /* All required data is now available for the codec */
1512 #ifdef HAVE_TAGCACHE
1513 if (!autoresume_enable
|| cur_id3
->offset
)
1516 /* Send the "buffer" event now */
1517 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, cur_id3
);
1520 buf_pin_handle(info
->id3_hid
, false);
1523 (void)auto_skip
; /* ifndef HAVE_TAGCACHE */
1527 /** --- Audio thread --- **/
1529 /* Load and parse a cuesheet for the file - returns false if the buffer
1531 static bool audio_load_cuesheet(struct track_info
*info
,
1532 struct mp3entry
*track_id3
)
1534 struct cuesheet
*cue
= get_current_cuesheet();
1535 track_id3
->cuesheet
= NULL
;
1537 if (cue
&& info
->cuesheet_hid
== ERR_HANDLE_NOT_FOUND
)
1539 /* If error other than a full buffer, then mark it "unsupported" to
1540 avoid reloading attempt */
1541 int hid
= ERR_UNSUPPORTED_TYPE
;
1542 struct cuesheet_file cue_file
;
1544 #ifdef HAVE_IO_PRIORITY
1545 buf_back_off_storage(true);
1547 if (look_for_cuesheet_file(track_id3
, &cue_file
))
1549 hid
= bufalloc(NULL
, sizeof (struct cuesheet
), TYPE_CUESHEET
);
1553 void *cuesheet
= NULL
;
1554 bufgetdata(hid
, sizeof (struct cuesheet
), &cuesheet
);
1556 if (parse_cuesheet(&cue_file
, (struct cuesheet
*)cuesheet
))
1558 /* Indicate cuesheet is present (while track remains
1560 track_id3
->cuesheet
= cue
;
1565 hid
= ERR_UNSUPPORTED_TYPE
;
1570 #ifdef HAVE_IO_PRIORITY
1571 buf_back_off_storage(false);
1573 if (hid
== ERR_BUFFER_FULL
)
1575 logf("buffer is full for now (%s)", __func__
);
1581 logf("Cuesheet loading failed");
1583 info
->cuesheet_hid
= hid
;
1590 #ifdef HAVE_ALBUMART
1591 /* Load any album art for the file - returns false if the buffer is full */
1592 static bool audio_load_albumart(struct track_info
*info
,
1593 struct mp3entry
*track_id3
)
1598 struct bufopen_bitmap_data user_data
;
1599 int *aa_hid
= &info
->aa_hid
[i
];
1600 int hid
= ERR_UNSUPPORTED_TYPE
;
1602 /* albumart_slots may change during a yield of bufopen,
1603 * but that's no problem */
1604 if (*aa_hid
>= 0 || *aa_hid
== ERR_UNSUPPORTED_TYPE
||
1605 !albumart_slots
[i
].used
)
1608 memset(&user_data
, 0, sizeof(user_data
));
1609 user_data
.dim
= &albumart_slots
[i
].dim
;
1611 #ifdef HAVE_IO_PRIORITY
1612 buf_back_off_storage(true);
1615 /* We can only decode jpeg for embedded AA */
1616 if (track_id3
->has_embedded_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1618 user_data
.embedded_albumart
= &track_id3
->albumart
;
1619 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1622 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1624 /* No embedded AA or it couldn't be loaded - try other sources */
1625 char path
[MAX_PATH
];
1627 if (find_albumart(track_id3
, path
, sizeof(path
),
1628 &albumart_slots
[i
].dim
))
1630 user_data
.embedded_albumart
= NULL
;
1631 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1635 #ifdef HAVE_IO_PRIORITY
1636 buf_back_off_storage(false);
1638 if (hid
== ERR_BUFFER_FULL
)
1640 logf("buffer is full for now (%s)", __func__
);
1645 /* If error other than a full buffer, then mark it "unsupported"
1646 to avoid reloading attempt */
1649 logf("Album art loading failed");
1650 hid
= ERR_UNSUPPORTED_TYPE
;
1659 #endif /* HAVE_ALBUMART */
1661 #ifdef HAVE_CODEC_BUFFERING
1662 /* Load a codec for the file onto the buffer - assumes we're working from the
1663 currently loading track - not called for the current track */
1664 static bool audio_buffer_codec(struct track_info
*track_info
,
1665 struct mp3entry
*track_id3
)
1667 /* This will not be the current track -> it cannot be the first and the
1668 current track cannot be ahead of buffering -> there is a previous
1669 track entry which is either current or ahead of the current */
1670 struct track_info
*prev_info
= track_list_last(-1);
1671 struct mp3entry
*prev_id3
= bufgetid3(prev_info
->id3_hid
);
1673 /* If the previous codec is the same as this one, there is no need to
1674 put another copy of it on the file buffer (in other words, only
1675 buffer codecs at format transitions) */
1678 int codt
= get_audio_base_codec_type(track_id3
->codectype
);
1679 int prev_codt
= get_audio_base_codec_type(prev_id3
->codectype
);
1681 if (codt
== prev_codt
)
1683 logf("Reusing prev. codec: %d", prev_id3
->codectype
);
1687 /* else just load it (harmless) */
1689 /* Load the codec onto the buffer if possible */
1690 const char *codec_fn
= get_codec_filename(track_id3
->codectype
);
1694 char codec_path
[MAX_PATH
+1]; /* Full path to codec */
1695 codec_get_full_path(codec_path
, codec_fn
);
1697 track_info
->codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1699 if (track_info
->codec_hid
>= 0)
1701 logf("Buffered codec: %d", afmt
);
1707 #endif /* HAVE_CODEC_BUFFERING */
1709 /* Load metadata for the next track (with bufopen). The rest of the track
1710 loading will be handled by audio_finish_load_track once the metadata has
1711 been actually loaded by the buffering thread.
1713 Each track is arranged in the buffer as follows:
1714 <id3|[cuesheet|][album art|][codec|]audio>
1716 The next will not be loaded until the previous succeeds if the buffer was
1717 full at the time. To put any metadata after audio would make those handles
1720 static int audio_load_track(void)
1722 if (in_progress_id3_hid
>= 0)
1724 /* There must be an info pointer if the in-progress id3 is even there */
1725 struct track_info
*info
= track_list_last(0);
1727 if (info
->id3_hid
== in_progress_id3_hid
)
1729 if (filling
== STATE_FILLING
)
1731 /* Haven't finished the metadata but the notification is
1732 anticipated to come soon */
1733 logf("%s(): in progress ok: %d". __func__
, info
->id3_hid
);
1734 return LOAD_TRACK_OK
;
1736 else if (filling
== STATE_FULL
)
1738 /* Buffer was full trying to complete the load after the
1739 metadata finished, so attempt to continue - older handles
1740 should have been cleared already */
1741 logf("%s(): finishing load: %d". __func__
, info
->id3_hid
);
1742 filling
= STATE_FILLING
;
1743 buffer_event_finished_callback(&info
->id3_hid
);
1744 return LOAD_TRACK_OK
;
1748 /* Some old, stray buffering message */
1749 logf("%s(): already in progress: %d". __func__
, info
->id3_hid
);
1750 return LOAD_TRACK_ERR_BUSY
;
1753 filling
= STATE_FILLING
;
1755 struct track_info
*info
= track_list_alloc_track();
1758 /* List is full so stop buffering tracks - however, attempt to obtain
1759 metadata as the unbuffered id3 */
1760 logf("No free tracks");
1761 filling
= STATE_FULL
;
1764 playlist_peek_offset
++;
1766 logf("Buffering track: s%u/c%u/e%u/p%d",
1767 track_list
.start
, track_list
.current
, track_list
.end
,
1768 playlist_peek_offset
);
1770 /* Get track name from current playlist read position */
1772 char name_buf
[MAX_PATH
+ 1];
1773 const char *trackname
;
1778 trackname
= playlist_peek(playlist_peek_offset
, name_buf
,
1784 /* Test for broken playlists by probing for the files */
1785 fd
= open(trackname
, O_RDONLY
);
1789 logf("Open failed");
1790 /* Skip invalid entry from playlist */
1791 playlist_skip_entry(NULL
, playlist_peek_offset
);
1793 /* Sync the playlist if it isn't finished */
1794 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
1800 /* No track - exhausted the playlist entries */
1801 logf("End-of-playlist");
1802 id3_write_locked(UNBUFFERED_ID3
, NULL
);
1804 if (filling
!= STATE_FULL
)
1805 track_list_unalloc_track(); /* Free this entry */
1807 playlist_peek_offset
--; /* Maintain at last index */
1809 /* We can end up here after the real last track signals its completion
1810 and miss the transition to STATE_FINISHED esp. if dropping the last
1811 songs of a playlist late in their load (2nd stage) */
1812 info
= track_list_last(0);
1814 if (info
&& buf_handle_remaining(info
->audio_hid
) == 0)
1815 filling_is_finished();
1817 filling
= STATE_END_OF_PLAYLIST
;
1819 return LOAD_TRACK_ERR_NO_MORE
;
1822 /* Successfully opened the file - get track metadata */
1823 if (filling
== STATE_FULL
||
1824 (info
->id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
)) < 0)
1826 /* Buffer or track list is full */
1827 struct mp3entry
*ub_id3
;
1829 playlist_peek_offset
--;
1831 /* Load the metadata for the first unbuffered track */
1832 ub_id3
= id3_get(UNBUFFERED_ID3
);
1834 get_metadata(ub_id3
, fd
, trackname
);
1837 if (filling
!= STATE_FULL
)
1839 track_list_unalloc_track();
1840 filling
= STATE_FULL
;
1843 logf("%s: buffer is full for now (%u tracks)", __func__
,
1844 track_list_count());
1848 /* Successful load initiation */
1849 info
->filesize
= filesize(fd
);
1850 in_progress_id3_hid
= info
->id3_hid
; /* Remember what's in-progress */
1854 return LOAD_TRACK_OK
;
1857 /* Second part of the track loading: We now have the metadata available, so we
1858 can load the codec, the album art and finally the audio data.
1859 This is called on the audio thread after the buffering thread calls the
1860 buffering_handle_finished_callback callback. */
1861 static int audio_finish_load_track(struct track_info
*info
)
1863 int trackstat
= LOAD_TRACK_OK
;
1865 if (info
->id3_hid
!= in_progress_id3_hid
)
1867 /* We must not be here if not! */
1868 logf("%s: wrong track %d/%d", __func__
, info
->id3_hid
,
1869 in_progress_id3_hid
);
1870 return LOAD_TRACK_ERR_BUSY
;
1873 /* The current track for decoding (there is always one if the list is
1875 struct track_info
*cur_info
= track_list_current(0);
1876 struct mp3entry
*track_id3
= valid_mp3entry(bufgetid3(info
->id3_hid
));
1880 /* This is an error condition. Track cannot be played without valid
1881 metadata; skip the track. */
1882 logf("No metadata");
1883 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1884 goto audio_finish_load_track_exit
;
1887 /* Try to load a cuesheet for the track */
1888 if (!audio_load_cuesheet(info
, track_id3
))
1890 /* No space for cuesheet on buffer, not an error */
1891 filling
= STATE_FULL
;
1892 goto audio_finish_load_track_exit
;
1895 #ifdef HAVE_ALBUMART
1896 /* Try to load album art for the track */
1897 if (!audio_load_albumart(info
, track_id3
))
1899 /* No space for album art on buffer, not an error */
1900 filling
= STATE_FULL
;
1901 goto audio_finish_load_track_exit
;
1905 /* All handles available to external routines are ready - audio and codec
1906 information is private */
1908 if (info
== track_list_user_current(0))
1910 /* Send only when the track handles could not all be opened ahead of
1911 time for the user's current track - otherwise everything is ready
1912 by the time PLAYBACK_EVENT_TRACK_CHANGE is sent */
1913 send_event(PLAYBACK_EVENT_CUR_TRACK_READY
, id3_get(PLAYING_ID3
));
1916 #ifdef HAVE_CODEC_BUFFERING
1917 /* Try to buffer a codec for the track */
1918 if (info
!= cur_info
&& !audio_buffer_codec(info
, track_id3
))
1920 if (info
->codec_hid
== ERR_BUFFER_FULL
)
1922 /* No space for codec on buffer, not an error */
1923 filling
= STATE_FULL
;
1924 logf("buffer is full for now (%s)", __func__
);
1928 /* This is an error condition, either no codec was found, or
1929 reading the codec file failed part way through, either way,
1931 logf("No codec for: %s", track_id3
->path
);
1932 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
1935 goto audio_finish_load_track_exit
;
1937 #endif /* HAVE_CODEC_BUFFERING */
1939 /** Finally, load the audio **/
1940 size_t file_offset
= 0;
1941 track_id3
->elapsed
= 0;
1943 if (track_id3
->offset
>= info
->filesize
)
1944 track_id3
->offset
= 0;
1946 logf("%s: set offset for %s to %lu\n", __func__
,
1947 id3
->title
, (unsigned long)offset
);
1949 /* Adjust for resume rewind so we know what to buffer - starting the codec
1950 calls it again, so we don't save it (and they shouldn't accumulate) */
1951 size_t offset
= resume_rewind_adjusted_offset(track_id3
);
1953 enum data_type audiotype
= rbcodec_format_is_atomic(track_id3
->codectype
) ?
1954 TYPE_ATOMIC_AUDIO
: TYPE_PACKET_AUDIO
;
1956 if (audiotype
== TYPE_ATOMIC_AUDIO
)
1957 logf("Loading atomic %d", track_id3
->codectype
);
1959 if (format_buffers_with_offset(track_id3
->codectype
))
1961 /* This format can begin buffering from any point */
1962 file_offset
= offset
;
1965 logf("load track: %s", track_id3
->path
);
1967 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1969 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1970 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1974 /* No offset given or it is very minimal - begin at the first frame
1975 according to the metadata */
1976 file_offset
= track_id3
->first_frame_offset
;
1979 int hid
= bufopen(track_id3
->path
, file_offset
, audiotype
, NULL
);
1983 info
->audio_hid
= hid
;
1985 if (info
== cur_info
)
1987 /* This is the current track to decode - should be started now */
1988 trackstat
= LOAD_TRACK_READY
;
1993 /* Buffer could be full but not properly so if this is the only
1995 if (hid
== ERR_BUFFER_FULL
&& audio_track_count() > 1)
1997 filling
= STATE_FULL
;
1998 logf("Buffer is full for now (%s)", __func__
);
2002 /* Nothing to play if no audio handle - skip this */
2003 logf("Could not add audio data handle");
2004 trackstat
= LOAD_TRACK_ERR_FINISH_FAILED
;
2008 audio_finish_load_track_exit
:
2009 if (trackstat
< LOAD_TRACK_OK
)
2011 playlist_skip_entry(NULL
, playlist_peek_offset
);
2012 track_info_close(info
);
2013 track_list_unalloc_track();
2015 if (playlist_peek(playlist_peek_offset
, NULL
, 0))
2018 playlist_peek_offset
--;
2021 if (filling
!= STATE_FULL
)
2023 /* Load next track - error or not */
2024 in_progress_id3_hid
= ERR_HANDLE_NOT_FOUND
;
2025 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
2026 audio_queue_post(Q_AUDIO_FILL_BUFFER
, 0);
2031 trackstat
= LOAD_TRACK_ERR_FINISH_FULL
;
2037 /* Start a new track load */
2038 static int audio_fill_file_buffer(void)
2040 if (play_status
== PLAY_STOPPED
)
2041 return LOAD_TRACK_ERR_FAILED
;
2043 trigger_cpu_boost();
2045 /* Must reset the buffer before use if trashed or voice only - voice
2046 file size shouldn't have changed so we can go straight from
2047 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
2048 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
2049 audio_reset_buffer(AUDIOBUF_STATE_INITIALIZED
);
2051 logf("Starting buffer fill");
2053 int trackstat
= audio_load_track();
2055 if (trackstat
>= LOAD_TRACK_OK
)
2057 if (track_list_current(0) == track_list_user_current(0))
2060 if (filling
== STATE_FULL
&& !track_list_user_current(1))
2062 /* There are no user tracks on the buffer after this therefore
2063 this is the next track */
2064 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3
));
2071 /* Discard unwanted tracks and start refill from after the specified playlist
2073 static int audio_reset_and_rebuffer(
2074 enum track_clear_action action
, int peek_offset
)
2076 logf("Forcing rebuffer: 0x%X, %d", flags
, peek_offset
);
2078 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2080 /* Remove unwanted tracks - caller must have ensured codec isn't using
2082 track_list_clear(action
);
2084 /* Refill at specified position (-1 starts at index offset 0) */
2085 playlist_peek_offset
= peek_offset
;
2087 /* Fill the buffer */
2088 return audio_fill_file_buffer();
2091 /* Handle buffering events
2092 (Q_AUDIO_BUFFERING) */
2093 static void audio_on_buffering(int event
)
2095 enum track_clear_action action
;
2098 if (track_list_empty())
2103 case BUFFER_EVENT_BUFFER_LOW
:
2104 if (filling
!= STATE_FULL
&& filling
!= STATE_END_OF_PLAYLIST
)
2105 return; /* Should be nothing left to fill */
2107 /* Clear old tracks and continue buffering where it left off */
2108 action
= TRACK_LIST_KEEP_NEW
;
2109 peek_offset
= playlist_peek_offset
;
2112 case BUFFER_EVENT_REBUFFER
:
2113 /* Remove all but the currently decoding track and redo buffering
2115 action
= TRACK_LIST_KEEP_CURRENT
;
2116 peek_offset
= (skip_pending
== TRACK_SKIP_AUTO
) ? 1 : 0;
2123 switch (skip_pending
)
2125 case TRACK_SKIP_NONE
:
2126 case TRACK_SKIP_AUTO
:
2127 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2128 audio_reset_and_rebuffer(action
, peek_offset
);
2131 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2132 /* Already finished */
2137 logf("Buffering call, inv. state: %d", (int)skip_pending
);
2141 /* Handle starting the next track load
2142 (Q_AUDIO_FILL_BUFFER) */
2143 static void audio_on_fill_buffer(void)
2145 audio_handle_track_load_status(audio_fill_file_buffer());
2148 /* Handle posted load track finish event
2149 (Q_AUDIO_FINISH_LOAD_TRACK) */
2150 static void audio_on_finish_load_track(int id3_hid
)
2152 struct track_info
*info
= track_list_last(0);
2154 if (!info
|| !buf_is_handle(id3_hid
))
2157 if (info
== track_list_user_current(1))
2159 /* Just loaded the metadata right after the current position */
2160 audio_update_and_announce_next_track(bufgetid3(info
->id3_hid
));
2163 if (audio_finish_load_track(info
) != LOAD_TRACK_READY
)
2164 return; /* Not current track */
2166 bool is_user_current
= info
== track_list_user_current(0);
2168 if (is_user_current
)
2171 buf_read_cuesheet(info
->cuesheet_hid
);
2174 if (audio_start_codec(automatic_skip
))
2176 if (is_user_current
)
2178 /* Be sure all tagtree info is synchronized; it will be needed for the
2179 track finish event - the sync will happen when finalizing a track
2181 bool was_valid
= valid_mp3entry(id3_get(PLAYING_ID3
));
2183 playing_id3_sync(info
, -1);
2187 /* Playing id3 hadn't been updated yet because no valid track
2188 was yet available - treat like the first track */
2189 audio_playlist_track_change();
2195 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2199 /* Called when handles other than metadata handles have finished buffering
2200 (Q_AUDIO_HANDLE_FINISHED) */
2201 static void audio_on_handle_finished(int hid
)
2203 /* Right now, only audio handles should end up calling this */
2204 if (filling
== STATE_END_OF_PLAYLIST
)
2206 struct track_info
*info
= track_list_last(0);
2208 /* Really we don't know which order the handles will actually complete
2209 to zero bytes remaining since another thread is doing it - be sure
2210 it's the right one */
2211 if (info
&& info
->audio_hid
== hid
)
2213 /* This was the last track in the playlist and we now have all the
2215 filling_is_finished();
2220 /* Called to make an outstanding track skip the current track and to send the
2221 transition events */
2222 static void audio_finalise_track_change(void)
2224 switch (skip_pending
)
2226 case TRACK_SKIP_NONE
: /* Manual skip */
2229 case TRACK_SKIP_AUTO
:
2230 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2232 int playlist_delta
= skip_pending
== TRACK_SKIP_AUTO
? 1 : 0;
2233 audio_playlist_track_finish();
2235 if (!playlist_peek(playlist_delta
, NULL
, 0))
2237 /* Track ended up rejected - push things ahead like the codec blew
2238 it (because it was never started and now we're here where it
2239 should have been decoding the next track by now) - next, a
2240 directory change or end of playback will most likely happen */
2241 skip_pending
= TRACK_SKIP_NONE
;
2242 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2246 if (!playlist_delta
)
2249 playlist_peek_offset
-= playlist_delta
;
2250 if (playlist_next(playlist_delta
) >= 0)
2252 /* What!? Disappear? Hopeless bleak despair */
2255 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2256 default: /* Invalid */
2257 filling
= STATE_ENDED
;
2258 audio_stop_playback();
2262 struct track_info
*info
= track_list_current(0);
2263 struct mp3entry
*track_id3
= NULL
;
2267 /* Update the current cuesheet if any and enabled */
2270 buf_read_cuesheet(info
->cuesheet_hid
);
2271 track_id3
= bufgetid3(info
->id3_hid
);
2274 id3_write(PLAYING_ID3
, track_id3
);
2276 /* The skip is technically over */
2277 skip_pending
= TRACK_SKIP_NONE
;
2279 /* Sync the next track information */
2280 info
= track_list_current(1);
2282 id3_write(NEXTTRACK_ID3
, info
? bufgetid3(info
->id3_hid
) :
2283 id3_get(UNBUFFERED_ID3
));
2287 audio_playlist_track_change();
2290 /* Actually begin a transition and take care of the codec change - may complete
2291 it now or ask pcmbuf for notification depending on the type */
2292 static void audio_begin_track_change(enum pcm_track_change_type type
,
2295 /* Even if the new track is bad, the old track must be finished off */
2296 pcmbuf_start_track_change(type
);
2298 bool auto_skip
= type
!= TRACK_CHANGE_MANUAL
;
2302 /* Manual track change happens now */
2303 audio_finalise_track_change();
2304 pcmbuf_sync_position_update();
2306 if (play_status
== PLAY_STOPPED
)
2307 return; /* Stopped us */
2310 if (trackstat
>= LOAD_TRACK_OK
)
2312 struct track_info
*info
= track_list_current(0);
2314 if (info
->audio_hid
< 0)
2317 /* Everything needed for the codec is ready - start it */
2318 if (audio_start_codec(auto_skip
))
2321 playing_id3_sync(info
, -1);
2325 trackstat
= LOAD_TRACK_ERR_START_CODEC
;
2328 audio_handle_track_load_status(trackstat
);
2331 /* Transition to end-of-playlist state and begin wait for PCM to finish */
2332 static void audio_monitor_end_of_playlist(void)
2334 skip_pending
= TRACK_SKIP_AUTO_END_PLAYLIST
;
2335 filling
= STATE_ENDING
;
2336 pcmbuf_start_track_change(TRACK_CHANGE_END_OF_DATA
);
2339 /* Codec has completed decoding the track
2340 (usually Q_AUDIO_CODEC_COMPLETE) */
2341 static void audio_on_codec_complete(int status
)
2343 logf("%s(%d)", __func__
, status
);
2345 if (play_status
== PLAY_STOPPED
)
2348 /* If it didn't notify us first, don't expect "seek complete" message
2349 since the codec can't post it now - do things like it would have
2351 audio_complete_codec_seek();
2353 if (play_status
== PLAY_PAUSED
|| skip_pending
!= TRACK_SKIP_NONE
)
2355 /* Old-hay on the ip-skay - codec has completed decoding
2357 Paused: We're not sounding it, so just remember that it happened
2358 and the resume will begin the transition
2360 Skipping: There was already a skip in progress, remember it and
2361 allow no further progress until the PCM from the previous
2364 codec_skip_pending
= true;
2365 codec_skip_status
= status
;
2369 codec_skip_pending
= false;
2371 int trackstat
= LOAD_TRACK_OK
;
2373 automatic_skip
= true;
2374 skip_pending
= TRACK_SKIP_AUTO
;
2376 /* Does this track have an entry allocated? */
2377 struct track_info
*info
= track_list_advance_current(1);
2379 if (!info
|| info
->audio_hid
< 0)
2381 bool end_of_playlist
= false;
2385 /* Track load is not complete - it might have stopped on a
2386 full buffer without reaching the audio handle or we just
2389 If this type is atomic and we couldn't get the audio,
2390 perhaps it would need to wrap to make the allocation and
2391 handles are in the way - to maximize the liklihood it can
2392 be allocated, clear all handles to reset the buffer and
2393 its indexes to 0 - for packet audio, this should not be an
2394 issue and a pointless full reload of all the track's
2395 metadata may be avoided */
2397 struct mp3entry
*track_id3
= bufgetid3(info
->id3_hid
);
2399 if (track_id3
&& !rbcodec_format_is_atomic(track_id3
->codectype
))
2401 /* Continue filling after this track */
2402 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT
, 1);
2403 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2406 /* else rebuffer at this track; status applies to the track we
2409 else if (!playlist_peek(1, NULL
, 0))
2411 /* Play sequence is complete - directory change or other playlist
2412 resequencing - the playlist must now be advanced in order to
2413 continue since a peek ahead to the next track is not possible */
2414 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2415 end_of_playlist
= playlist_next(1) < 0;
2418 if (!end_of_playlist
)
2420 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
,
2421 skip_pending
== TRACK_SKIP_AUTO
? 0 : -1);
2423 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2425 /* Failed to find anything after all - do playlist switchover
2427 skip_pending
= TRACK_SKIP_AUTO_NEW_PLAYLIST
;
2428 end_of_playlist
= playlist_next(1) < 0;
2432 if (end_of_playlist
)
2434 audio_monitor_end_of_playlist();
2439 audio_begin_track_change(TRACK_CHANGE_AUTO
, trackstat
);
2442 /* Called when codec completes seek operation
2443 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2444 static void audio_on_codec_seek_complete(void)
2446 logf("%s()", __func__
);
2447 audio_complete_codec_seek();
2451 /* Called when PCM track change has completed
2452 (Q_AUDIO_TRACK_CHANGED) */
2453 static void audio_on_track_changed(void)
2455 /* Finish whatever is pending so that the WPS is in sync */
2456 audio_finalise_track_change();
2458 if (codec_skip_pending
)
2460 /* Codec got ahead completing a short track - complete the
2461 codec's skip and begin the next */
2462 codec_skip_pending
= false;
2463 audio_on_codec_complete(codec_skip_status
);
2467 /* Begin playback from an idle state, transition to a new playlist or
2468 invalidate the buffer and resume (if playing).
2469 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2470 static void audio_start_playback(size_t offset
, unsigned int flags
)
2472 enum play_status old_status
= play_status
;
2474 if (flags
& AUDIO_START_NEWBUF
)
2476 /* Mark the buffer dirty - if not playing, it will be reset next
2478 if (buffer_state
== AUDIOBUF_STATE_INITIALIZED
)
2479 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
2482 if (old_status
!= PLAY_STOPPED
)
2484 logf("%s(%lu): skipping", __func__
, (unsigned long)offset
);
2486 halt_decoding_track(true);
2488 automatic_skip
= false;
2491 if (flags
& AUDIO_START_RESTART
)
2493 /* Clear out some stuff to resume the current track where it
2496 offset
= id3_get(PLAYING_ID3
)->offset
;
2497 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2501 /* This is more-or-less treated as manual track transition */
2502 /* Save resume information for current track */
2503 audio_playlist_track_finish();
2504 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2506 /* Indicate manual track change */
2507 pcmbuf_start_track_change(TRACK_CHANGE_MANUAL
);
2508 wipe_track_metadata(true);
2511 /* Set after track finish event in case skip was in progress */
2512 skip_pending
= TRACK_SKIP_NONE
;
2516 if (flags
& AUDIO_START_RESTART
)
2517 return; /* Must already be playing */
2519 /* Cold playback start from a stopped state */
2520 logf("%s(%lu): starting", __func__
, offset
);
2522 /* Set audio parameters */
2523 #if INPUT_SRC_CAPS != 0
2524 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
2525 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
2527 #ifndef PLATFORM_HAS_VOLUME_CHANGE
2528 sound_set_volume(global_settings
.volume
);
2530 /* Be sure channel is audible */
2531 pcmbuf_fade(false, true);
2533 /* Update our state */
2534 play_status
= PLAY_PLAYING
;
2537 /* Codec's position should be available as soon as it knows it */
2538 position_key
= pcmbuf_get_position_key();
2539 pcmbuf_sync_position_update();
2541 /* Start fill from beginning of playlist */
2542 playlist_peek_offset
= -1;
2543 buf_set_base_handle(-1);
2545 /* Officially playing */
2546 queue_reply(&audio_queue
, 1);
2548 /* Add these now - finish event for the first id3 will most likely be sent
2550 add_event(BUFFER_EVENT_REBUFFER
, false, buffer_event_rebuffer_callback
);
2551 add_event(BUFFER_EVENT_FINISHED
, false, buffer_event_finished_callback
);
2553 if (old_status
== PLAY_STOPPED
)
2555 /* Send coldstart event */
2556 send_event(PLAYBACK_EVENT_START_PLAYBACK
, NULL
);
2559 /* Fill the buffer */
2560 int trackstat
= audio_fill_file_buffer();
2562 if (trackstat
>= LOAD_TRACK_OK
)
2564 /* This is the currently playing track - get metadata, stat */
2565 playing_id3_sync(track_list_current(0), offset
);
2567 if (valid_mp3entry(id3_get(PLAYING_ID3
)))
2569 /* Only if actually changing tracks... */
2570 if (!(flags
& AUDIO_START_RESTART
))
2571 audio_playlist_track_change();
2576 /* Found nothing playable */
2577 audio_handle_track_load_status(trackstat
);
2581 /* Stop playback and enter an idle state
2582 (usually Q_AUDIO_STOP) */
2583 static void audio_stop_playback(void)
2585 logf("%s()", __func__
);
2587 if (play_status
== PLAY_STOPPED
)
2590 bool do_fade
= global_settings
.fade_on_stop
&& filling
!= STATE_ENDED
;
2592 pcmbuf_fade(do_fade
, false);
2594 /* Wait for fade-out */
2595 audio_wait_fade_complete();
2597 /* Stop the codec and unload it */
2598 halt_decoding_track(true);
2602 /* Save resume information - "filling" might have been set to
2603 "STATE_ENDED" by caller in order to facilitate end of playlist */
2604 audio_playlist_track_finish();
2606 skip_pending
= TRACK_SKIP_NONE
;
2607 automatic_skip
= false;
2609 /* Close all tracks and mark them NULL */
2610 remove_event(BUFFER_EVENT_REBUFFER
, buffer_event_rebuffer_callback
);
2611 remove_event(BUFFER_EVENT_FINISHED
, buffer_event_finished_callback
);
2612 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffer_event_buffer_low_callback
);
2614 track_list_clear(TRACK_LIST_CLEAR_ALL
);
2616 /* Update our state */
2618 play_status
= PLAY_STOPPED
;
2620 wipe_track_metadata(true);
2623 filling
= STATE_IDLE
;
2627 /* Pause the playback of the current track
2629 static void audio_on_pause(bool pause
)
2631 logf("%s(%s)", __func__
, pause
? "true" : "false");
2633 if (play_status
== PLAY_STOPPED
|| pause
== (play_status
== PLAY_PAUSED
))
2636 play_status
= pause
? PLAY_PAUSED
: PLAY_PLAYING
;
2638 if (!pause
&& codec_skip_pending
)
2640 /* Actually do the skip that is due - resets the status flag */
2641 audio_on_codec_complete(codec_skip_status
);
2644 bool do_fade
= global_settings
.fade_on_stop
;
2646 pcmbuf_fade(do_fade
, !pause
);
2648 if (!ff_rw_mode
&& !(do_fade
&& pause
))
2650 /* Not in ff/rw mode - can actually change the audio state now */
2651 pcmbuf_pause(pause
);
2655 /* Skip a certain number of tracks forwards or backwards
2657 static void audio_on_skip(void)
2661 /* Eat the delta to keep it synced, even if not playing */
2662 int toskip
= skip_offset
;
2665 logf("%s(): %d", __func__
, toskip
);
2669 if (play_status
== PLAY_STOPPED
)
2672 /* Force codec to abort this track */
2673 halt_decoding_track(true);
2675 /* Kill the ff/rw halt */
2679 automatic_skip
= false;
2681 /* If there was an auto skip in progress, there will be residual
2682 advancement of the playlist and/or track list so compensation will be
2683 required in order to end up in the right spot */
2684 int track_list_delta
= toskip
;
2685 int playlist_delta
= toskip
;
2687 if (skip_pending
!= TRACK_SKIP_NONE
)
2689 if (skip_pending
!= TRACK_SKIP_AUTO_END_PLAYLIST
)
2692 if (skip_pending
== TRACK_SKIP_AUTO_NEW_PLAYLIST
)
2696 audio_playlist_track_finish();
2697 skip_pending
= TRACK_SKIP_NONE
;
2699 /* Update the playlist current track now */
2701 while ((pl_retval
= playlist_next(playlist_delta
)) < 0)
2705 /* Some variety of fatal error while updating playlist */
2706 filling
= STATE_ENDED
;
2707 audio_stop_playback();
2711 /* Manual skip out of range (because the playlist wasn't updated
2712 yet by us and so the check in audio_skip returned 'ok') - bring
2714 int d
= toskip
< 0 ? 1 : -1;
2716 while (!playlist_check(playlist_delta
))
2718 if (playlist_delta
== d
)
2720 /* Had to move the opposite direction to correct, which is
2721 wrong - this is the end */
2722 filling
= STATE_ENDED
;
2723 audio_stop_playback();
2727 playlist_delta
+= d
;
2728 track_list_delta
+= d
;
2732 /* Adjust things by how much the playlist was manually moved */
2733 playlist_peek_offset
-= playlist_delta
;
2735 struct track_info
*info
= track_list_advance_current(track_list_delta
);
2736 int trackstat
= LOAD_TRACK_OK
;
2738 if (!info
|| info
->audio_hid
< 0)
2740 /* We don't know the next track thus we know we don't have it */
2741 trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2744 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2747 /* Skip to the next/previous directory
2748 (Q_AUDIO_DIR_SKIP) */
2749 static void audio_on_dir_skip(int direction
)
2751 logf("%s(%d)", __func__
, direction
);
2757 if (play_status
== PLAY_STOPPED
)
2760 /* Force codec to abort this track */
2761 halt_decoding_track(true);
2763 /* Kill the ff/rw halt */
2767 automatic_skip
= false;
2769 audio_playlist_track_finish();
2771 /* Unless automatic and gapless, skips do not pend */
2772 skip_pending
= TRACK_SKIP_NONE
;
2774 /* Regardless of the return value we need to rebuffer. If it fails the old
2775 playlist will resume, else the next dir will start playing. */
2776 playlist_next_dir(direction
);
2778 wipe_track_metadata(false);
2780 int trackstat
= audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1);
2782 if (trackstat
== LOAD_TRACK_ERR_NO_MORE
)
2784 /* The day the music died - finish-off whatever is playing and call it
2786 audio_monitor_end_of_playlist();
2790 audio_begin_track_change(TRACK_CHANGE_MANUAL
, trackstat
);
2793 /* Enter seek mode in order to start a seek
2794 (Q_AUDIO_PRE_FF_REWIND) */
2795 static void audio_on_pre_ff_rewind(void)
2797 logf("%s()", __func__
);
2799 if (play_status
== PLAY_STOPPED
|| ff_rw_mode
)
2804 audio_wait_fade_complete();
2806 if (play_status
== PLAY_PAUSED
)
2812 /* Seek the playback of the current track to the specified time
2813 (Q_AUDIO_FF_REWIND) */
2814 static void audio_on_ff_rewind(long time
)
2816 logf("%s(%ld)", __func__
, time
);
2818 if (play_status
== PLAY_STOPPED
)
2821 enum track_skip_type pending
= skip_pending
;
2825 case TRACK_SKIP_NONE
: /* The usual case */
2826 case TRACK_SKIP_AUTO
: /* Have to back it out (fun!) */
2827 case TRACK_SKIP_AUTO_END_PLAYLIST
: /* Still have the last codec used */
2829 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
2830 struct mp3entry
*ci_id3
= id3_get(CODEC_ID3
);
2832 automatic_skip
= false;
2834 /* Send event before clobbering the time */
2835 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2836 then skipping back to this track resumes properly. Something else
2837 should be sent. We're not _really_ finishing the track are we? */
2839 send_event(PLAYBACK_EVENT_TRACK_FINISH
, id3
);
2841 id3
->elapsed
= time
;
2842 queue_reply(&audio_queue
, 1);
2844 bool haltres
= halt_decoding_track(pending
== TRACK_SKIP_AUTO
);
2846 /* Need this set in case ff/rw mode + error but _after_ the codec
2847 halt that will reset it */
2848 codec_seeking
= true;
2850 /* If in transition, key will have changed - sync to it */
2851 position_key
= pcmbuf_get_position_key();
2853 if (pending
== TRACK_SKIP_AUTO
)
2855 if (!track_list_advance_current(-1))
2857 /* Not in list - must rebuffer at the current playlist index */
2858 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL
, -1)
2861 /* Codec is stopped */
2867 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
2868 rebuffer is needed */
2869 skip_pending
= TRACK_SKIP_NONE
;
2870 struct track_info
*cur_info
= track_list_current(0);
2872 /* Track must complete the loading _now_ since a codec and audio
2873 handle are needed in order to do the seek */
2874 if (cur_info
->audio_hid
< 0 &&
2875 audio_finish_load_track(cur_info
) != LOAD_TRACK_READY
)
2877 /* Call above should push any load sequence - no need for
2878 halt_decoding_track here if no skip was pending here because
2879 there would not be a codec started if no audio handle was yet
2884 if (pending
== TRACK_SKIP_AUTO
)
2886 if (!bufreadid3(cur_info
->id3_hid
, ci_id3
) ||
2887 !audio_init_codec(cur_info
, ci_id3
))
2889 /* We should have still been able to get it - skip it and move
2890 onto the next one - like it or not this track is broken */
2894 /* Set the codec API to the correct metadata and track info */
2895 ci
.audio_hid
= cur_info
->audio_hid
;
2896 ci
.filesize
= cur_info
->filesize
;
2897 buf_set_base_handle(cur_info
->audio_hid
);
2902 /* If codec must be (re)started, reset the offset */
2910 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2912 /* We cannot do this because the playlist must be reversed by one
2913 and it doesn't always return the same song when going backwards
2914 across boundaries as forwards (either because of randomization
2915 or inconsistency in deciding what the previous track should be),
2916 therefore the whole operation would often end up as nonsense -
2917 lock out seeking for a couple seconds */
2919 /* Sure as heck cancel seek mode too! */
2920 audio_ff_rewind_end();
2925 /* Won't see this */
2929 if (play_status
== PLAY_STOPPED
)
2931 /* Playback ended because of an error completing a track load */
2935 /* Always fake it as a codec start error which will handle mode
2936 cancellations and skip to the next track */
2937 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC
);
2940 /* Invalidates all but currently playing track
2942 static void audio_on_audio_flush(void)
2944 logf("%s", __func__
);
2946 if (track_list_empty())
2947 return; /* Nothing to flush out */
2949 switch (skip_pending
)
2951 case TRACK_SKIP_NONE
:
2952 case TRACK_SKIP_AUTO_END_PLAYLIST
:
2953 /* Remove all but the currently playing track from the list and
2954 refill after that */
2955 track_list_clear(TRACK_LIST_KEEP_CURRENT
);
2956 playlist_peek_offset
= 0;
2957 id3_write_locked(UNBUFFERED_ID3
, NULL
);
2958 audio_update_and_announce_next_track(NULL
);
2960 /* Ignore return since it's about the next track, not this one */
2961 audio_fill_file_buffer();
2963 if (skip_pending
== TRACK_SKIP_NONE
)
2966 /* There's now a track after this one now - convert to auto skip -
2967 no skip should pend right now because multiple flush messages can
2968 be fired which would cause a restart in the below cases */
2969 skip_pending
= TRACK_SKIP_NONE
;
2970 audio_clear_track_notifications();
2971 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, CODEC_OK
);
2974 case TRACK_SKIP_AUTO
:
2975 case TRACK_SKIP_AUTO_NEW_PLAYLIST
:
2976 /* Precisely removing what it already decoded for the next track is
2977 not possible so a restart is required in order to continue the
2978 currently playing track without the now invalid future track
2980 audio_start_playback(0, AUDIO_START_RESTART
);
2983 default: /* Nothing else is a state */
2988 #ifdef AUDIO_HAVE_RECORDING
2989 /* Load the requested encoder type
2990 (Q_AUDIO_LOAD_ENCODER) */
2991 static void audio_on_load_encoder(int afmt
)
2995 if (play_status
!= PLAY_STOPPED
)
2996 audio_stop_playback(); /* Can't load both types at once */
2998 codec_unload(); /* Encoder still loaded, stop and unload it */
3000 if (afmt
!= AFMT_UNKNOWN
)
3002 res
= codec_load(-1, afmt
| CODEC_TYPE_ENCODER
);
3004 codec_go(); /* These are run immediately */
3007 queue_reply(&audio_queue
, res
);
3009 #endif /* AUDIO_HAVE_RECORDING */
3011 static void audio_thread(void)
3013 struct queue_event ev
;
3023 case STATE_END_OF_PLAYLIST
:
3024 if (buf_get_watermark() == 0)
3026 /* End of buffering for now, let's calculate the watermark,
3027 register for a low buffer event and unboost */
3028 audio_update_filebuf_watermark(0);
3029 add_event(BUFFER_EVENT_BUFFER_LOW
, true,
3030 buffer_event_buffer_low_callback
);
3033 case STATE_FINISHED
:
3034 /* All data was buffered */
3039 if (audio_pcmbuf_track_change_scan())
3041 /* Transfer notification to audio queue event */
3042 ev
.id
= Q_AUDIO_TRACK_CHANGED
;
3047 /* If doing auto skip, poll pcmbuf track notifications a bit
3048 faster to promply detect the transition */
3049 queue_wait_w_tmo(&audio_queue
, &ev
,
3050 skip_pending
== TRACK_SKIP_NONE
?
3057 queue_wait(&audio_queue
, &ev
);
3059 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3062 #ifdef AUDIO_HAVE_RECORDING
3063 /* Must monitor the encoder message for recording so it can remove
3064 it if we process the insertion before it does. It cannot simply
3065 be removed from under recording however. */
3066 case Q_AUDIO_LOAD_ENCODER
:
3069 case SYS_USB_DISCONNECTED
:
3070 filling
= STATE_IDLE
;
3074 if (filling
== STATE_USB
)
3077 #endif /* CONFIG_PLATFORM */
3082 /** Codec and track change messages **/
3083 case Q_AUDIO_CODEC_COMPLETE
:
3084 /* Codec is done processing track and has gone idle */
3085 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev
.data
);
3086 audio_on_codec_complete(ev
.data
);
3089 case Q_AUDIO_CODEC_SEEK_COMPLETE
:
3090 /* Codec is done seeking */
3091 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
3092 audio_on_codec_seek_complete();
3095 case Q_AUDIO_TRACK_CHANGED
:
3096 /* PCM track change done */
3097 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3098 audio_on_track_changed();
3101 /** Control messages **/
3103 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3104 audio_start_playback(ev
.data
, 0);
3108 LOGFQUEUE("audio < Q_AUDIO_STOP");
3109 audio_stop_playback();
3111 queue_clear(&audio_queue
);
3115 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3116 audio_on_pause(ev
.data
);
3120 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3124 case Q_AUDIO_DIR_SKIP
:
3125 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3126 audio_on_dir_skip(ev
.data
);
3129 case Q_AUDIO_PRE_FF_REWIND
:
3130 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3131 audio_on_pre_ff_rewind();
3134 case Q_AUDIO_FF_REWIND
:
3135 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3136 audio_on_ff_rewind(ev
.data
);
3140 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev
.data
);
3141 audio_on_audio_flush();
3144 /** Buffering messages **/
3145 case Q_AUDIO_BUFFERING
:
3146 /* some buffering event */
3147 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev
.data
);
3148 audio_on_buffering(ev
.data
);
3151 case Q_AUDIO_FILL_BUFFER
:
3152 /* continue buffering next track */
3153 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3154 audio_on_fill_buffer();
3157 case Q_AUDIO_FINISH_LOAD_TRACK
:
3158 /* metadata is buffered */
3159 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
3160 audio_on_finish_load_track(ev
.data
);
3163 case Q_AUDIO_HANDLE_FINISHED
:
3164 /* some other type is buffered */
3165 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
3166 audio_on_handle_finished(ev
.data
);
3169 /** Miscellaneous messages **/
3170 case Q_AUDIO_REMAKE_AUDIO_BUFFER
:
3171 /* buffer needs to be reinitialized */
3172 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
3173 audio_start_playback(0, AUDIO_START_RESTART
| AUDIO_START_NEWBUF
);
3176 #ifdef HAVE_DISK_STORAGE
3177 case Q_AUDIO_UPDATE_WATERMARK
:
3178 /* buffering watermark needs updating */
3179 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev
.data
);
3180 audio_update_filebuf_watermark(ev
.data
);
3182 #endif /* HAVE_DISK_STORAGE */
3184 #ifdef AUDIO_HAVE_RECORDING
3185 case Q_AUDIO_LOAD_ENCODER
:
3186 /* load an encoder for recording */
3187 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev
.data
);
3188 audio_on_load_encoder(ev
.data
);
3190 #endif /* AUDIO_HAVE_RECORDING */
3192 case SYS_USB_CONNECTED
:
3193 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3194 audio_stop_playback();
3195 #ifdef PLAYBACK_VOICE
3198 filling
= STATE_USB
;
3199 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3203 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3207 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3214 /* --- Buffering callbacks --- */
3216 /* Called when fullness is below the watermark level */
3217 static void buffer_event_buffer_low_callback(void *data
)
3219 logf("low buffer callback");
3220 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
3221 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_BUFFER_LOW
);
3225 /* Called when handles must be discarded in order to buffer new data */
3226 static void buffer_event_rebuffer_callback(void *data
)
3228 logf("rebuffer callback");
3229 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3230 audio_queue_post(Q_AUDIO_BUFFERING
, BUFFER_EVENT_REBUFFER
);
3234 /* A handle has completed buffering and all required data is available */
3235 static void buffer_event_finished_callback(void *data
)
3237 int hid
= *(const int *)data
;
3238 const enum data_type htype
= buf_handle_data_type(hid
);
3240 logf("handle %d finished buffering (type:%u)", hid
, (unsigned)htype
);
3242 /* Limit queue traffic */
3246 /* The metadata handle for the last loaded track has been buffered.
3247 We can ask the audio thread to load the rest of the track's data. */
3248 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid
);
3249 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK
, hid
);
3252 case TYPE_PACKET_AUDIO
:
3253 /* Strip any useless trailing tags that are left. */
3256 case TYPE_ATOMIC_AUDIO
:
3257 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid
);
3258 audio_queue_post(Q_AUDIO_HANDLE_FINISHED
, hid
);
3262 /* Don't care to know about these */
3268 /** -- Codec callbacks -- **/
3270 /* Update elapsed time for next PCM insert */
3271 void audio_codec_update_elapsed(unsigned long elapsed
)
3273 #ifdef AB_REPEAT_ENABLE
3274 ab_position_report(elapsed
);
3276 /* Save in codec's id3 where it is used at next pcm insert */
3277 id3_get(CODEC_ID3
)->elapsed
= elapsed
;
3280 /* Update offset for next PCM insert */
3281 void audio_codec_update_offset(size_t offset
)
3283 /* Save in codec's id3 where it is used at next pcm insert */
3284 id3_get(CODEC_ID3
)->offset
= offset
;
3287 /* Codec has finished running */
3288 void audio_codec_complete(int status
)
3290 #ifdef AB_REPEAT_ENABLE
3291 if (status
>= CODEC_OK
)
3293 /* Normal automatic skip */
3294 ab_end_of_track_report();
3298 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_COMPLETE: %d", status
);
3299 audio_queue_post(Q_AUDIO_CODEC_COMPLETE
, status
);
3302 /* Codec has finished seeking */
3303 void audio_codec_seek_complete(void)
3305 LOGFQUEUE("codec > audio Q_AUDIO_CODEC_SEEK_COMPLETE");
3306 audio_queue_post(Q_AUDIO_CODEC_SEEK_COMPLETE
, 0);
3310 /** --- Pcmbuf callbacks --- **/
3312 /* Update the elapsed and offset from the information cached during the
3313 PCM buffer insert */
3314 void audio_pcmbuf_position_callback(unsigned long elapsed
, off_t offset
,
3317 if (key
== position_key
)
3319 struct mp3entry
*id3
= id3_get(PLAYING_ID3
);
3320 id3
->elapsed
= elapsed
;
3321 id3
->offset
= offset
;
3325 /* Synchronize position info to the codec's */
3326 void audio_pcmbuf_sync_position(void)
3328 audio_pcmbuf_position_callback(ci
.id3
->elapsed
, ci
.id3
->offset
,
3329 pcmbuf_get_position_key());
3332 /* Post message from pcmbuf that the end of the previous track has just
3334 void audio_pcmbuf_track_change(bool pcmbuf
)
3338 /* Notify of the change in special-purpose semaphore object */
3339 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3340 audio_pcmbuf_track_change_post();
3344 /* Safe to post directly to the queue */
3345 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3346 audio_queue_post(Q_AUDIO_TRACK_CHANGED
, 0);
3350 /* May pcmbuf start PCM playback when the buffer is full enough? */
3351 bool audio_pcmbuf_may_play(void)
3353 return play_status
== PLAY_PLAYING
&& !ff_rw_mode
;
3357 /** -- External interfaces -- **/
3359 /* Return the playback and recording status */
3360 int audio_status(void)
3362 unsigned int ret
= play_status
;
3364 #ifdef AUDIO_HAVE_RECORDING
3365 /* Do this here for constitency with mpeg.c version */
3366 ret
|= pcm_rec_status();
3372 /* Clear all accumulated audio errors for playback and recording */
3373 void audio_error_clear(void)
3375 #ifdef AUDIO_HAVE_RECORDING
3376 pcm_rec_error_clear();
3380 /* Get a copy of the id3 data for the for current track + offset + skip delta */
3381 bool audio_peek_track(struct mp3entry
*id3
, int offset
)
3383 bool retval
= false;
3387 if (play_status
!= PLAY_STOPPED
)
3389 id3
->path
[0] = '\0'; /* Null path means it should be filled now */
3390 retval
= audio_get_track_metadata(offset
+ skip_offset
, id3
) &&
3391 id3
->path
[0] != '\0';
3399 /* Return the mp3entry for the currently playing track */
3400 struct mp3entry
* audio_current_track(void)
3402 struct mp3entry
*id3
;
3406 #ifdef AUDIO_FAST_SKIP_PREVIEW
3407 if (skip_offset
!= 0)
3409 /* This is a peekahead */
3410 id3
= id3_get(PLAYING_PEEK_ID3
);
3411 audio_peek_track(id3
, 0);
3417 id3
= id3_get(PLAYING_ID3
);
3418 audio_get_track_metadata(0, id3
);
3426 /* Obtains the mp3entry for the next track from the current */
3427 struct mp3entry
* audio_next_track(void)
3429 struct mp3entry
*id3
= id3_get(NEXTTRACK_ID3
);
3433 #ifdef AUDIO_FAST_SKIP_PREVIEW
3434 if (skip_offset
!= 0)
3436 /* This is a peekahead */
3437 if (!audio_peek_track(id3
, 1))
3444 if (!audio_get_track_metadata(1, id3
))
3453 /* Start playback at the specified offset */
3454 void audio_play(long offset
)
3458 #ifdef PLAYBACK_VOICE
3459 /* Truncate any existing voice output so we don't have spelling
3460 * etc. over the first part of the played track */
3461 talk_force_shutup();
3464 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
3465 audio_queue_send(Q_AUDIO_PLAY
, offset
);
3468 /* Stop playback if playing */
3469 void audio_stop(void)
3471 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3472 audio_queue_send(Q_AUDIO_STOP
, 0);
3475 /* Pause playback if playing */
3476 void audio_pause(void)
3478 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3479 audio_queue_send(Q_AUDIO_PAUSE
, true);
3482 /* This sends a stop message and the audio thread will dump all its
3483 subsequent messages */
3484 void audio_hard_stop(void)
3487 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3488 audio_queue_send(Q_AUDIO_STOP
, 1);
3489 #ifdef PLAYBACK_VOICE
3492 if (audiobuf_handle
> 0)
3493 audiobuf_handle
= core_free(audiobuf_handle
);
3496 /* Resume playback if paused */
3497 void audio_resume(void)
3499 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
3500 audio_queue_send(Q_AUDIO_PAUSE
, false);
3503 /* Skip the specified number of tracks forward or backward from the current */
3504 void audio_skip(int offset
)
3508 /* If offset has to be backed-out to stay in range, no skip is done */
3509 int accum
= skip_offset
+ offset
;
3511 while (offset
!= 0 && !playlist_check(accum
))
3513 offset
+= offset
< 0 ? 1 : -1;
3514 accum
= skip_offset
+ offset
;
3519 /* Accumulate net manual skip count since the audio thread last
3521 skip_offset
= accum
;
3523 system_sound_play(SOUND_TRACK_SKIP
);
3525 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset
);
3527 #ifdef AUDIO_FAST_SKIP_PREVIEW
3528 /* Do this before posting so that the audio thread can correct us
3529 when things settle down - additionally, if audio gets a message
3530 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3531 handler a skip event with the correct info but doesn't skip */
3532 send_event(PLAYBACK_EVENT_TRACK_SKIP
, NULL
);
3533 #endif /* AUDIO_FAST_SKIP_PREVIEW */
3535 /* Playback only needs the final state even if more than one is
3536 processed because it wasn't removed in time */
3537 queue_remove_from_head(&audio_queue
, Q_AUDIO_SKIP
);
3538 audio_queue_post(Q_AUDIO_SKIP
, 0);
3542 /* No more tracks */
3543 system_sound_play(SOUND_TRACK_NO_MORE
);
3549 /* Skip one track forward from the current */
3550 void audio_next(void)
3555 /* Skip one track backward from the current */
3556 void audio_prev(void)
3561 /* Move one directory forward */
3562 void audio_next_dir(void)
3564 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3565 audio_queue_post(Q_AUDIO_DIR_SKIP
, 1);
3568 /* Move one directory backward */
3569 void audio_prev_dir(void)
3571 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3572 audio_queue_post(Q_AUDIO_DIR_SKIP
, -1);
3575 /* Pause playback in order to start a seek that flushes the old audio */
3576 void audio_pre_ff_rewind(void)
3578 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3579 audio_queue_post(Q_AUDIO_PRE_FF_REWIND
, 0);
3582 /* Seek to the new time in the current track */
3583 void audio_ff_rewind(long time
)
3585 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3586 audio_queue_post(Q_AUDIO_FF_REWIND
, time
);
3589 /* Clear all but the currently playing track then rebuffer */
3590 void audio_flush_and_reload_tracks(void)
3592 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3593 audio_queue_post(Q_AUDIO_FLUSH
, 0);
3596 /* Return the pointer to the main audio buffer, optionally preserving
3598 unsigned char * audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
3602 if (audio_is_initialized
)
3606 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
3608 if (buffer_size
== NULL
)
3610 /* Special case for talk_init to use since it already knows it's
3612 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3616 /* make sure buffer is freed and re-allocated to simplify code below
3617 * (audio_hard_stop() likely has done that already) */
3618 if (audiobuf_handle
> 0)
3619 audiobuf_handle
= core_free(audiobuf_handle
);
3621 audiobuf_handle
= core_alloc_maximum("audiobuf", &filebuflen
, &ops
);
3622 buf
= core_get_data(audiobuf_handle
);
3624 if (buffer_state
== AUDIOBUF_STATE_INITIALIZED
)
3625 buffering_reset(NULL
, 0); /* mark buffer invalid */
3627 if (talk_buf
|| !talk_voice_required())
3629 logf("get buffer: talk, audio");
3630 /* Ok to use everything from audiobuf - voice is loaded,
3631 the talk buffer is not needed because voice isn't being used, or
3632 could be AUDIOBUF_STATE_TRASHED already. If state is
3633 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't
3634 written without the caller knowing what's going on. Changing certain
3635 settings may move it to a worse condition but the memory in use by
3636 something else will remain undisturbed.
3638 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
3640 talk_buffer_steal();
3641 buffer_state
= AUDIOBUF_STATE_TRASHED
;
3646 logf("get buffer: audio");
3647 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3648 still AUDIOBUF_STATE_INITIALIZED */
3649 size_t talkbuf_size
= talkbuf_init(buf
);
3650 buf
+= talkbuf_size
; /* Skip talk buffer */
3651 filebuflen
-= talkbuf_size
;
3652 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
3655 *buffer_size
= filebuflen
;
3659 #ifdef HAVE_RECORDING
3660 /* Stop audio, voice and obtain all available buffer space */
3661 unsigned char * audio_get_recording_buffer(size_t *buffer_size
)
3664 return audio_get_buffer(true, buffer_size
);
3666 #endif /* HAVE_RECORDING */
3668 /* Restore audio buffer to a particular state (promoting status) */
3669 bool audio_restore_playback(int type
)
3673 case AUDIO_WANT_PLAYBACK
:
3674 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
3675 audio_reset_buffer(AUDIOBUF_STATE_INITIALIZED
);
3677 case AUDIO_WANT_VOICE
:
3678 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
3679 audio_reset_buffer(AUDIOBUF_STATE_VOICED_ONLY
);
3687 /** --- Miscellaneous public interfaces --- **/
3689 #ifdef HAVE_ALBUMART
3690 /* Return which album art handle is current for the user in the given slot */
3691 int playback_current_aa_hid(int slot
)
3693 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3695 struct track_info
*info
= track_list_user_current(skip_offset
);
3697 if (!info
&& abs(skip_offset
) <= 1)
3699 /* Give the actual position a go */
3700 info
= track_list_user_current(0);
3704 return info
->aa_hid
[slot
];
3707 return ERR_HANDLE_NOT_FOUND
;
3710 /* Find an album art slot that doesn't match the dimensions of another that
3711 is already claimed - increment the use count if it is */
3712 int playback_claim_aa_slot(struct dim
*dim
)
3716 /* First try to find a slot already having the size to reuse it since we
3717 don't want albumart of the same size buffered multiple times */
3720 struct albumart_slot
*slot
= &albumart_slots
[i
];
3722 if (slot
->dim
.width
== dim
->width
&&
3723 slot
->dim
.height
== dim
->height
)
3730 /* Size is new, find a free slot */
3733 if (!albumart_slots
[i
].used
)
3735 albumart_slots
[i
].used
++;
3736 albumart_slots
[i
].dim
= *dim
;
3741 /* Sorry, no free slot */
3745 /* Invalidate the albumart_slot - decrement the use count if > 0 */
3746 void playback_release_aa_slot(int slot
)
3748 if ((unsigned)slot
< MAX_MULTIPLE_AA
)
3750 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
3752 if (aa_slot
->used
> 0)
3756 #endif /* HAVE_ALBUMART */
3759 #ifdef HAVE_RECORDING
3760 /* Load an encoder and run it */
3761 bool audio_load_encoder(int afmt
)
3763 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3764 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
3765 return audio_queue_send(Q_AUDIO_LOAD_ENCODER
, afmt
) != 0;
3772 /* Stop an encoder and unload it */
3773 void audio_remove_encoder(void)
3775 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
3776 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3777 audio_queue_send(Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
3780 #endif /* HAVE_RECORDING */
3782 /* Is an automatic skip in progress? If called outside transition callbacks,
3783 indicates the last skip type at the time it was processed and isn't very
3785 bool audio_automatic_skip(void)
3787 return automatic_skip
;
3790 /* Would normally calculate byte offset from an elapsed time but is not
3792 int audio_get_file_pos(void)
3797 /* Return the elapsed time of the track previous to the current */
3798 unsigned long audio_prev_elapsed(void)
3800 return prev_track_elapsed
;
3803 /* Return total file buffer length after accounting for the talk buf */
3804 size_t audio_get_filebuflen(void)
3806 return buf_length();
3809 /* How many tracks exist on the buffer - full or partial */
3810 int audio_track_count(void)
3811 __attribute__((alias("track_list_count")));
3813 /* Return total ringbuffer space occupied - ridx to widx */
3814 long audio_filebufused(void)
3820 /** -- Settings -- **/
3822 /* Enable or disable cuesheet support and allocate/don't allocate the
3823 extra associated resources */
3824 void audio_set_cuesheet(int enable
)
3826 if (play_status
== PLAY_STOPPED
|| !enable
!= !get_current_cuesheet())
3828 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3829 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3833 #ifdef HAVE_DISK_STORAGE
3834 /* Set the audio antiskip buffer margin by index */
3835 void audio_set_buffer_margin(int setting
)
3837 static const unsigned short lookup
[] =
3838 { 5, 15, 30, 60, 120, 180, 300, 600 };
3840 if ((unsigned)setting
>= ARRAYLEN(lookup
))
3843 logf("buffer margin: %u", (unsigned)lookup
[setting
]);
3845 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
3846 (unsigned)lookup
[setting
]);
3847 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK
, lookup
[setting
]);
3849 #endif /* HAVE_DISK_STORAGE */
3851 #ifdef HAVE_CROSSFADE
3852 /* Take necessary steps to enable or disable the crossfade setting */
3853 void audio_set_crossfade(int enable
)
3855 /* Tell it the next setting to use */
3856 pcmbuf_request_crossfade_enable(enable
);
3858 /* Return if size hasn't changed or this is too early to determine
3859 which in the second case there's no way we could be playing
3861 if (!pcmbuf_is_same_size())
3863 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3864 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER
, 0);
3867 #endif /* HAVE_CROSSFADE */
3870 /** -- Startup -- **/
3872 /* Initialize the audio system - called from init() in main.c */
3873 void audio_init(void)
3875 /* Can never do this twice */
3876 if (audio_is_initialized
)
3878 logf("audio: already initialized");
3882 logf("audio: initializing");
3884 /* Initialize queues before giving control elsewhere in case it likes
3885 to send messages. Thread creation will be delayed however so nothing
3886 starts running until ready if something yields such as talk_init. */
3887 queue_init(&audio_queue
, true);
3889 mutex_init(&id3_mutex
);
3893 codec_thread_init();
3895 /* This thread does buffer, so match its priority */
3896 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
3897 sizeof(audio_stack
), 0, audio_thread_name
3898 IF_PRIO(, MIN(PRIORITY_BUFFERING
, PRIORITY_USER_INTERFACE
))
3901 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
3904 /* Initialize the track buffering system */
3908 #ifdef HAVE_CROSSFADE
3909 /* Set crossfade setting for next buffer init which should be about... */
3910 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
3913 /* ...now...audio_reset_buffer must know the size of voicefile buffer so
3914 init talk first which will init the buffers */
3917 /* Probably safe to say */
3918 audio_is_initialized
= true;
3920 sound_settings_apply();
3921 #ifdef HAVE_DISK_STORAGE
3922 audio_set_buffer_margin(global_settings
.buffer_margin
);