summaryrefslogtreecommitdiff
path: root/apps/playback.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-04-27 03:08:23 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-04-27 03:08:23 +0000
commitc537d5958e8b421ac4f9bef6c8b9e7425a6cf167 (patch)
tree7ed36518fb6524da7bbd913ba7619b85b5d15d23 /apps/playback.c
parentdcf0f8de4a37ff1d2ea510aef75fa67977a8bdcc (diff)
downloadrockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.tar.gz
rockbox-c537d5958e8b421ac4f9bef6c8b9e7425a6cf167.zip
Commit FS#12069 - Playback rework - first stages. Gives as thorough as possible a treatment of codec management, track change and metadata logic as possible while maintaining fairly narrow focus and not rewriting everything all at once. Please see the rockbox-dev mail archive on 2011-04-25 (Playback engine rework) for a more thorough manifest of what was addressed. Plugins and codecs become incompatible.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29785 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r--apps/playback.c4590
1 files changed, 2981 insertions, 1609 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 632fd05d3d..a369d15715 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -9,6 +9,7 @@
9 * 9 *
10 * Copyright (C) 2005-2007 Miika Pekkarinen 10 * Copyright (C) 2005-2007 Miika Pekkarinen
11 * Copyright (C) 2007-2008 Nicolas Pennequin 11 * Copyright (C) 2007-2008 Nicolas Pennequin
12 * Copyright (C) 2011 Michael Sevakis
12 * 13 *
13 * This program is free software; you can redistribute it and/or 14 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License 15 * modify it under the terms of the GNU General Public License
@@ -19,53 +20,61 @@
19 * KIND, either express or implied. 20 * KIND, either express or implied.
20 * 21 *
21 ****************************************************************************/ 22 ****************************************************************************/
22
23/* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
24 * play whilst audio is paused */
25#include "config.h" 23#include "config.h"
26#include "system.h" 24#include "system.h"
27#include <string.h>
28#include "playback.h"
29#include "codec_thread.h"
30#include "kernel.h" 25#include "kernel.h"
26#include "panic.h"
27#include "buffer.h"
28#include "sound.h"
29#include "ata.h"
30#include "usb.h"
31#include "codecs.h" 31#include "codecs.h"
32#include "buffering.h" 32#include "codec_thread.h"
33#include "voice_thread.h" 33#include "voice_thread.h"
34#include "usb.h" 34#include "metadata.h"
35#include "ata.h" 35#include "cuesheet.h"
36#include "buffering.h"
37#include "talk.h"
36#include "playlist.h" 38#include "playlist.h"
39#include "abrepeat.h"
37#include "pcmbuf.h" 40#include "pcmbuf.h"
38#include "buffer.h" 41#include "playback.h"
39#include "cuesheet.h" 42
40#ifdef HAVE_TAGCACHE 43#ifdef HAVE_TAGCACHE
41#include "tagcache.h" 44#include "tagcache.h"
42#endif 45#endif
46
47#ifdef AUDIO_HAVE_RECORDING
48#include "pcm_record.h"
49#endif
50
43#ifdef HAVE_LCD_BITMAP 51#ifdef HAVE_LCD_BITMAP
44#ifdef HAVE_ALBUMART 52#ifdef HAVE_ALBUMART
45#include "albumart.h" 53#include "albumart.h"
46#endif 54#endif
47#endif 55#endif
48#include "sound.h"
49#include "metadata.h"
50#include "splash.h"
51#include "talk.h"
52#include "panic.h"
53 56
54#ifdef HAVE_RECORDING 57/* TODO: The audio thread really is doing multitasking of acting like a
55#include "pcm_record.h" 58 consumer and producer of tracks. It may be advantageous to better
56#endif 59 logically separate the two functions. I won't go that far just yet. */
57 60
61/* Internal support for voice playback */
58#define PLAYBACK_VOICE 62#define PLAYBACK_VOICE
59 63
60/* amount of guess-space to allow for codecs that must hunt and peck 64#if CONFIG_PLATFORM & PLATFORM_NATIVE
61 * for their correct seeek target, 32k seems a good size */ 65/* Application builds don't support direct code loading */
66#define HAVE_CODEC_BUFFERING
67#endif
68
69/* Amount of guess-space to allow for codecs that must hunt and peck
70 * for their correct seek target, 32k seems a good size */
62#define AUDIO_REBUFFER_GUESS_SIZE (1024*32) 71#define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
63 72
64/* Define LOGF_ENABLE to enable logf output in this file */ 73/* Define LOGF_ENABLE to enable logf output in this file */
65/*#define LOGF_ENABLE*/ 74/* #define LOGF_ENABLE */
66#include "logf.h" 75#include "logf.h"
67 76
68/* macros to enable logf for queues 77/* Macros to enable logf for queues
69 logging on SYS_TIMEOUT can be disabled */ 78 logging on SYS_TIMEOUT can be disabled */
70#ifdef SIMULATOR 79#ifdef SIMULATOR
71/* Define this for logf output of all queuing except SYS_TIMEOUT */ 80/* Define this for logf output of all queuing except SYS_TIMEOUT */
@@ -86,202 +95,292 @@
86#define LOGFQUEUE_SYS_TIMEOUT(...) 95#define LOGFQUEUE_SYS_TIMEOUT(...)
87#endif 96#endif
88 97
98/* Variables are commented with the threads that use them:
99 * A=audio, C=codec, O=other. A suffix of "-" indicates that the variable is
100 * read but not updated on that thread. Audio is the only user unless otherwise
101 * specified.
102 */
89 103
90static enum filling_state { 104/** Miscellaneous **/
91 STATE_IDLE, /* audio is stopped: nothing to do */ 105bool audio_is_initialized = false; /* (A,O-) */
92 STATE_FILLING, /* adding tracks to the buffer */ 106extern struct codec_api ci; /* (A,C) */
93 STATE_FULL, /* can't add any more tracks */ 107
94 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */ 108/** Possible arrangements of the main buffer **/
95 STATE_FINISHED, /* all remaining tracks are fully buffered */ 109static enum audio_buffer_state
96 STATE_ENDING, /* audio playback is ending */ 110{
97#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 111 AUDIOBUF_STATE_TRASHED = -1, /* trashed; must be reset */
98 STATE_USB, /* USB mode, ignore most messages */ 112 AUDIOBUF_STATE_INITIALIZED = 0, /* voice+audio OR audio-only */
113 AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
114} buffer_state = AUDIOBUF_STATE_TRASHED; /* (A,O) */
115
116/** Main state control **/
117static bool ff_rw_mode SHAREDBSS_ATTR = false; /* Pre-ff-rewind mode (A,O-) */
118
119enum play_status
120{
121 PLAY_STOPPED = 0,
122 PLAY_PLAYING = AUDIO_STATUS_PLAY,
123 PLAY_PAUSED = AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE,
124} play_status = PLAY_STOPPED;
125
126/* Sizeable things that only need exist during playback and not when stopped */
127static struct audio_scratch_memory
128{
129 struct mp3entry codec_id3; /* (A,C) */
130 struct mp3entry unbuffered_id3;
131 struct cuesheet *curr_cue; /* Will follow this structure */
132} * audio_scratch_memory = NULL;
133
134/* These are used to store the current, next and optionally the peek-ahead
135 * mp3entry's - this guarentees that the pointer returned by audio_current/
136 * next_track will be valid for the full duration of the currently playing
137 * track */
138enum audio_id3_types
139{
140 /* These are allocated statically */
141 PLAYING_ID3 = 0,
142 NEXTTRACK_ID3,
143#ifdef AUDIO_FAST_SKIP_PREVIEW
144 /* The real playing metadata must has to be protected since it contains
145 critical info for other features */
146 PLAYING_PEEK_ID3,
99#endif 147#endif
100} filling; 148 ID3_TYPE_NUM_STATIC,
101 149 /* These go in the scratch memory */
102/* As defined in plugins/lib/xxx2wav.h */ 150 UNBUFFERED_ID3 = ID3_TYPE_NUM_STATIC,
103#define GUARD_BUFSIZE (32*1024) 151 CODEC_ID3,
104 152};
105bool audio_is_initialized = false; 153static struct mp3entry static_id3_entries[ID3_TYPE_NUM_STATIC]; /* (A,O) */
106static bool audio_thread_ready SHAREDBSS_ATTR = false;
107 154
108/* Variables are commented with the threads that use them: * 155/* Peeking functions can yield and mess us up */
109 * A=audio, C=codec, V=voice. A suffix of - indicates that * 156static struct mutex id3_mutex SHAREDBSS_ATTR; /* (A,0)*/
110 * the variable is read but not updated on that thread. */
111/* TBD: Split out "audio" and "playback" (ie. calling) threads */
112 157
113/* Main state control */
114static volatile bool playing SHAREDBSS_ATTR = false;/* Is audio playing? (A) */
115static volatile bool paused SHAREDBSS_ATTR = false; /* Is audio paused? (A/C-) */
116 158
117/* Ring buffer where compressed audio and codecs are loaded */ 159/** For Scrobbler support **/
118static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
119static size_t filebuflen = 0; /* Size of buffer (A/C-) */
120/* FIXME: make buf_ridx (C/A-) */
121 160
122/* Possible arrangements of the buffer */ 161/* Previous track elapsed time */
123enum audio_buffer_state 162static unsigned long prev_track_elapsed = 0; /* (A,O-) */
124{
125 AUDIOBUF_STATE_TRASHED = -1, /* trashed; must be reset */
126 AUDIOBUF_STATE_INITIALIZED = 0, /* voice+audio OR audio-only */
127 AUDIOBUF_STATE_VOICED_ONLY = 1, /* voice-only */
128};
129static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
130
131/* These are used to store the current and next (or prev if the current is the last)
132 * mp3entry's in a round-robin system. This guarentees that the pointer returned
133 * by audio_current/next_track will be valid for the full duration of the
134 * currently playing track */
135static struct mp3entry mp3entry_buf[2];
136struct mp3entry *thistrack_id3, /* the currently playing track */
137 *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
138 * next track otherwise */
139static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
140
141/* for cuesheet support */
142static struct cuesheet *curr_cue = NULL;
143 163
144 164
165/** For album art support **/
145#define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT 166#define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
146
147#ifdef HAVE_ALBUMART 167#ifdef HAVE_ALBUMART
148 168
149static struct albumart_slot { 169static struct albumart_slot
150 struct dim dim; /* holds width, height of the albumart */ 170{
151 int used; /* counter, increments if something uses it */ 171 struct dim dim; /* Holds width, height of the albumart */
152} albumart_slots[MAX_MULTIPLE_AA]; 172 int used; /* Counter; increments if something uses it */
173} albumart_slots[MAX_MULTIPLE_AA]; /* (A,O) */
153 174
154#define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++) 175#define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
155#endif 176#endif /* HAVE_ALBUMART */
156 177
157 178
158#define MAX_TRACK 128 179/** Information used for tracking buffer fills **/
159#define MAX_TRACK_MASK (MAX_TRACK-1)
160 180
161/* Track info structure about songs in the file buffer (A/C-) */ 181/* Buffer and thread state tracking */
162static struct track_info { 182static enum filling_state
163 int audio_hid; /* The ID for the track's buffer handle */ 183{
164 int id3_hid; /* The ID for the track's metadata handle */ 184 STATE_BOOT = 0, /* audio thread is not ready yet */
165 int codec_hid; /* The ID for the track's codec handle */ 185 STATE_IDLE, /* audio is stopped: nothing to do */
166#ifdef HAVE_ALBUMART 186 STATE_FILLING, /* adding tracks to the buffer */
167 int aa_hid[MAX_MULTIPLE_AA];/* The ID for the track's album art handle */ 187 STATE_FULL, /* can't add any more tracks */
188 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
189 STATE_FINISHED, /* all remaining tracks are fully buffered */
190 STATE_ENDING, /* audio playback is ending */
191 STATE_ENDED, /* audio playback is done */
192#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
193 STATE_USB, /* USB mode, ignore most messages */
168#endif 194#endif
169 int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */ 195} filling = STATE_BOOT;
170 196
171 size_t filesize; /* File total length */ 197/* Track info - holds information about each track in the buffer */
198struct track_info
199{
200 /* In per-track allocated order: */
201 int id3_hid; /* Metadata handle ID */
202 int cuesheet_hid; /* Parsed cueesheet handle ID */
203#ifdef HAVE_ALBUMART
204 int aa_hid[MAX_MULTIPLE_AA];/* Album art handle IDs */
205#endif
206#ifdef HAVE_CODEC_BUFFERING
207 int codec_hid; /* Buffered codec handle ID */
208#endif
209 int audio_hid; /* Main audio data handle ID */
210 size_t filesize; /* File total length on disk
211 TODO: This should be stored
212 in the handle or the
213 id3 and would use less
214 ram */
215};
172 216
173 bool taginfo_ready; /* Is metadata read */ 217/* Track list - holds info about all buffered tracks */
174 218#if MEMORYSIZE >= 32
175} tracks[MAX_TRACK]; 219#define TRACK_LIST_LEN 128 /* Must be 2^int(+n) */
220#elif MEMORYSIZE >= 16
221#define TRACK_LIST_LEN 64
222#elif MEMORYSIZE >= 8
223#define TRACK_LIST_LEN 32
224#else
225#define TRACK_LIST_LEN 16
226#endif
176 227
177static volatile int track_ridx = 0; /* Track being decoded (A/C-) */ 228#define TRACK_LIST_MASK (TRACK_LIST_LEN-1)
178static int track_widx = 0; /* Track being buffered (A) */
179#define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
180 229
181static struct track_info *prev_ti = NULL; /* Pointer to the previously played 230static struct
182 track */ 231{
232 /* read, write and current are maintained unwrapped, limited only by the
233 unsigned int range and wrap-safe comparisons are used */
183 234
184/* Information used only for filling the buffer */ 235 /* NOTE: there appears to be a bug in arm-elf-eabi-gcc 4.4.4 for ARMv4 where
185/* Playlist steps from playing track to next track to be buffered (A) */ 236 if 'end' follows 'start' in this structure, track_list_count performs
186static int last_peek_offset = 0; 237 'start - end' rather than 'end - start', giving negative count values...
238 so leave it this way for now! */
239 unsigned int end; /* Next open position */
240 unsigned int start; /* First track in list */
241 unsigned int current; /* Currently decoding track */
242 struct track_info tracks[TRACK_LIST_LEN]; /* Buffered track information */
243} track_list; /* (A, O-) */
187 244
188/* Scrobbler support */
189static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
190 245
191/* Track change controls */ 246/* Playlist steps from playlist position to next track to be buffered */
192static bool automatic_skip = false; /* Who initiated in-progress skip? (A) */ 247static int playlist_peek_offset = 0;
193extern bool track_transition; /* Are we in a track transition? */
194static bool dir_skip = false; /* Is a directory skip pending? (A) */
195static bool new_playlist = false; /* Are we starting a new playlist? (A) */
196static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
197static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
198 248
199static bool start_play_g = false; /* Used by audio_load_track to notify 249/* Metadata handle of track load in progress (meaning all handles have not
200 audio_finish_load_track about start_play */ 250 yet been opened for the track, id3 always exists or the track does not)
201 251
202/* True when a track load is in progress, i.e. audio_load_track() has returned 252 Tracks are keyed by their metadata handles if track list pointers are
203 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing 253 insufficient to make comparisons */
204 * audio_load_track() to get called twice in a row, which would cause problems. 254static int in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
205 */
206static bool track_load_started = false;
207 255
208#ifdef HAVE_DISK_STORAGE 256#ifdef HAVE_DISK_STORAGE
209static size_t buffer_margin = 5; /* Buffer margin aka anti-skip buffer (A/C-) */ 257/* Buffer margin A.K.A. anti-skip buffer (in seconds) */
258static size_t buffer_margin = 5;
210#endif 259#endif
211 260
212/* Event queues */ 261/* Values returned for track loading */
213struct event_queue audio_queue SHAREDBSS_ATTR; 262enum track_load_status
214static struct event_queue pcmbuf_queue SHAREDBSS_ATTR; 263{
264 LOAD_TRACK_ERR_START_CODEC = -6,
265 LOAD_TRACK_ERR_FINISH_FAILED = -5,
266 LOAD_TRACK_ERR_FINISH_FULL = -4,
267 LOAD_TRACK_ERR_BUSY = -3,
268 LOAD_TRACK_ERR_NO_MORE = -2,
269 LOAD_TRACK_ERR_FAILED = -1,
270 LOAD_TRACK_OK = 0,
271 LOAD_TRACK_READY = 1,
272};
215 273
216extern struct codec_api ci; 274/** Track change controls **/
217extern unsigned int codec_thread_id; 275
276/* What sort of skip is pending globally? */
277enum track_skip_type
278{
279 /* Relative to what user is intended to see: */
280 /* Codec: +0, Track List: +0, Playlist: +0 */
281 TRACK_SKIP_NONE = 0, /* no track skip */
282 /* Codec: +1, Track List: +1, Playlist: +0 */
283 TRACK_SKIP_AUTO, /* codec-initiated skip */
284 /* Codec: +1, Track List: +1, Playlist: +1 */
285 TRACK_SKIP_AUTO_NEW_PLAYLIST, /* codec-initiated skip is new playlist */
286 /* Codec: xx, Track List: +0, Playlist: +0 */
287 TRACK_SKIP_AUTO_END_PLAYLIST, /* codec-initiated end of playlist */
288 /* Manual skip: Never pends */
289 TRACK_SKIP_MANUAL, /* manual track skip */
290 /* Manual skip: Never pends */
291 TRACK_SKIP_DIR_CHANGE, /* manual directory skip */
292} skip_pending = TRACK_SKIP_NONE;
293
294/* Note about TRACK_SKIP_AUTO_NEW_PLAYLIST:
295 Fixing playlist code to be able to peek into the first song of
296 the next playlist would fix any issues and this wouldn't need
297 to be a special case since pre-advancing the playlist would be
298 unneeded - it could be much more like TRACK_SKIP_AUTO and all
299 actions that require reversal during an in-progress transition
300 would work as expected */
301
302/* Used to indicate status for the events. Must be separate to satisfy all
303 clients so the correct metadata is read when sending the change events
304 and also so that it is read correctly outside the events. */
305static bool automatic_skip = false; /* (A, O-) */
306
307/* Pending manual track skip offset */
308static int skip_offset = 0; /* (A, O) */
309
310/* Track change notification */
311static struct
312{
313 unsigned int in; /* Number of pcmbuf posts (audio isr) */
314 unsigned int out; /* Number of times audio has read the difference */
315} track_change = { 0, 0 };
316
317/** Codec status **/
318/* Did the codec notify us it finished while we were paused or while still
319 in an automatic transition?
320
321 If paused, it is necessary to defer a codec-initiated skip until resuming
322 or else the track will move forward while not playing audio!
323
324 If in-progress, skips should not build-up ahead of where the WPS is when
325 really short tracks finish decoding.
326
327 If it is forgotten, it will be missed altogether and playback will just sit
328 there looking stupid and comatose until the user does something */
329static bool codec_skip_pending = false;
330static int codec_skip_status;
331static bool codec_seeking = false; /* Codec seeking ack expected? */
218 332
219/* Multiple threads */ 333
220/* Set the watermark to trigger buffer fill (A/C) */ 334/* Event queues */
221static void set_filebuf_watermark(void); 335static struct event_queue audio_queue SHAREDBSS_ATTR;
222 336
223/* Audio thread */ 337/* Audio thread */
224static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR; 338static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
225static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)]; 339static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
226static const char audio_thread_name[] = "audio"; 340static const char audio_thread_name[] = "audio";
341static unsigned int audio_thread_id = 0;
342
343/* Forward declarations */
344enum audio_start_playback_flags
345{
346 AUDIO_START_RESTART = 0x1, /* "Restart" playback (flush _all_ tracks) */
347 AUDIO_START_NEWBUF = 0x2, /* Mark the audiobuffer as invalid */
348};
227 349
228static void audio_thread(void); 350static void audio_start_playback(size_t offset, unsigned int flags);
229static void audio_initiate_track_change(long direction);
230static bool audio_have_tracks(void);
231static void audio_reset_buffer(void);
232static void audio_stop_playback(void); 351static void audio_stop_playback(void);
352static void buffer_event_buffer_low_callback(void *data);
353static void buffer_event_rebuffer_callback(void *data);
354static void buffer_event_finished_callback(void *data);
355
233 356
234/**************************************/ 357/**************************************/
235 358
236/** Pcmbuf callbacks */ 359/** --- audio_queue helpers --- **/
237 360
238/* Between the codec and PCM track change, we need to keep updating the 361/* codec thread needs access */
239 * "elapsed" value of the previous (to the codec, but current to the 362void audio_queue_post(long id, intptr_t data)
240 * user/PCM/WPS) track, so that the progressbar reaches the end.
241 * During that transition, the WPS will display othertrack_id3. */
242void audio_pcmbuf_position_callback(unsigned int time)
243{ 363{
244 time += othertrack_id3->elapsed; 364 queue_post(&audio_queue, id, data);
245 othertrack_id3->elapsed = (time >= othertrack_id3->length)
246 ? othertrack_id3->length : time;
247} 365}
248 366
249/* Post message from pcmbuf that the end of the previous track 367static intptr_t audio_queue_send(long id, intptr_t data)
250 * has just been played. */
251void audio_post_track_change(bool pcmbuf)
252{ 368{
253 if (pcmbuf) 369 return queue_send(&audio_queue, id, data);
254 {
255 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
256 queue_post(&pcmbuf_queue, Q_AUDIO_TRACK_CHANGED, 0);
257 }
258 else
259 {
260 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
261 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
262 }
263} 370}
264 371
265/* Scan the pcmbuf queue and return true if a message pulled */
266static bool pcmbuf_queue_scan(struct queue_event *ev)
267{
268 if (!queue_empty(&pcmbuf_queue))
269 {
270 /* Transfer message to audio queue */
271 pcm_play_lock();
272 /* Pull message - never, ever any blocking call! */
273 queue_wait_w_tmo(&pcmbuf_queue, ev, 0);
274 pcm_play_unlock();
275 return true;
276 }
277
278 return false;
279}
280 372
373/** --- MP3Entry --- **/
281 374
282/** Helper functions */ 375/* Does the mp3entry have enough info for us to use it? */
376static struct mp3entry * valid_mp3entry(const struct mp3entry *id3)
377{
378 return id3 && (id3->length != 0 || id3->filesize != 0) &&
379 id3->codectype != AFMT_UNKNOWN ? (struct mp3entry *)id3 : NULL;
380}
283 381
284static struct mp3entry *bufgetid3(int handle_id) 382/* Return a pointer to an mp3entry on the buffer, as it is */
383static struct mp3entry * bufgetid3(int handle_id)
285{ 384{
286 if (handle_id < 0) 385 if (handle_id < 0)
287 return NULL; 386 return NULL;
@@ -295,6 +394,7 @@ static struct mp3entry *bufgetid3(int handle_id)
295 return id3; 394 return id3;
296} 395}
297 396
397/* Read an mp3entry from the buffer, adjusted */
298static bool bufreadid3(int handle_id, struct mp3entry *id3out) 398static bool bufreadid3(int handle_id, struct mp3entry *id3out)
299{ 399{
300 struct mp3entry *id3 = bufgetid3(handle_id); 400 struct mp3entry *id3 = bufgetid3(handle_id);
@@ -308,1200 +408,1441 @@ static bool bufreadid3(int handle_id, struct mp3entry *id3out)
308 return false; 408 return false;
309} 409}
310 410
311static bool clear_track_info(struct track_info *track) 411/* Lock the id3 mutex */
412static void id3_mutex_lock(void)
312{ 413{
313 /* bufclose returns true if the handle is not found, or if it is closed 414 mutex_lock(&id3_mutex);
314 * successfully, so these checks are safe on non-existant handles */
315 if (!track)
316 return false;
317
318 if (track->codec_hid >= 0) {
319 if (bufclose(track->codec_hid))
320 track->codec_hid = -1;
321 else
322 return false;
323 }
324
325 if (track->id3_hid >= 0) {
326 if (bufclose(track->id3_hid))
327 track->id3_hid = -1;
328 else
329 return false;
330 }
331
332 if (track->audio_hid >= 0) {
333 if (bufclose(track->audio_hid))
334 track->audio_hid = -1;
335 else
336 return false;
337 }
338
339#ifdef HAVE_ALBUMART
340 {
341 int i;
342 FOREACH_ALBUMART(i)
343 {
344 if (track->aa_hid[i] >= 0) {
345 if (bufclose(track->aa_hid[i]))
346 track->aa_hid[i] = -1;
347 else
348 return false;
349 }
350 }
351 }
352#endif
353
354 if (track->cuesheet_hid >= 0) {
355 if (bufclose(track->cuesheet_hid))
356 track->cuesheet_hid = -1;
357 else
358 return false;
359 }
360
361 track->filesize = 0;
362 track->taginfo_ready = false;
363
364 return true;
365} 415}
366 416
367/* --- External interfaces --- */ 417/* Unlock the id3 mutex */
368 418static void id3_mutex_unlock(void)
369/* This sends a stop message and the audio thread will dump all it's
370 subsequenct messages */
371void audio_hard_stop(void)
372{ 419{
373 /* Stop playback */ 420 mutex_unlock(&id3_mutex);
374 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
375 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
376#ifdef PLAYBACK_VOICE
377 voice_stop();
378#endif
379} 421}
380 422
381bool audio_restore_playback(int type) 423/* Return one of the collection of mp3entry pointers - collect them all here */
424static inline struct mp3entry * id3_get(enum audio_id3_types id3_num)
382{ 425{
383 switch (type) 426 switch (id3_num)
384 { 427 {
385 case AUDIO_WANT_PLAYBACK: 428 case UNBUFFERED_ID3:
386 if (buffer_state != AUDIOBUF_STATE_INITIALIZED) 429 return &audio_scratch_memory->unbuffered_id3;
387 audio_reset_buffer(); 430 case CODEC_ID3:
388 return true; 431 return &audio_scratch_memory->codec_id3;
389 case AUDIO_WANT_VOICE:
390 if (buffer_state == AUDIOBUF_STATE_TRASHED)
391 audio_reset_buffer();
392 return true;
393 default: 432 default:
394 return false; 433 return &static_id3_entries[id3_num];
395 } 434 }
396} 435}
397 436
398unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size) 437/* Copy an mp3entry into one of the mp3 entries */
438static void id3_write(enum audio_id3_types id3_num,
439 const struct mp3entry *id3_src)
399{ 440{
400 unsigned char *buf, *end; 441 struct mp3entry *dest_id3 = id3_get(id3_num);
401
402 if (audio_is_initialized)
403 {
404 audio_hard_stop();
405 }
406 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
407
408 /* Reset the buffering thread so that it doesn't try to use the data */
409 buffering_reset(filebuf, filebuflen);
410
411 if (buffer_size == NULL)
412 {
413 /* Special case for talk_init to use since it already knows it's
414 trashed */
415 buffer_state = AUDIOBUF_STATE_TRASHED;
416 return NULL;
417 }
418 442
419 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED 443 if (id3_src)
420 || !talk_voice_required()) 444 copy_mp3entry(dest_id3, id3_src);
421 {
422 logf("get buffer: talk, audio");
423 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
424 the talk buffer is not needed because voice isn't being used, or
425 could be AUDIOBUF_STATE_TRASHED already. If state is
426 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
427 without the caller knowing what's going on. Changing certain settings
428 may move it to a worse condition but the memory in use by something
429 else will remain undisturbed.
430 */
431 if (buffer_state != AUDIOBUF_STATE_TRASHED)
432 {
433 talk_buffer_steal();
434 buffer_state = AUDIOBUF_STATE_TRASHED;
435 }
436
437 buf = audiobuf;
438 end = audiobufend;
439 }
440 else 445 else
441 { 446 wipe_mp3entry(dest_id3);
442 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
443 still AUDIOBUF_STATE_INITIALIZED */
444 /* Skip talk buffer and move pcm buffer to end to maximize available
445 contiguous memory - no audio running means voice will not need the
446 swap space */
447 logf("get buffer: audio");
448 buf = audiobuf + talk_get_bufsize();
449 end = audiobufend - pcmbuf_init(audiobufend);
450 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
451 }
452
453 *buffer_size = end - buf;
454
455 return buf;
456} 447}
457 448
458bool audio_buffer_state_trashed(void) 449/* Call id3_write "safely" because peek aheads can yield, even if the fast
450 preview isn't enabled */
451static void id3_write_locked(enum audio_id3_types id3_num,
452 const struct mp3entry *id3_src)
459{ 453{
460 return buffer_state == AUDIOBUF_STATE_TRASHED; 454 id3_mutex_lock();
455 id3_write(id3_num, id3_src);
456 id3_mutex_unlock();
461} 457}
462 458
463#ifdef HAVE_RECORDING 459
464unsigned char *audio_get_recording_buffer(size_t *buffer_size) 460/** --- Track info --- **/
461
462/* Close a handle and mark it invalid */
463static void track_info_close_handle(int *hid_p)
465{ 464{
466 /* Stop audio, voice and obtain all available buffer space */ 465 int hid = *hid_p;
467 audio_hard_stop();
468 talk_buffer_steal();
469 466
470 unsigned char *end = audiobufend; 467 /* bufclose returns true if the handle is not found, or if it is closed
471 buffer_state = AUDIOBUF_STATE_TRASHED; 468 * successfully, so these checks are safe on non-existant handles */
472 *buffer_size = end - audiobuf; 469 if (hid >= 0)
470 bufclose(hid);
473 471
474 return (unsigned char *)audiobuf; 472 /* Always reset to "no handle" in case it was something else */
473 *hid_p = ERR_HANDLE_NOT_FOUND;
475} 474}
476 475
477bool audio_load_encoder(int afmt) 476/* Close all handles in a struct track_info and clear it */
477static void track_info_close(struct track_info *info)
478{ 478{
479#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 479 /* Close them in the order they are allocated on the buffer to speed up
480 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt); 480 the handle searching */
481 return queue_send(&audio_queue, Q_AUDIO_LOAD_ENCODER, afmt) > 0; 481 track_info_close_handle(&info->id3_hid);
482#else 482 track_info_close_handle(&info->cuesheet_hid);
483 (void)afmt; 483#ifdef HAVE_ALBUMART
484 return true; 484 int i;
485 FOREACH_ALBUMART(i)
486 track_info_close_handle(&info->aa_hid[i]);
485#endif 487#endif
486} /* audio_load_encoder */ 488#ifdef HAVE_CODEC_BUFFERING
489 track_info_close_handle(&info->codec_hid);
490#endif
491 track_info_close_handle(&info->audio_hid);
492 info->filesize = 0;
493}
487 494
488void audio_remove_encoder(void) 495/* Invalidate all members to initial values - does not close handles */
496static void track_info_wipe(struct track_info * info)
489{ 497{
490#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 498 info->id3_hid = ERR_HANDLE_NOT_FOUND;
491 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL"); 499 info->cuesheet_hid = ERR_HANDLE_NOT_FOUND;
492 queue_send(&audio_queue, Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN); 500#ifdef HAVE_ALBUMART
501 int i;
502 FOREACH_ALBUMART(i)
503 info->aa_hid[i] = ERR_HANDLE_NOT_FOUND;
504#endif
505#ifdef HAVE_CODEC_BUFFERING
506 info->codec_hid = ERR_HANDLE_NOT_FOUND;
493#endif 507#endif
494} /* audio_remove_encoder */ 508 info->audio_hid = ERR_HANDLE_NOT_FOUND;
509 info->filesize = 0;
510}
495 511
496#endif /* HAVE_RECORDING */
497 512
513/** --- Track list --- **/
498 514
499struct mp3entry* audio_current_track(void) 515/* Initialize the track list */
516static void track_list_init(void)
500{ 517{
501 const char *filename; 518 int i;
502 struct playlist_track_info trackinfo; 519 for (i = 0; i < TRACK_LIST_LEN; i++)
503 int cur_idx; 520 track_info_wipe(&track_list.tracks[i]);
504 int offset = ci.new_track + wps_offset;
505 struct mp3entry *write_id3;
506
507 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
508 521
509 if (cur_idx == track_ridx && *thistrack_id3->path) 522 track_list.start = track_list.end = track_list.current;
510 { 523}
511 /* The usual case */
512 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
513 {
514 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
515 thistrack_id3->cuesheet = curr_cue;
516 }
517 return thistrack_id3;
518 }
519 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
520 {
521 /* We're in a track transition. The codec has moved on to the next track,
522 but the audio being played is still the same (now previous) track.
523 othertrack_id3.elapsed is being updated in an ISR by
524 codec_pcmbuf_position_callback */
525 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
526 {
527 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
528 othertrack_id3->cuesheet = curr_cue;
529 }
530 return othertrack_id3;
531 }
532 524
533 if (offset != 0) 525/* Return number of items allocated in the list */
534 { 526static unsigned int track_list_count(void)
535 /* Codec may be using thistrack_id3, so it must not be overwritten. 527{
536 If this is a manual skip, othertrack_id3 will become 528 return track_list.end - track_list.start;
537 thistrack_id3 in audio_check_new_track(). 529}
538 FIXME: If this is an automatic skip, it probably means multiple
539 short tracks fit in the PCM buffer. Overwriting othertrack_id3
540 can lead to an incorrect value later.
541 Note that othertrack_id3 may also be used for next track.
542 */
543 write_id3 = othertrack_id3;
544 }
545 else
546 {
547 write_id3 = thistrack_id3;
548 }
549 530
550 if (tracks[cur_idx].id3_hid >= 0) 531/* Return true if the list is empty */
551 { 532static inline bool track_list_empty(void)
552 /* The current track's info has been buffered but not read yet, so get it */ 533{
553 if (bufreadid3(tracks[cur_idx].id3_hid, write_id3)) 534 return track_list.end == track_list.start;
554 return write_id3; 535}
555 }
556 536
557 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info 537/* Returns true if the list is holding the maximum number of items */
558 we have and return that. */ 538static bool track_list_full(void)
539{
540 return track_list.end - track_list.start >= TRACK_LIST_LEN;
541}
559 542
560 memset(write_id3, 0, sizeof(struct mp3entry)); 543/* Test if the index is within the allocated range */
544static bool track_list_in_range(int pos)
545{
546 return (int)(pos - track_list.start) >= 0 &&
547 (int)(pos - track_list.end) < 0;
548}
561 549
562 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo); 550static struct track_info * track_list_entry(int pos)
563 filename = trackinfo.filename; 551{
564 if (!filename) 552 return &track_list.tracks[pos & TRACK_LIST_MASK];
565 filename = "No file!"; 553}
566 554
567#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE) 555/* Return the info of the last allocation plus an offset, NULL if result is
568 if (tagcache_fill_tags(write_id3, filename)) 556 out of bounds */
569 return write_id3; 557static struct track_info * track_list_last(int offset)
570#endif 558{
559 /* Last is before the end since the end isn't inclusive */
560 unsigned int pos = track_list.end + offset - 1;
571 561
572 strlcpy(write_id3->path, filename, sizeof(write_id3->path)); 562 if (!track_list_in_range(pos))
573 write_id3->title = strrchr(write_id3->path, '/'); 563 return NULL;
574 if (!write_id3->title)
575 write_id3->title = &write_id3->path[0];
576 else
577 write_id3->title++;
578 564
579 return write_id3; 565 return track_list_entry(pos);
580} 566}
581 567
582struct mp3entry* audio_next_track(void) 568/* Allocate space at the end for another track if not full */
569static struct track_info * track_list_alloc_track(void)
583{ 570{
584 int next_idx; 571 if (track_list_full())
585 int offset = ci.new_track + wps_offset;
586
587 if (!audio_have_tracks())
588 return NULL; 572 return NULL;
589 573
590 if (wps_offset == -1 && *thistrack_id3->path) 574 return track_list_entry(track_list.end++);
591 { 575}
592 /* We're in a track transition. The next track for the WPS is the one
593 currently being decoded. */
594 return thistrack_id3;
595 }
596 576
597 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK; 577/* Remove the last track entry allocated in order to support backing out
578 of a track load */
579static void track_list_unalloc_track(void)
580{
581 if (track_list_empty())
582 return;
598 583
599 if (tracks[next_idx].id3_hid >= 0) 584 track_list.end--;
600 {
601 if (bufreadid3(tracks[next_idx].id3_hid, othertrack_id3))
602 return othertrack_id3;
603 else
604 return NULL;
605 }
606 585
607 if (next_idx == track_widx) 586 if (track_list.current == track_list.end &&
587 track_list.current != track_list.start)
608 { 588 {
609 /* The next track hasn't been buffered yet, so we return the static 589 /* Current _must_ remain within bounds */
610 version of its metadata. */ 590 track_list.current--;
611 return &unbuffered_id3;
612 } 591 }
613
614 return NULL;
615} 592}
616 593
617/* gets a copy of the id3 data */ 594/* Return current track plus an offset, NULL if result is out of bounds */
618bool audio_peek_track(struct mp3entry* id3, int offset) 595static struct track_info * track_list_current(int offset)
619{ 596{
620 int next_idx; 597 unsigned int pos = track_list.current + offset;
621 int new_offset = ci.new_track + wps_offset + offset;
622
623 if (!audio_have_tracks())
624 return false;
625 next_idx = (track_ridx + new_offset) & MAX_TRACK_MASK;
626 598
627 if (tracks[next_idx].id3_hid >= 0) 599 if (!track_list_in_range(pos))
628 return bufreadid3(tracks[next_idx].id3_hid, id3); 600 return NULL;
629
630 return false;
631}
632
633#ifdef HAVE_ALBUMART
634
635int playback_current_aa_hid(int slot)
636{
637 if (slot < 0)
638 return -1;
639 int cur_idx;
640 int offset = ci.new_track + wps_offset;
641 601
642 cur_idx = track_ridx + offset; 602 return track_list_entry(pos);
643 cur_idx &= MAX_TRACK_MASK;
644 return tracks[cur_idx].aa_hid[slot];
645} 603}
646 604
647int playback_claim_aa_slot(struct dim *dim) 605/* Return current based upon what's intended that the user sees - not
606 necessarily where decoding is taking place */
607static struct track_info * track_list_user_current(int offset)
648{ 608{
649 int i; 609 if (skip_pending == TRACK_SKIP_AUTO ||
650 610 skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)
651 /* first try to find a slot already having the size to reuse it
652 * since we don't want albumart of the same size buffered multiple times */
653 FOREACH_ALBUMART(i)
654 {
655 struct albumart_slot *slot = &albumart_slots[i];
656 if (slot->dim.width == dim->width
657 && slot->dim.height == dim->height)
658 {
659 slot->used++;
660 return i;
661 }
662 }
663 /* size is new, find a free slot */
664 FOREACH_ALBUMART(i)
665 { 611 {
666 if (!albumart_slots[i].used) 612 offset--;
667 {
668 albumart_slots[i].used++;
669 albumart_slots[i].dim = *dim;
670 return i;
671 }
672 } 613 }
673 /* sorry, no free slot */
674 return -1;
675}
676 614
677void playback_release_aa_slot(int slot) 615 return track_list_current(offset);
678{
679 /* invalidate the albumart_slot */
680 struct albumart_slot *aa_slot = &albumart_slots[slot];
681
682 if (aa_slot->used > 0)
683 aa_slot->used--;
684} 616}
685 617
686#endif 618/* Advance current track by an offset, return false if result is out of
687void audio_play(long offset) 619 bounds */
620static struct track_info * track_list_advance_current(int offset)
688{ 621{
689 logf("audio_play"); 622 unsigned int pos = track_list.current + offset;
690 623
691#ifdef PLAYBACK_VOICE 624 if (!track_list_in_range(pos))
692 /* Truncate any existing voice output so we don't have spelling 625 return NULL;
693 * etc. over the first part of the played track */
694 talk_force_shutup();
695#endif
696 626
697 /* Start playback */ 627 track_list.current = pos;
698 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset); 628 return track_list_entry(pos);
699 /* Don't return until playback has actually started */
700 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
701} 629}
702 630
703void audio_stop(void) 631/* Clear tracks in the list, optionally preserving the current track -
632 returns 'false' if the operation was changed */
633enum track_clear_action
704{ 634{
705 /* Stop playback */ 635 TRACK_LIST_CLEAR_ALL = 0, /* Clear all tracks */
706 LOGFQUEUE("audio >| audio Q_AUDIO_STOP"); 636 TRACK_LIST_KEEP_CURRENT, /* Keep current only; clear before + after */
707 /* Don't return until playback has actually stopped */ 637 TRACK_LIST_KEEP_NEW /* Keep current and those that follow */
708 queue_send(&audio_queue, Q_AUDIO_STOP, 0); 638};
709}
710 639
711void audio_pause(void) 640static void track_list_clear(enum track_clear_action action)
712{ 641{
713 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE"); 642 logf("%s(%d)", __func__, (int)action);
714 /* Don't return until playback has actually paused */
715 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
716}
717 643
718void audio_resume(void) 644 /* Don't care now since rebuffering is imminent */
719{ 645 buf_set_watermark(0);
720 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
721 /* Don't return until playback has actually resumed */
722 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
723}
724 646
725void audio_skip(int direction) 647 if (action != TRACK_LIST_CLEAR_ALL)
726{
727 if (playlist_check(ci.new_track + wps_offset + direction))
728 { 648 {
729 if (global_settings.beep) 649 struct track_info *cur = track_list_current(0);
730 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
731 650
732 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction); 651 if (!cur || cur->id3_hid < 0)
733 queue_post(&audio_queue, Q_AUDIO_SKIP, direction); 652 action = TRACK_LIST_CLEAR_ALL; /* Nothing worthwhile keeping */
734 /* Update wps while our message travels inside deep playback queues. */
735 wps_offset += direction;
736 } 653 }
737 else 654
655 /* Noone should see this progressing */
656 int start = track_list.start;
657 int current = track_list.current;
658 int end = track_list.end;
659
660 track_list.start = current;
661
662 switch (action)
738 { 663 {
739 /* No more tracks. */ 664 case TRACK_LIST_CLEAR_ALL:
740 if (global_settings.beep) 665 /* Result: .start = .current, .end = .current */
741 pcmbuf_beep(1000, 100, 1500*global_settings.beep); 666 track_list.end = current;
667 break;
668
669 case TRACK_LIST_KEEP_CURRENT:
670 /* Result: .start = .current, .end = .current + 1 */
671 track_list.end = current + 1;
672 break;
673
674 case TRACK_LIST_KEEP_NEW:
675 /* Result: .start = .current, .end = .end */
676 end = current;
677 break;
742 } 678 }
743}
744 679
745void audio_next(void) 680 /* Close all open handles in the range except the for the current track
746{ 681 if preserving that */
747 audio_skip(1); 682 while (start != end)
748} 683 {
684 if (action != TRACK_LIST_KEEP_CURRENT || start != current)
685 {
686 struct track_info *info =
687 &track_list.tracks[start & TRACK_LIST_MASK];
749 688
750void audio_prev(void) 689 /* If this is the in-progress load, abort it */
751{ 690 if (in_progress_id3_hid >= 0 &&
752 audio_skip(-1); 691 info->id3_hid == in_progress_id3_hid)
753} 692 {
693 in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
694 }
754 695
755void audio_next_dir(void) 696 track_info_close(info);
756{ 697 }
757 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
758 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
759}
760 698
761void audio_prev_dir(void) 699 start++;
762{ 700 }
763 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
764 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
765} 701}
766 702
767void audio_pre_ff_rewind(void)
768{
769 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
770 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
771}
772 703
773void audio_ff_rewind(long newpos) 704/** --- Audio buffer -- **/
774{
775 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
776 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
777}
778 705
779void audio_flush_and_reload_tracks(void) 706/* What size is needed for the scratch buffer? */
707static size_t scratch_mem_size(void)
780{ 708{
781 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH"); 709 size_t size = sizeof (struct audio_scratch_memory);
782 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0); 710
711 if (global_settings.cuesheet)
712 size += sizeof (struct cuesheet);
713
714 return size;
783} 715}
784 716
785void audio_error_clear(void) 717/* Initialize the memory area where data is stored that is only used when
718 playing audio and anything depending upon it */
719static void scratch_mem_init(void *mem)
786{ 720{
787#ifdef AUDIO_HAVE_RECORDING 721 audio_scratch_memory = (struct audio_scratch_memory *)mem;
788 pcm_rec_error_clear(); 722 id3_write_locked(UNBUFFERED_ID3, NULL);
789#endif 723 id3_write(CODEC_ID3, NULL);
724 ci.id3 = id3_get(CODEC_ID3);
725 audio_scratch_memory->curr_cue = NULL;
726
727 if (global_settings.cuesheet)
728 {
729 audio_scratch_memory->curr_cue =
730 SKIPBYTES((struct cuesheet *)audio_scratch_memory,
731 sizeof (struct audio_scratch_memory));
732 }
790} 733}
791 734
792int audio_status(void) 735/* Set up the audio buffer for playback */
736static void audio_reset_buffer(void)
793{ 737{
794 int ret = 0; 738 /*
739 * Layout audio buffer as follows:
740 * [[|TALK]|SCRATCH|BUFFERING|PCM|]
741 */
795 742
796 if (playing) 743 /* see audio_get_recording_buffer if this is modified */
797 ret |= AUDIO_STATUS_PLAY; 744 logf("%s()", __func__);
798 745
799 if (paused) 746 /* If the setup of anything allocated before the file buffer is
800 ret |= AUDIO_STATUS_PAUSE; 747 changed, do check the adjustments after the buffer_alloc call
748 as it will likely be affected and need sliding over */
801 749
802#ifdef HAVE_RECORDING 750 /* Initially set up file buffer as all space available */
803 /* Do this here for constitency with mpeg.c version */ 751 unsigned char *filebuf = audiobuf + talk_get_bufsize();
804 /* FIXME: pcm_rec_status() is deprecated */ 752 size_t filebuflen = audiobufend - filebuf;
805 ret |= pcm_rec_status(); 753 size_t allocsize;
806#endif
807 754
808 return ret; 755 ALIGN_BUFFER(filebuf, filebuflen, sizeof (intptr_t));
809}
810 756
811bool audio_automatic_skip(void) 757 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
812{ 758 allocsize = pcmbuf_init(filebuf + filebuflen);
813 return automatic_skip;
814}
815 759
816int audio_get_file_pos(void) 760 /* Make sure filebuflen is a pointer sized multiple after adjustment */
817{ 761 allocsize = ALIGN_UP(allocsize, sizeof (intptr_t));
818 return 0; 762 if (allocsize > filebuflen)
819} 763 goto bufpanic;
820 764
821#ifdef HAVE_DISK_STORAGE 765 filebuflen -= allocsize;
822void audio_set_buffer_margin(int setting)
823{
824 static const unsigned short lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
825 buffer_margin = lookup[setting];
826 logf("buffer margin: %ld", (long)buffer_margin);
827 set_filebuf_watermark();
828}
829#endif
830 766
831#ifdef HAVE_CROSSFADE 767 /* Scratch memory */
832/* Take necessary steps to enable or disable the crossfade setting */ 768 allocsize = scratch_mem_size();
833void audio_set_crossfade(int enable) 769 if (allocsize > filebuflen)
834{ 770 goto bufpanic;
835 size_t offset;
836 bool was_playing;
837 size_t size;
838 771
839 /* Tell it the next setting to use */ 772 scratch_mem_init(filebuf);
840 pcmbuf_request_crossfade_enable(enable); 773 filebuf += allocsize;
774 filebuflen -= allocsize;
841 775
842 /* Return if size hasn't changed or this is too early to determine 776 buffering_reset(filebuf, filebuflen);
843 which in the second case there's no way we could be playing
844 anything at all */
845 if (pcmbuf_is_same_size()) return;
846 777
847 offset = 0; 778 /* Clear any references to the file buffer */
848 was_playing = playing; 779 buffer_state = AUDIOBUF_STATE_INITIALIZED;
849 780
850 /* Playback has to be stopped before changing the buffer size */ 781#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
851 if (was_playing) 782 /* Make sure everything adds up - yes, some info is a bit redundant but
783 aids viewing and the sumation of certain variables should add up to
784 the location of others. */
852 { 785 {
853 /* Store the track resume position */ 786 size_t pcmbufsize;
854 offset = thistrack_id3->offset; 787 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
788 logf("fbuf: %08X", (unsigned)filebuf);
789 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
790 logf("sbuf: %08X", (unsigned)audio_scratch_memory);
791 logf("sbufe: %08X", (unsigned)(audio_scratch_memory + allocsize));
792 logf("pcmb: %08X", (unsigned)pcmbuf);
793 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
855 } 794 }
795#endif
856 796
857 /* Blast it - audio buffer will have to be setup again next time 797 return;
858 something plays */
859 audio_get_buffer(true, &size);
860 798
861 /* Restart playback if audio was running previously */ 799bufpanic:
862 if (was_playing) 800 panicf("%s(): EOM (%zu > %zu)", __func__, allocsize, filebuflen);
863 audio_play(offset);
864} 801}
865#endif
866
867/* --- Routines called from multiple threads --- */
868 802
869static void set_filebuf_watermark(void) 803/* Set the buffer margin to begin rebuffering when 'seconds' from empty */
804static void audio_update_filebuf_watermark(int seconds)
870{ 805{
871 if (!filebuf) 806 size_t bytes = 0;
872 return; /* Audio buffers not yet set up */
873 807
874#ifdef HAVE_DISK_STORAGE 808#ifdef HAVE_DISK_STORAGE
875 int seconds;
876 int spinup = ata_spinup_time(); 809 int spinup = ata_spinup_time();
810
811 if (seconds == 0)
812 {
813 /* By current setting */
814 seconds = buffer_margin;
815 }
816 else
817 {
818 /* New setting */
819 buffer_margin = seconds;
820
821 if (buf_get_watermark() == 0)
822 {
823 /* Write a watermark only if the audio thread already did so for
824 itself or it will fail to set the event and the watermark - if
825 it hasn't yet, it will use the new setting when it does */
826 return;
827 }
828 }
829
877 if (spinup) 830 if (spinup)
878 seconds = (spinup / HZ) + 1; 831 seconds += (spinup / HZ) + 1;
879 else 832 else
880 seconds = 5; 833 seconds += 5;
881 834
882 seconds += buffer_margin; 835 seconds += buffer_margin;
883#else 836#else
884 /* flash storage */ 837 /* flash storage */
885 int seconds = 1; 838 seconds = 1;
886#endif 839#endif
887 840
888 /* bitrate of last track in buffer dictates watermark */ 841 /* Watermark is a function of the bitrate of the last track in the buffer */
889 struct mp3entry* id3 = NULL; 842 struct mp3entry *id3 = NULL;
890 if (tracks[track_widx].taginfo_ready) 843 struct track_info *info = track_list_last(0);
891 id3 = bufgetid3(tracks[track_widx].id3_hid); 844
845 if (info)
846 id3 = valid_mp3entry(bufgetid3(info->id3_hid));
847
848 if (id3)
849 {
850 if (get_audio_base_data_type(id3->codectype) == TYPE_PACKET_AUDIO)
851 {
852 bytes = id3->bitrate * (1000/8) * seconds;
853 }
854 else
855 {
856 /* Bitrate has no meaning to buffering margin for atomic audio -
857 rebuffer when it's the only track left unless it's the only
858 track that fits, in which case we should avoid constant buffer
859 low events */
860 if (track_list_count() > 1)
861 bytes = info->filesize + 1;
862 }
863 }
892 else 864 else
893 id3 = bufgetid3(tracks[track_widx-1].id3_hid); 865 {
894 if (!id3) { 866 /* Then set the minimum - this should not occur anyway */
895 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx); 867 logf("fwmark: No id3 for last track (s%u/c%u/e%u)",
896 return; 868 track_list.start, track_list.current, track_list.end);
897 } 869 }
898 size_t bytes = id3->bitrate * (1000/8) * seconds; 870
899 buf_set_watermark(bytes); 871 /* Actually setting zero disables the notification and we use that
900 logf("fwmark: %d", bytes); 872 to detect that it has been reset */
873 buf_set_watermark(MAX(bytes, 1));
874 logf("fwmark: %lu", (unsigned long)bytes);
901} 875}
902 876
903/* --- Buffering callbacks --- */
904 877
905static void buffering_low_buffer_callback(void *data) 878/** -- Track change notification -- **/
879
880/* Check the pcmbuf track changes and return write the message into the event
881 if there are any */
882static inline bool audio_pcmbuf_track_change_scan(void)
906{ 883{
907 (void)data; 884 if (track_change.out != track_change.in)
908 logf("low buffer callback"); 885 {
886 track_change.out++;
887 return true;
888 }
889
890 return false;
891}
892
893/* Clear outstanding track change posts */
894static inline void audio_pcmbuf_track_change_clear(void)
895{
896 track_change.out = track_change.in;
897}
898
899/* Post a track change notification - called by audio ISR */
900static inline void audio_pcmbuf_track_change_post(void)
901{
902 track_change.in++;
903}
909 904
910 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) { 905
911 /* force a refill */ 906/** --- Helper functions --- **/
912 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER"); 907
913 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); 908/* Removes messages that might end up in the queue before or while processing
909 a manual track change. Responding to them would be harmful since they
910 belong to a previous track's playback period. Anything that would generate
911 the stale messages must first be put into a state where it will not do so.
912 */
913static void audio_clear_track_notifications(void)
914{
915 static const long filter_list[][2] =
916 {
917 /* codec messages */
918 { Q_AUDIO_CODEC_SEEK_COMPLETE, Q_AUDIO_CODEC_COMPLETE },
919 /* track change messages */
920 { Q_AUDIO_TRACK_CHANGED, Q_AUDIO_TRACK_CHANGED },
921 };
922
923 const int filter_count = ARRAYLEN(filter_list) - 1;
924
925 /* Remove any pcmbuf notifications */
926 pcmbuf_monitor_track_change(false);
927 audio_pcmbuf_track_change_clear();
928
929 /* Scrub the audio queue of the old mold */
930 while (queue_peek_ex(&audio_queue, NULL,
931 filter_count | QPEEK_REMOVE_EVENTS,
932 filter_list))
933 {
934 yield(); /* Not strictly needed, per se, ad infinitum, ra, ra */
914 } 935 }
915} 936}
916 937
917static void buffering_handle_rebuffer_callback(void *data) 938/* Takes actions based upon track load status codes */
939static void audio_handle_track_load_status(int trackstat)
918{ 940{
919 (void)data; 941 switch (trackstat)
920 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH"); 942 {
921 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0); 943 case LOAD_TRACK_ERR_NO_MORE:
944 if (track_list_count() > 0)
945 break;
946
947 case LOAD_TRACK_ERR_START_CODEC:
948 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, CODEC_ERROR);
949 break;
950
951 default:
952 break;
953 }
922} 954}
923 955
924static void buffering_handle_finished_callback(void *data) 956/* Announce the end of playing the current track */
957static void audio_playlist_track_finish(void)
925{ 958{
926 logf("handle %d finished buffering", *(int*)data); 959 struct mp3entry *id3 = valid_mp3entry(id3_get(PLAYING_ID3));
927 int hid = (*(int*)data);
928 960
929 if (hid == tracks[track_widx].id3_hid) 961 playlist_update_resume_info(filling == STATE_ENDED ? NULL : id3);
962
963 if (id3)
930 { 964 {
931 int offset = ci.new_track + wps_offset; 965 send_event(PLAYBACK_EVENT_TRACK_FINISH, id3);
932 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK; 966 prev_track_elapsed = id3->elapsed;
933 /* The metadata handle for the last loaded track has been buffered.
934 We can ask the audio thread to load the rest of the track's data. */
935 LOGFQUEUE("audio > audio Q_AUDIO_FINISH_LOAD");
936 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
937 if (tracks[next_idx].id3_hid == hid)
938 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
939 } 967 }
940 else 968 else
941 { 969 {
942 /* This is most likely an audio handle, so we strip the useless 970 prev_track_elapsed = 0;
943 trailing tags that are left. */
944 strip_tags(hid);
945
946 if (hid == tracks[track_widx-1].audio_hid
947 && filling == STATE_END_OF_PLAYLIST)
948 {
949 /* This was the last track in the playlist.
950 We now have all the data we need. */
951 logf("last track finished buffering");
952 filling = STATE_FINISHED;
953 }
954 } 971 }
955} 972}
956 973
974/* Announce the beginning of the new track */
975static void audio_playlist_track_change(void)
976{
977 struct mp3entry *id3 = valid_mp3entry(id3_get(PLAYING_ID3));
978
979 if (id3)
980 send_event(PLAYBACK_EVENT_TRACK_CHANGE, id3);
957 981
958/* --- Audio thread --- */ 982 playlist_update_resume_info(id3);
983}
959 984
960static bool audio_have_tracks(void) 985/* Change the data for the next track and send the event */
986static void audio_update_and_announce_next_track(const struct mp3entry *id3_next)
961{ 987{
962 return (audio_track_count() != 0); 988 id3_write_locked(NEXTTRACK_ID3, id3_next);
989 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE,
990 id3_get(NEXTTRACK_ID3));
963} 991}
964 992
965static int audio_free_track_count(void) 993/* Bring the user current mp3entry up to date and set a new offset for the
994 buffered metadata */
995static void playing_id3_sync(struct track_info *user_info, size_t offset)
966{ 996{
967 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */ 997 id3_mutex_lock();
968 return MAX_TRACK - 1 - audio_track_count(); 998
999 struct mp3entry *id3 = bufgetid3(user_info->id3_hid);
1000
1001 if (offset == (size_t)-1)
1002 {
1003 struct mp3entry *ply_id3 = id3_get(PLAYING_ID3);
1004 size_t play_offset = ply_id3->offset;
1005 long play_elapsed = ply_id3->elapsed;
1006 id3_write(PLAYING_ID3, id3);
1007 ply_id3->offset = play_offset;
1008 ply_id3->elapsed = play_elapsed;
1009 offset = 0;
1010 }
1011 else
1012 {
1013 id3_write(PLAYING_ID3, id3);
1014 }
1015
1016 if (id3)
1017 id3->offset = offset;
1018
1019 id3_mutex_unlock();
969} 1020}
970 1021
971int audio_track_count(void) 1022/* Wipe-out track metadata - current is optional */
1023static void wipe_track_metadata(bool current)
972{ 1024{
973 /* Calculate difference from track_ridx to track_widx 1025 id3_mutex_lock();
974 * taking into account a possible wrap-around. */ 1026
975 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK; 1027 if (current)
1028 id3_write(PLAYING_ID3, NULL);
1029
1030 id3_write(NEXTTRACK_ID3, NULL);
1031 id3_write(UNBUFFERED_ID3, NULL);
1032
1033 id3_mutex_unlock();
976} 1034}
977 1035
978long audio_filebufused(void) 1036/* Called when buffering is completed on the last track handle */
1037static void filling_is_finished(void)
979{ 1038{
980 return (long) buf_used(); 1039 logf("last track finished buffering");
1040
1041 /* There's no more to load or watch for */
1042 buf_set_watermark(0);
1043 filling = STATE_FINISHED;
981} 1044}
982 1045
983/* Update track info after successful a codec track change */ 1046/* Stop the codec decoding or waiting for its data to be ready - returns
984static void audio_update_trackinfo(void) 1047 'false' if the codec ended up stopped */
1048static bool halt_decoding_track(bool stop)
985{ 1049{
986 bool resume = false; 1050 /* If it was waiting for us to clear the buffer to make a rebuffer
1051 happen, it should cease otherwise codec_stop could deadlock waiting
1052 for the codec to go to its main loop - codec's request will now
1053 force-fail */
1054 bool retval = false;
987 1055
988 /* Load the curent track's metadata into curtrack_id3 */ 1056 buf_signal_handle(ci.audio_hid, true);
989 if (CUR_TI->id3_hid >= 0)
990 bufreadid3(CUR_TI->id3_hid, thistrack_id3);
991 1057
992 /* Reset current position */ 1058 if (stop)
993 thistrack_id3->elapsed = 0; 1059 codec_stop();
1060 else
1061 retval = codec_pause();
994 1062
995#ifdef HAVE_TAGCACHE 1063 audio_clear_track_notifications();
996 /* Ignoring resume position for automatic track change if so configured */
997 resume = global_settings.autoresume_enable &&
998 (!automatic_skip /* Resume all manually selected tracks */
999 || global_settings.autoresume_automatic == AUTORESUME_NEXTTRACK_ALWAYS
1000 || (global_settings.autoresume_automatic != AUTORESUME_NEXTTRACK_NEVER
1001 /* Not never resume? */
1002 && autoresumable(thistrack_id3))); /* Pass Resume filter? */
1003#endif
1004 1064
1005 if (!resume) 1065 /* We now know it's idle and not waiting for buffered data */
1006 { 1066 buf_signal_handle(ci.audio_hid, false);
1007 thistrack_id3->offset = 0;
1008 }
1009 1067
1010 logf("audio_update_trackinfo: Set offset for %s to %lX\n", 1068 codec_skip_pending = false;
1011 thistrack_id3->title, thistrack_id3->offset); 1069 codec_seeking = false;
1012 1070
1013 /* Update the codec API */ 1071 return retval;
1014 ci.filesize = CUR_TI->filesize;
1015 ci.id3 = thistrack_id3;
1016 ci.curpos = 0;
1017 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1018} 1072}
1019 1073
1020/* Clear tracks between write and read, non inclusive */ 1074/* Clear the PCM on a manual skip */
1021static void audio_clear_track_entries(void) 1075static void audio_clear_paused_pcm(void)
1022{ 1076{
1023 int cur_idx = track_widx; 1077 if (play_status == PLAY_PAUSED && !pcmbuf_is_crossfade_active())
1024 1078 pcmbuf_play_stop();
1025 logf("Clearing tracks: r%d/w%d", track_ridx, track_widx); 1079}
1026 1080
1027 /* Loop over all tracks from write-to-read */ 1081/* End the ff/rw mode */
1028 while (1) 1082static void audio_ff_rewind_end(void)
1083{
1084 /* A seamless seek (not calling audio_pre_ff_rewind) skips this
1085 section */
1086 if (ff_rw_mode)
1029 { 1087 {
1030 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK; 1088 ff_rw_mode = false;
1031 1089
1032 if (cur_idx == track_ridx) 1090 if (codec_seeking)
1033 break; 1091 {
1092 /* Clear the buffer */
1093 pcmbuf_play_stop();
1094 }
1034 1095
1035 clear_track_info(&tracks[cur_idx]); 1096 if (play_status != PLAY_PAUSED)
1097 {
1098 /* Seeking-while-playing, resume PCM playback */
1099 pcmbuf_pause(false);
1100 }
1036 } 1101 }
1037} 1102}
1038 1103
1039/* Clear all tracks */ 1104/* Complete the codec seek */
1040static bool audio_release_tracks(void) 1105static void audio_complete_codec_seek(void)
1041{ 1106{
1042 int i, cur_idx; 1107 /* If a seek completed while paused, 'paused' is true.
1043 1108 * If seeking from seek mode, 'ff_rw_mode' is true. */
1044 logf("releasing all tracks"); 1109 if (codec_seeking)
1045
1046 for(i = 0; i < MAX_TRACK; i++)
1047 { 1110 {
1048 cur_idx = (track_ridx + i) & MAX_TRACK_MASK; 1111 audio_ff_rewind_end();
1049 if (!clear_track_info(&tracks[cur_idx])) 1112 codec_seeking = false; /* set _after_ the call! */
1050 return false;
1051 } 1113 }
1114 /* else it's waiting and we must repond */
1115}
1052 1116
1053 return true; 1117/* Get the current cuesheet pointer */
1118static inline struct cuesheet * get_current_cuesheet(void)
1119{
1120 return audio_scratch_memory->curr_cue;
1054} 1121}
1055 1122
1056static bool audio_loadcodec(bool start_play) 1123/* Read the cuesheet from the buffer */
1124static void buf_read_cuesheet(int handle_id)
1057{ 1125{
1058 int prev_track, hid; 1126 struct cuesheet *cue = get_current_cuesheet();
1059 char codec_path[MAX_PATH]; /* Full path to codec */
1060 const struct mp3entry *id3, *prev_id3;
1061 1127
1062 if (tracks[track_widx].id3_hid < 0) { 1128 if (!cue || handle_id < 0)
1063 return false; 1129 return;
1064 }
1065 1130
1066 id3 = bufgetid3(tracks[track_widx].id3_hid); 1131 bufread(handle_id, sizeof (struct cuesheet), cue);
1067 if (!id3) 1132}
1068 return false;
1069 1133
1070 const char *codec_fn = get_codec_filename(id3->codectype); 1134/* Backend to peek/current/next track metadata interface functions -
1071 if (codec_fn == NULL) 1135 fill in the mp3entry with as much information as we may obtain about
1136 the track at the specified offset from the user current track -
1137 returns false if no information exists with us */
1138static bool audio_get_track_metadata(int offset, struct mp3entry *id3)
1139{
1140 if (play_status == PLAY_STOPPED)
1072 return false; 1141 return false;
1073 1142
1074 tracks[track_widx].codec_hid = -1; 1143 if (id3->path[0] != '\0')
1144 return true; /* Already filled */
1145
1146 struct track_info *info = track_list_user_current(offset);
1075 1147
1076 if (start_play) 1148 if (!info)
1077 { 1149 {
1078 /* Load the codec directly from disk and save some memory. */ 1150 struct mp3entry *ub_id3 = id3_get(UNBUFFERED_ID3);
1079 track_ridx = track_widx; 1151
1080 ci.filesize = CUR_TI->filesize; 1152 if (offset > 0 && track_list_user_current(offset - 1))
1081 ci.id3 = thistrack_id3; 1153 {
1082 ci.taginfo_ready = &CUR_TI->taginfo_ready; 1154 /* Try the unbuffered id3 since we're moving forward */
1083 ci.curpos = 0; 1155 if (ub_id3->path[0] != '\0')
1084 return codec_load(-1, id3->codectype); 1156 {
1157 copy_mp3entry(id3, ub_id3);
1158 return true;
1159 }
1160 }
1085 } 1161 }
1086 else 1162 else if (bufreadid3(info->id3_hid, id3))
1087 { 1163 {
1088 /* If we already have another track than this one buffered */ 1164 return true;
1089 if (track_widx != track_ridx) 1165 }
1090 {
1091 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1092
1093 id3 = bufgetid3(tracks[track_widx].id3_hid);
1094 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1095 1166
1096 /* If the previous codec is the same as this one and the current 1167 /* We didn't find the ID3 metadata, so we fill it with the little info we
1097 * one is the correct one, there is no need to put another copy of 1168 have and return that */
1098 * it on the file buffer */
1099 if (id3 && prev_id3)
1100 {
1101 int codt = get_codec_base_type(id3->codectype);
1102 int prev_codt = get_codec_base_type(prev_id3->codectype);
1103 int cod_loaded = get_codec_base_type(codec_loaded());
1104 1169
1105 if (codt == prev_codt && codt == cod_loaded) 1170 char path[MAX_PATH+1];
1106 { 1171 if (playlist_peek(offset, path, sizeof (path)))
1107 logf("Reusing prev. codec"); 1172 {
1108 return true; 1173#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
1109 } 1174 /* Try to get it from the database */
1110 } 1175 if (!tagcache_fill_tags(id3, path))
1176#endif
1177 {
1178 /* By now, filename is the only source of info */
1179 fill_metadata_from_path(id3, path);
1111 } 1180 }
1181
1182 return true;
1112 } 1183 }
1113 1184
1114 codec_get_full_path(codec_path, codec_fn); 1185 wipe_mp3entry(id3);
1115 1186
1116 hid = tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL); 1187 return false;
1188}
1117 1189
1118 /* not an error if codec load it supported, will load it from disk 1190/* Get a resume rewind adjusted offset from the ID3 */
1119 * application builds don't support it 1191unsigned long resume_rewind_adjusted_offset(const struct mp3entry *id3)
1120 */ 1192{
1121 if (hid < 0 && hid != ERR_UNSUPPORTED_TYPE) 1193 unsigned long offset = id3->offset;
1122 return false; 1194 size_t resume_rewind = global_settings.resume_rewind *
1195 id3->bitrate * (1000/8);
1123 1196
1124 if (hid >= 0) 1197 if (offset < resume_rewind)
1125 logf("Loaded codec"); 1198 offset = 0;
1126 else 1199 else
1127 logf("Buffering codec unsupported, load later from disk"); 1200 offset -= resume_rewind;
1128 1201
1129 return true; 1202 return offset;
1130} 1203}
1131 1204
1132/* Load metadata for the next track (with bufopen). The rest of the track 1205/* Get the codec into ram and initialize it - keep it if it's ready */
1133 loading will be handled by audio_finish_load_track once the metadata has been 1206static bool audio_init_codec(struct track_info *track_info,
1134 actually loaded by the buffering thread. */ 1207 struct mp3entry *track_id3)
1135static bool audio_load_track(size_t offset, bool start_play)
1136{ 1208{
1137 char name_buf[MAX_PATH + 1]; 1209 int codt_loaded = get_audio_base_codec_type(codec_loaded());
1138 const char *trackname; 1210 int hid = ERR_HANDLE_NOT_FOUND;
1139 int fd = -1;
1140 1211
1141 if (track_load_started) { 1212 if (codt_loaded != AFMT_UNKNOWN)
1142 /* There is already a track load in progress, so track_widx hasn't been 1213 {
1143 incremented yet. Loading another track would overwrite the one that 1214 int codt = get_audio_base_codec_type(track_id3->codectype);
1144 hasn't finished loading. */ 1215
1145 logf("audio_load_track(): a track load is already in progress"); 1216 if (codt == codt_loaded)
1146 return false; 1217 {
1218 /* Codec is the same base type */
1219 logf("Reusing prev. codec: %d", track_id3->codectype);
1220#ifdef HAVE_CODEC_BUFFERING
1221 /* Close any buffered codec (we could have skipped directly to a
1222 format transistion that is the same format as the current track
1223 and the buffered one is no longer needed) */
1224 track_info_close_handle(&track_info->codec_hid);
1225#endif
1226 return true;
1227 }
1228 else
1229 {
1230 /* New codec - first make sure the old one's gone */
1231 logf("Removing prev. codec: %d", codt_loaded);
1232 codec_unload();
1233 }
1147 } 1234 }
1148 1235
1149 start_play_g = start_play; /* will be read by audio_finish_load_track */ 1236 logf("New codec: %d/%d", track_id3->codectype, codec_loaded());
1150 1237
1151 /* Stop buffer filling if there is no free track entries. 1238#ifdef HAVE_CODEC_BUFFERING
1152 Don't fill up the last track entry (we wan't to store next track 1239 /* Codec thread will close the handle even if it fails and will load from
1153 metadata there). */ 1240 storage if hid is not valid or the buffer load fails */
1154 if (!audio_free_track_count()) 1241 hid = track_info->codec_hid;
1155 { 1242 track_info->codec_hid = ERR_HANDLE_NOT_FOUND;
1156 logf("No free tracks"); 1243#endif
1244
1245 return codec_load(hid, track_id3->codectype);
1246 (void)track_info; /* When codec buffering isn't supported */
1247}
1248
1249/* Start the codec for the current track scheduled to be decoded */
1250static bool audio_start_codec(bool auto_skip)
1251{
1252 struct track_info *info = track_list_current(0);
1253 struct mp3entry *cur_id3 = valid_mp3entry(bufgetid3(info->id3_hid));
1254
1255 if (!cur_id3)
1157 return false; 1256 return false;
1158 }
1159 1257
1160 last_peek_offset++; 1258 buf_pin_handle(info->id3_hid, true);
1161 tracks[track_widx].taginfo_ready = false;
1162 1259
1163 logf("Buffering track: r%d/w%d", track_ridx, track_widx); 1260 if (!audio_init_codec(info, cur_id3))
1164 /* Get track name from current playlist read position. */
1165 while ((trackname = playlist_peek(last_peek_offset, name_buf,
1166 sizeof(name_buf))) != NULL)
1167 { 1261 {
1168 /* Handle broken playlists. */ 1262 buf_pin_handle(info->id3_hid, false);
1169 fd = open(trackname, O_RDONLY); 1263 return false;
1170 if (fd < 0)
1171 {
1172 logf("Open failed");
1173 /* Skip invalid entry from playlist. */
1174 playlist_skip_entry(NULL, last_peek_offset);
1175 }
1176 else
1177 break;
1178 } 1264 }
1179 1265
1180 if (!trackname) 1266#ifdef HAVE_TAGCACHE
1267 bool autoresume_enable = global_settings.autoresume_enable;
1268
1269 if (autoresume_enable && !cur_id3->offset)
1181 { 1270 {
1182 logf("End-of-playlist"); 1271 /* Resume all manually selected tracks */
1183 memset(&unbuffered_id3, 0, sizeof(struct mp3entry)); 1272 bool resume = !auto_skip;
1184 filling = STATE_END_OF_PLAYLIST; 1273
1274 /* Send the "buffer" event to obtain the resume position for the codec */
1275 send_event(PLAYBACK_EVENT_TRACK_BUFFER, cur_id3);
1185 1276
1186 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0) 1277 if (!resume)
1187 { 1278 {
1188 /* Stop playback if no valid track was found. */ 1279 /* Automatic skip - do further tests to see if we should just
1189 audio_stop_playback(); 1280 ignore any autoresume position */
1281 int autoresume_automatic = global_settings.autoresume_automatic;
1282
1283 switch (autoresume_automatic)
1284 {
1285 case AUTORESUME_NEXTTRACK_ALWAYS:
1286 /* Just resume unconditionally */
1287 resume = true;
1288 break;
1289 case AUTORESUME_NEXTTRACK_NEVER:
1290 /* Force-rewind it */
1291 break;
1292 default:
1293 /* Not "never resume" - pass resume filter? */
1294 resume = autoresumable(cur_id3);
1295 }
1190 } 1296 }
1191 1297
1192 return false; 1298 if (!resume)
1299 cur_id3->offset = 0;
1300
1301 logf("%s: Set offset for %s to %lX\n", __func__,
1302 cur_id3->title, cur_id3->offset);
1193 } 1303 }
1304#endif /* HAVE_TAGCACHE */
1194 1305
1195 tracks[track_widx].filesize = filesize(fd); 1306 /* Rewind the required amount - if an autoresume was done, this also rewinds
1307 that by the setting's amount
1196 1308
1197 if (offset > tracks[track_widx].filesize) 1309 It would be best to have bookkeeping about whether or not the track
1198 offset = 0; 1310 sounded or not since skipping to it or else skipping to it while paused
1311 and back again will cause accumulation of silent rewinds - that's not
1312 our job to track directly nor could it be in any reasonable way
1313 */
1314 cur_id3->offset = resume_rewind_adjusted_offset(cur_id3);
1315
1316 /* Update the codec API with the metadata and track info */
1317 id3_write(CODEC_ID3, cur_id3);
1199 1318
1200 /* Set default values */ 1319 ci.audio_hid = info->audio_hid;
1201 if (start_play) 1320 ci.filesize = info->filesize;
1321 buf_set_base_handle(info->audio_hid);
1322
1323 /* All required data is now available for the codec */
1324 codec_go();
1325
1326#ifdef HAVE_TAGCACHE
1327 if (!autoresume_enable || cur_id3->offset)
1328#endif
1202 { 1329 {
1203 buf_set_watermark(filebuflen/2); 1330 /* Send the "buffer" event now */
1204 dsp_configure(ci.dsp, DSP_RESET, 0); 1331 send_event(PLAYBACK_EVENT_TRACK_BUFFER, cur_id3);
1205 playlist_update_resume_info(audio_current_track());
1206 } 1332 }
1207 1333
1208 /* Get track metadata if we don't already have it. */ 1334 buf_pin_handle(info->id3_hid, false);
1209 if (tracks[track_widx].id3_hid < 0) 1335 return true;
1336
1337 (void)auto_skip; /* ifndef HAVE_TAGCACHE */
1338}
1339
1340
1341/** --- Audio thread --- **/
1342
1343/* Load and parse a cuesheet for the file - returns false if the buffer
1344 is full */
1345static bool audio_load_cuesheet(struct track_info *info,
1346 struct mp3entry *track_id3)
1347{
1348 struct cuesheet *cue = get_current_cuesheet();
1349 track_id3->cuesheet = NULL;
1350
1351 if (cue && info->cuesheet_hid == ERR_HANDLE_NOT_FOUND)
1210 { 1352 {
1211 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL); 1353 /* If error other than a full buffer, then mark it "unsupported" to
1354 avoid reloading attempt */
1355 int hid = ERR_UNSUPPORTED_TYPE;
1356 char cuepath[MAX_PATH];
1212 1357
1213 if (tracks[track_widx].id3_hid < 0) 1358#ifdef HAVE_IO_PRIORITY
1359 buf_back_off_storage(true);
1360#endif
1361 if (look_for_cuesheet_file(track_id3->path, cuepath))
1214 { 1362 {
1215 /* Buffer is full. */ 1363 hid = bufalloc(NULL, sizeof (struct cuesheet), TYPE_CUESHEET);
1216 get_metadata(&unbuffered_id3, fd, trackname);
1217 last_peek_offset--;
1218 close(fd);
1219 logf("buffer is full for now (get metadata)");
1220 filling = STATE_FULL;
1221 return false;
1222 }
1223 1364
1224 if (track_widx == track_ridx) 1365 if (hid >= 0)
1225 { 1366 {
1226 /* TODO: Superfluos buffering call? */ 1367 void *cuesheet = NULL;
1227 buf_request_buffer_handle(tracks[track_widx].id3_hid); 1368 bufgetdata(hid, sizeof (struct cuesheet), &cuesheet);
1228 if (bufreadid3(tracks[track_widx].id3_hid, thistrack_id3)) 1369
1229 { 1370 if (parse_cuesheet(cuepath, (struct cuesheet *)cuesheet))
1230 thistrack_id3->offset = offset; 1371 {
1231 logf("audio_load_track: set offset for %s to %lX\n", 1372 /* Indicate cuesheet is present (while track remains
1232 thistrack_id3->title, 1373 buffered) */
1233 offset); 1374 track_id3->cuesheet = cue;
1375 }
1376 else
1377 {
1378 bufclose(hid);
1379 hid = ERR_UNSUPPORTED_TYPE;
1380 }
1234 } 1381 }
1235 else
1236 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1237 } 1382 }
1238 1383
1239 if (start_play) 1384#ifdef HAVE_IO_PRIORITY
1385 buf_back_off_storage(false);
1386#endif
1387 if (hid == ERR_BUFFER_FULL)
1240 { 1388 {
1241 playlist_update_resume_info(audio_current_track()); 1389 logf("buffer is full for now (%s)", __func__);
1390 return false;
1391 }
1392 else
1393 {
1394 if (hid < 0)
1395 logf("Cuesheet loading failed");
1396
1397 info->cuesheet_hid = hid;
1242 } 1398 }
1243 } 1399 }
1244 1400
1245 close(fd);
1246 track_load_started = true; /* Remember that we've started loading a track */
1247 return true; 1401 return true;
1248} 1402}
1249 1403
1250#ifdef HAVE_ALBUMART 1404#ifdef HAVE_ALBUMART
1251/* Load any album art for the file */ 1405/* Load any album art for the file - returns false if the buffer is full */
1252static void audio_load_albumart(struct mp3entry *track_id3) 1406static bool audio_load_albumart(struct track_info *info,
1407 struct mp3entry *track_id3)
1253{ 1408{
1254 int i; 1409 int i;
1255
1256 FOREACH_ALBUMART(i) 1410 FOREACH_ALBUMART(i)
1257 { 1411 {
1258 struct bufopen_bitmap_data user_data; 1412 struct bufopen_bitmap_data user_data;
1259 int hid = ERR_HANDLE_NOT_FOUND; 1413 int *aa_hid = &info->aa_hid[i];
1414 int hid = ERR_UNSUPPORTED_TYPE;
1260 1415
1261 /* albumart_slots may change during a yield of bufopen, 1416 /* albumart_slots may change during a yield of bufopen,
1262 * but that's no problem */ 1417 * but that's no problem */
1263 if (tracks[track_widx].aa_hid[i] >= 0 || !albumart_slots[i].used) 1418 if (*aa_hid >= 0 || *aa_hid == ERR_UNSUPPORTED_TYPE ||
1419 !albumart_slots[i].used)
1264 continue; 1420 continue;
1265 1421
1266 memset(&user_data, 0, sizeof(user_data)); 1422 memset(&user_data, 0, sizeof(user_data));
1267 user_data.dim = &(albumart_slots[i].dim); 1423 user_data.dim = &albumart_slots[i].dim;
1268 1424
1269 /* we can only decode jpeg for embedded AA */ 1425#ifdef HAVE_IO_PRIORITY
1426 buf_back_off_storage(true);
1427#endif
1428
1429 /* We can only decode jpeg for embedded AA */
1270 if (track_id3->embed_albumart && track_id3->albumart.type == AA_TYPE_JPG) 1430 if (track_id3->embed_albumart && track_id3->albumart.type == AA_TYPE_JPG)
1271 { 1431 {
1272 user_data.embedded_albumart = &(track_id3->albumart); 1432 user_data.embedded_albumart = &track_id3->albumart;
1273 hid = bufopen(track_id3->path, 0, TYPE_BITMAP, &user_data); 1433 hid = bufopen(track_id3->path, 0, TYPE_BITMAP, &user_data);
1274 } 1434 }
1275 1435
1276 if (hid < 0 && hid != ERR_BUFFER_FULL) 1436 if (hid < 0 && hid != ERR_BUFFER_FULL)
1277 { 1437 {
1278 /* no embedded AA or it couldn't be loaded, try other sources */ 1438 /* No embedded AA or it couldn't be loaded - try other sources */
1279 char path[MAX_PATH]; 1439 char path[MAX_PATH];
1280 1440
1281 if (find_albumart(track_id3, path, sizeof(path), 1441 if (find_albumart(track_id3, path, sizeof(path),
1282 &(albumart_slots[i].dim))) 1442 &albumart_slots[i].dim))
1283 { 1443 {
1284 user_data.embedded_albumart = NULL; 1444 user_data.embedded_albumart = NULL;
1285 hid = bufopen(path, 0, TYPE_BITMAP, &user_data); 1445 hid = bufopen(path, 0, TYPE_BITMAP, &user_data);
1286 } 1446 }
1287 } 1447 }
1288 1448
1449#ifdef HAVE_IO_PRIORITY
1450 buf_back_off_storage(false);
1451#endif
1289 if (hid == ERR_BUFFER_FULL) 1452 if (hid == ERR_BUFFER_FULL)
1290 { 1453 {
1291 filling = STATE_FULL; 1454 logf("buffer is full for now (%s)", __func__);
1292 logf("buffer is full for now (get album art)"); 1455 return false;
1293 } 1456 }
1294 else if (hid < 0) 1457 else
1295 { 1458 {
1296 logf("Album art loading failed"); 1459 /* If error other than a full buffer, then mark it "unsupported"
1297 } 1460 to avoid reloading attempt */
1461 if (hid < 0)
1462 {
1463 logf("Album art loading failed");
1464 hid = ERR_UNSUPPORTED_TYPE;
1465 }
1298 1466
1299 tracks[track_widx].aa_hid[i] = hid; 1467 *aa_hid = hid;
1468 }
1300 } 1469 }
1470
1471 return true;
1301} 1472}
1302#endif 1473#endif /* HAVE_ALBUMART */
1303 1474
1304/* Second part of the track loading: We now have the metadata available, so we 1475#ifdef HAVE_CODEC_BUFFERING
1305 can load the codec, the album art and finally the audio data. 1476/* Load a codec for the file onto the buffer - assumes we're working from the
1306 This is called on the audio thread after the buffering thread calls the 1477 currently loading track - not called for the current track */
1307 buffering_handle_finished_callback callback. */ 1478static bool audio_buffer_codec(struct track_info *track_info,
1308static void audio_finish_load_track(void) 1479 struct mp3entry *track_id3)
1309{ 1480{
1310 size_t file_offset = 0; 1481 /* This will not be the current track -> it cannot be the first and the
1311 size_t offset = 0; 1482 current track cannot be ahead of buffering -> there is a previous
1312 bool start_play = start_play_g; 1483 track entry which is either current or ahead of the current */
1484 struct track_info *prev_info = track_list_last(-1);
1485 struct mp3entry *prev_id3 = bufgetid3(prev_info->id3_hid);
1313 1486
1314 track_load_started = false; 1487 /* If the previous codec is the same as this one, there is no need to
1488 put another copy of it on the file buffer (in other words, only
1489 buffer codecs at format transitions) */
1490 if (prev_id3)
1491 {
1492 int codt = get_audio_base_codec_type(track_id3->codectype);
1493 int prev_codt = get_audio_base_codec_type(prev_id3->codectype);
1315 1494
1316 if (tracks[track_widx].id3_hid < 0) { 1495 if (codt == prev_codt)
1317 logf("No metadata"); 1496 {
1318 return; 1497 logf("Reusing prev. codec: %d", prev_id3->codectype);
1498 return true;
1499 }
1319 } 1500 }
1501 /* else just load it (harmless) */
1320 1502
1321 struct mp3entry *track_id3; 1503 /* Load the codec onto the buffer if possible */
1504 const char *codec_fn = get_codec_filename(track_id3->codectype);
1505 if (!codec_fn)
1506 return false;
1322 1507
1323 if (track_widx == track_ridx) 1508 char codec_path[MAX_PATH+1]; /* Full path to codec */
1324 track_id3 = thistrack_id3; 1509 codec_get_full_path(codec_path, codec_fn);
1325 else 1510
1326 track_id3 = bufgetid3(tracks[track_widx].id3_hid); 1511 track_info->codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1327 1512
1328 if (track_id3->length == 0 && track_id3->filesize == 0) 1513 if (track_info->codec_hid >= 0)
1329 { 1514 {
1330 logf("audio_finish_load_track: invalid metadata"); 1515 logf("Buffered codec: %d", afmt);
1516 return true;
1517 }
1331 1518
1332 /* Invalid metadata */ 1519 return false;
1333 bufclose(tracks[track_widx].id3_hid); 1520}
1334 tracks[track_widx].id3_hid = -1; 1521#endif /* HAVE_CODEC_BUFFERING */
1335 1522
1336 /* Skip invalid entry from playlist. */ 1523/* Load metadata for the next track (with bufopen). The rest of the track
1337 playlist_skip_entry(NULL, last_peek_offset--); 1524 loading will be handled by audio_finish_load_track once the metadata has
1525 been actually loaded by the buffering thread.
1338 1526
1339 /* load next track */ 1527 Each track is arranged in the buffer as follows:
1340 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play); 1528 <id3|[cuesheet|][album art|][codec|]audio>
1341 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1342 1529
1343 return; 1530 The next will not be loaded until the previous succeeds if the buffer was
1344 } 1531 full at the time. To put any metadata after audio would make those handles
1345 /* Try to load a cuesheet for the track */ 1532 unmovable.
1346 if (curr_cue) 1533*/
1534static int audio_load_track(void)
1535{
1536 if (in_progress_id3_hid >= 0)
1347 { 1537 {
1348 char cuepath[MAX_PATH]; 1538 /* There must be an info pointer if the in-progress id3 is even there */
1349 if (look_for_cuesheet_file(track_id3->path, cuepath)) 1539 struct track_info *info = track_list_last(0);
1540
1541 if (info->id3_hid == in_progress_id3_hid)
1350 { 1542 {
1351 void *temp; 1543 if (filling == STATE_FILLING)
1352 tracks[track_widx].cuesheet_hid =
1353 bufalloc(NULL, sizeof(struct cuesheet), TYPE_CUESHEET);
1354 if (tracks[track_widx].cuesheet_hid >= 0)
1355 { 1544 {
1356 bufgetdata(tracks[track_widx].cuesheet_hid, 1545 /* Haven't finished the metadata but the notification is
1357 sizeof(struct cuesheet), &temp); 1546 anticipated to come soon */
1358 struct cuesheet *cuesheet = (struct cuesheet*)temp; 1547 logf("%s(): in progress ok: %d". __func__, info->id3_hid);
1359 if (!parse_cuesheet(cuepath, cuesheet)) 1548 return LOAD_TRACK_OK;
1360 { 1549 }
1361 bufclose(tracks[track_widx].cuesheet_hid); 1550 else if (filling == STATE_FULL)
1362 track_id3->cuesheet = NULL; 1551 {
1363 } 1552 /* Buffer was full trying to complete the load after the
1553 metadata finished, so attempt to continue - older handles
1554 should have been cleared already */
1555 logf("%s(): finishing load: %d". __func__, info->id3_hid);
1556 filling = STATE_FILLING;
1557 buffer_event_finished_callback(&info->id3_hid);
1558 return LOAD_TRACK_OK;
1364 } 1559 }
1365 } 1560 }
1561
1562 /* Some old, stray buffering message */
1563 logf("%s(): already in progress: %d". __func__, info->id3_hid);
1564 return LOAD_TRACK_ERR_BUSY;
1366 } 1565 }
1367 1566
1368#ifdef HAVE_ALBUMART 1567 filling = STATE_FILLING;
1369 audio_load_albumart(track_id3); 1568
1370#endif 1569 struct track_info *info = track_list_alloc_track();
1570 if (info == NULL)
1571 {
1572 /* List is full so stop buffering tracks - however, attempt to obtain
1573 metadata as the unbuffered id3 */
1574 logf("No free tracks");
1575 filling = STATE_FULL;
1576 }
1577
1578 playlist_peek_offset++;
1579
1580 logf("Buffering track: s%u/c%u/e%u/p%d",
1581 track_list.start, track_list.current, track_list.end,
1582 playlist_peek_offset);
1583
1584 /* Get track name from current playlist read position */
1585 int fd = -1;
1586 char name_buf[MAX_PATH + 1];
1587 const char *trackname;
1371 1588
1372 /* Load the codec. */ 1589 while (1)
1373 if (!audio_loadcodec(start_play))
1374 { 1590 {
1375 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL) 1591
1592 trackname = playlist_peek(playlist_peek_offset, name_buf,
1593 sizeof (name_buf));
1594
1595 if (!trackname)
1596 break;
1597
1598 /* Test for broken playlists by probing for the files */
1599 fd = open(trackname, O_RDONLY);
1600 if (fd >= 0)
1601 break;
1602
1603 logf("Open failed");
1604 /* Skip invalid entry from playlist */
1605 playlist_skip_entry(NULL, playlist_peek_offset);
1606
1607 /* Sync the playlist if it isn't finished */
1608 if (playlist_peek(playlist_peek_offset, NULL, 0))
1609 playlist_next(0);
1610 }
1611
1612 if (!trackname)
1613 {
1614 /* No track - exhausted the playlist entries */
1615 logf("End-of-playlist");
1616 id3_write_locked(UNBUFFERED_ID3, NULL);
1617
1618 if (filling != STATE_FULL)
1619 track_list_unalloc_track(); /* Free this entry */
1620
1621 playlist_peek_offset--; /* Maintain at last index */
1622
1623 /* We can end up here after the real last track signals its completion
1624 and miss the transition to STATE_FINISHED esp. if dropping the last
1625 songs of a playlist late in their load (2nd stage) */
1626 info = track_list_last(0);
1627
1628 if (info && buf_handle_remaining(info->audio_hid) == 0)
1629 filling_is_finished();
1630 else
1631 filling = STATE_END_OF_PLAYLIST;
1632
1633 return LOAD_TRACK_ERR_NO_MORE;
1634 }
1635
1636 /* Successfully opened the file - get track metadata */
1637 if (filling == STATE_FULL ||
1638 (info->id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL)) < 0)
1639 {
1640 /* Buffer or track list is full */
1641 struct mp3entry *ub_id3;
1642
1643 playlist_peek_offset--;
1644
1645 /* Load the metadata for the first unbuffered track */
1646 ub_id3 = id3_get(UNBUFFERED_ID3);
1647 id3_mutex_lock();
1648 get_metadata(ub_id3, fd, trackname);
1649 id3_mutex_unlock();
1650
1651 if (filling != STATE_FULL)
1376 { 1652 {
1377 /* No space for codec on buffer, not an error */ 1653 track_list_unalloc_track();
1378 filling = STATE_FULL; 1654 filling = STATE_FULL;
1379 return;
1380 } 1655 }
1381 1656
1382 /* This is an error condition, either no codec was found, or reading 1657 logf("%s: buffer is full for now (%u tracks)", __func__,
1383 * the codec file failed part way through, either way, skip the track */ 1658 track_list_count());
1384 /* FIXME: We should not use splashf from audio thread! */ 1659 }
1385 splashf(HZ*2, "No codec for: %s", track_id3->path); 1660 else
1386 /* Skip invalid entry from playlist. */ 1661 {
1387 playlist_skip_entry(NULL, last_peek_offset); 1662 /* Successful load initiation */
1388 return; 1663 info->filesize = filesize(fd);
1664 in_progress_id3_hid = info->id3_hid; /* Remember what's in-progress */
1389 } 1665 }
1390 1666
1391 track_id3->elapsed = 0; 1667 close(fd);
1392 offset = track_id3->offset; 1668 return LOAD_TRACK_OK;
1393 size_t resume_rewind = (global_settings.resume_rewind * 1669}
1394 track_id3->bitrate * 1000) / 8;
1395 1670
1396 if (offset < resume_rewind) 1671/* Second part of the track loading: We now have the metadata available, so we
1672 can load the codec, the album art and finally the audio data.
1673 This is called on the audio thread after the buffering thread calls the
1674 buffering_handle_finished_callback callback. */
1675static int audio_finish_load_track(struct track_info *info)
1676{
1677 int trackstat = LOAD_TRACK_OK;
1678
1679 if (info->id3_hid != in_progress_id3_hid)
1397 { 1680 {
1398 offset = 0; 1681 /* We must not be here if not! */
1682 logf("%s: wrong track %d/%d", __func__, info->id3_hid,
1683 in_progress_id3_hid);
1684 return LOAD_TRACK_ERR_BUSY;
1399 } 1685 }
1400 else 1686
1687 /* The current track for decoding (there is always one if the list is
1688 populated) */
1689 struct track_info *cur_info = track_list_current(0);
1690 struct mp3entry *track_id3 = valid_mp3entry(bufgetid3(info->id3_hid));
1691
1692 if (!track_id3)
1401 { 1693 {
1402 offset -= resume_rewind; 1694 /* This is an error condition. Track cannot be played without valid
1695 metadata; skip the track. */
1696 logf("No metadata for: %s", track_id3->path);
1697 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1698 goto audio_finish_load_track_exit;
1699 }
1700
1701 /* Try to load a cuesheet for the track */
1702 if (!audio_load_cuesheet(info, track_id3))
1703 {
1704 /* No space for cuesheet on buffer, not an error */
1705 filling = STATE_FULL;
1706 goto audio_finish_load_track_exit;
1403 } 1707 }
1404 1708
1405 enum data_type type = TYPE_PACKET_AUDIO; 1709#ifdef HAVE_ALBUMART
1710 /* Try to load album art for the track */
1711 if (!audio_load_albumart(info, track_id3))
1712 {
1713 /* No space for album art on buffer, not an error */
1714 filling = STATE_FULL;
1715 goto audio_finish_load_track_exit;
1716 }
1717#endif
1406 1718
1407 switch (track_id3->codectype) { 1719#ifdef HAVE_CODEC_BUFFERING
1408 case AFMT_MPA_L1: 1720 /* Try to buffer a codec for the track */
1409 case AFMT_MPA_L2: 1721 if (info != cur_info && !audio_buffer_codec(info, track_id3))
1410 case AFMT_MPA_L3: 1722 {
1411 if (offset > 0) { 1723 if (info->codec_hid == ERR_BUFFER_FULL)
1412 file_offset = offset; 1724 {
1725 /* No space for codec on buffer, not an error */
1726 filling = STATE_FULL;
1727 logf("buffer is full for now (%s)", __func__);
1413 } 1728 }
1414 break; 1729 else
1415 1730 {
1416 case AFMT_WAVPACK: 1731 /* This is an error condition, either no codec was found, or
1417 if (offset > 0) { 1732 reading the codec file failed part way through, either way,
1418 file_offset = offset; 1733 skip the track */
1419 track_id3->elapsed = track_id3->length / 2; 1734 logf("No codec for: %s", track_id3->path);
1735 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1420 } 1736 }
1421 break;
1422 1737
1423 case AFMT_NSF: 1738 goto audio_finish_load_track_exit;
1424 case AFMT_SPC:
1425 case AFMT_SID:
1426 logf("Loading atomic %d",track_id3->codectype);
1427 type = TYPE_ATOMIC_AUDIO;
1428 break;
1429
1430 default:
1431 /* no special treatment needed */
1432 break;
1433 } 1739 }
1740#endif /* HAVE_CODEC_BUFFERING */
1434 1741
1435 track_id3->offset = offset; 1742 /** Finally, load the audio **/
1743 size_t file_offset = 0;
1744 track_id3->elapsed = 0;
1745
1746 if (track_id3->offset >= info->filesize)
1747 track_id3->offset = 0;
1748
1749 logf("%s: set offset for %s to %lu\n", __func__,
1750 id3->title, (unsigned long)offset);
1751
1752 /* Adjust for resume rewind so we know what to buffer - starting the codec
1753 calls it again, so we don't save it (and they shouldn't accumulate) */
1754 size_t offset = resume_rewind_adjusted_offset(track_id3);
1755
1756 enum data_type audiotype = get_audio_base_data_type(track_id3->codectype);
1757
1758 if (audiotype == TYPE_ATOMIC_AUDIO)
1759 logf("Loading atomic %d", track_id3->codectype);
1760
1761 if (format_buffers_with_offset(track_id3->codectype))
1762 {
1763 /* This format can begin buffering from any point */
1764 file_offset = offset;
1765 }
1436 1766
1437 logf("load track: %s", track_id3->path); 1767 logf("load track: %s", track_id3->path);
1438 1768
1439 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE) 1769 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1770 {
1771 /* We can buffer later in the file, adjust the hunt-and-peck margin */
1440 file_offset -= AUDIO_REBUFFER_GUESS_SIZE; 1772 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1441 else if (track_id3->first_frame_offset) 1773 }
1442 file_offset = track_id3->first_frame_offset;
1443 else 1774 else
1444 file_offset = 0; 1775 {
1776 /* No offset given or it is very minimal - begin at the first frame
1777 according to the metadata */
1778 file_offset = track_id3->first_frame_offset;
1779 }
1445 1780
1446 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type, 1781 int hid = bufopen(track_id3->path, file_offset, audiotype, NULL);
1447 NULL);
1448 1782
1449 /* No space left, not an error */ 1783 if (hid >= 0)
1450 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1451 { 1784 {
1452 filling = STATE_FULL; 1785 info->audio_hid = hid;
1453 logf("buffer is full for now (load audio)"); 1786
1454 return; 1787 if (info == cur_info)
1788 {
1789 /* This is the current track to decode - should be started now */
1790 trackstat = LOAD_TRACK_READY;
1791 }
1455 } 1792 }
1456 else if (tracks[track_widx].audio_hid < 0) 1793 else
1457 { 1794 {
1458 /* another error, do not continue either */ 1795 /* Buffer could be full but not properly so if this is the only
1459 logf("Could not add audio data handle"); 1796 track! */
1460 return; 1797 if (hid == ERR_BUFFER_FULL && audio_track_count() > 1)
1798 {
1799 filling = STATE_FULL;
1800 logf("Buffer is full for now (%s)", __func__);
1801 }
1802 else
1803 {
1804 /* Nothing to play if no audio handle - skip this */
1805 logf("Could not add audio data handle");
1806 trackstat = LOAD_TRACK_ERR_FINISH_FAILED;
1807 }
1461 } 1808 }
1462 1809
1463 /* All required data is now available for the codec -- unless the 1810audio_finish_load_track_exit:
1464 autoresume feature is in effect. In the latter case, the codec 1811 if (trackstat < LOAD_TRACK_OK)
1465 must wait until after PLAYBACK_EVENT_TRACK_BUFFER, which may
1466 generate a resume position. */
1467#ifdef HAVE_TAGCACHE
1468 if (!global_settings.autoresume_enable || offset)
1469#endif
1470 tracks[track_widx].taginfo_ready = true;
1471
1472 if (start_play)
1473 { 1812 {
1474 ci.curpos=file_offset; 1813 playlist_skip_entry(NULL, playlist_peek_offset);
1475 buf_request_buffer_handle(tracks[track_widx].audio_hid); 1814 track_info_close(info);
1476 } 1815 track_list_unalloc_track();
1477 1816
1478 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3); 1817 if (playlist_peek(playlist_peek_offset, NULL, 0))
1818 playlist_next(0);
1479 1819
1480#ifdef HAVE_TAGCACHE 1820 playlist_peek_offset--;
1481 /* In case the autoresume feature has been enabled, finally all 1821 }
1482 required data is available for the codec. */
1483 if (global_settings.autoresume_enable && !offset)
1484 tracks[track_widx].taginfo_ready = true;
1485#endif
1486
1487 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1488 1822
1489 /* load next track */ 1823 if (filling != STATE_FULL)
1490 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER"); 1824 {
1491 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0); 1825 /* Load next track - error or not */
1826 in_progress_id3_hid = ERR_HANDLE_NOT_FOUND;
1827 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1828 audio_queue_post(Q_AUDIO_FILL_BUFFER, 0);
1829 }
1830 else
1831 {
1832 /* Full */
1833 trackstat = LOAD_TRACK_ERR_FINISH_FULL;
1834 }
1492 1835
1493 return; 1836 return trackstat;
1494} 1837}
1495 1838
1496static void audio_fill_file_buffer(bool start_play, size_t offset) 1839/* Start a new track load */
1840static int audio_fill_file_buffer(void)
1497{ 1841{
1498 trigger_cpu_boost(); 1842 if (play_status == PLAY_STOPPED)
1843 return LOAD_TRACK_ERR_FAILED;
1499 1844
1500 /* No need to rebuffer if there are track skips pending, 1845 trigger_cpu_boost();
1501 * however don't cancel buffering on skipping while filling. */
1502 if (ci.new_track != 0 && filling != STATE_FILLING)
1503 return;
1504 filling = STATE_FILLING;
1505 1846
1506 /* Must reset the buffer before use if trashed or voice only - voice 1847 /* Must reset the buffer before use if trashed or voice only - voice
1507 file size shouldn't have changed so we can go straight from 1848 file size shouldn't have changed so we can go straight from
@@ -1511,772 +1852,1848 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
1511 1852
1512 logf("Starting buffer fill"); 1853 logf("Starting buffer fill");
1513 1854
1514 if (!start_play) 1855 int trackstat = audio_load_track();
1515 audio_clear_track_entries();
1516 1856
1517 /* Save the current resume position once. */ 1857 if (trackstat >= LOAD_TRACK_OK)
1518 playlist_update_resume_info(audio_current_track()); 1858 {
1859 if (track_list_current(0) == track_list_user_current(0))
1860 playlist_next(0);
1519 1861
1520 audio_load_track(offset, start_play); 1862 if (filling == STATE_FULL && !track_list_user_current(1))
1863 {
1864 /* There are no user tracks on the buffer after this therefore
1865 this is the next track */
1866 audio_update_and_announce_next_track(id3_get(UNBUFFERED_ID3));
1867 }
1868 }
1869
1870 return trackstat;
1521} 1871}
1522 1872
1523static void audio_rebuffer(void) 1873/* Discard unwanted tracks and start refill from after the specified playlist
1874 offset */
1875static int audio_reset_and_rebuffer(
1876 enum track_clear_action action, int peek_offset)
1524{ 1877{
1525 logf("Forcing rebuffer"); 1878 logf("Forcing rebuffer: 0x%X, %d", flags, peek_offset);
1526 1879
1527 clear_track_info(CUR_TI); 1880 id3_write_locked(UNBUFFERED_ID3, NULL);
1528 1881
1529 /* Reset track pointers */ 1882 /* Remove unwanted tracks - caller must have ensured codec isn't using
1530 track_widx = track_ridx; 1883 any */
1531 audio_clear_track_entries(); 1884 track_list_clear(action);
1532 1885
1533 /* Reset a possibly interrupted track load */ 1886 /* Refill at specified position (-1 starts at index offset 0) */
1534 track_load_started = false; 1887 playlist_peek_offset = peek_offset;
1535 1888
1536 /* Fill the buffer */ 1889 /* Fill the buffer */
1537 last_peek_offset = -1; 1890 return audio_fill_file_buffer();
1538 ci.curpos = 0; 1891}
1539 1892
1540 if (!CUR_TI->taginfo_ready) 1893/* Handle buffering events
1541 memset(thistrack_id3, 0, sizeof(struct mp3entry)); 1894 (Q_AUDIO_BUFFERING) */
1895static void audio_on_buffering(int event)
1896{
1897 enum track_clear_action action;
1898 int peek_offset;
1899
1900 if (track_list_empty())
1901 return;
1902
1903 switch (event)
1904 {
1905 case BUFFER_EVENT_BUFFER_LOW:
1906 if (filling != STATE_FULL && filling != STATE_END_OF_PLAYLIST)
1907 return; /* Should be nothing left to fill */
1908
1909 /* Clear old tracks and continue buffering where it left off */
1910 action = TRACK_LIST_KEEP_NEW;
1911 peek_offset = playlist_peek_offset;
1912 break;
1542 1913
1543 audio_fill_file_buffer(false, 0); 1914 case BUFFER_EVENT_REBUFFER:
1915 /* Remove all but the currently decoding track and redo buffering
1916 after that */
1917 action = TRACK_LIST_KEEP_CURRENT;
1918 peek_offset = (skip_pending == TRACK_SKIP_AUTO) ? 1 : 0;
1919 break;
1920
1921 default:
1922 return;
1923 }
1924
1925 switch (skip_pending)
1926 {
1927 case TRACK_SKIP_NONE:
1928 case TRACK_SKIP_AUTO:
1929 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
1930 audio_reset_and_rebuffer(action, peek_offset);
1931 break;
1932
1933 case TRACK_SKIP_AUTO_END_PLAYLIST:
1934 /* Already finished */
1935 break;
1936
1937 default:
1938 /* Invalid */
1939 logf("Buffering call, inv. state: %d", (int)skip_pending);
1940 }
1544} 1941}
1545 1942
1546/* Called on request from the codec to get a new track. This is the codec part 1943/* Handle starting the next track load
1547 of the track transition. */ 1944 (Q_AUDIO_FILL_BUFFER) */
1548static void audio_last_track(bool automatic) 1945static void audio_on_fill_buffer(void)
1549{ 1946{
1550 if (automatic) 1947 audio_handle_track_load_status(audio_fill_file_buffer());
1948}
1949
1950/* Handle posted load track finish event
1951 (Q_AUDIO_FINISH_LOAD_TRACK) */
1952static void audio_on_finish_load_track(int id3_hid)
1953{
1954 struct track_info *info = track_list_last(0);
1955
1956 if (!info || !buf_is_handle(id3_hid))
1957 return;
1958
1959 if (info == track_list_user_current(1))
1551 { 1960 {
1552 ci.new_track = 0; 1961 /* Just loaded the metadata right after the current position */
1553 automatic_skip = false; 1962 audio_update_and_announce_next_track(bufgetid3(info->id3_hid));
1963 }
1554 1964
1555 if (filling != STATE_ENDING) 1965 if (audio_finish_load_track(info) != LOAD_TRACK_READY)
1966 return; /* Not current track */
1967
1968 bool is_user_current = info == track_list_user_current(0);
1969
1970 if (is_user_current)
1971 {
1972 /* Copy cuesheet */
1973 buf_read_cuesheet(info->cuesheet_hid);
1974 }
1975
1976 if (audio_start_codec(automatic_skip))
1977 {
1978 if (is_user_current)
1556 { 1979 {
1557 /* Monitor remaining PCM before stopping */ 1980 /* Be sure all tagtree info is synchronized; it will be needed for the
1558 filling = STATE_ENDING; 1981 track finish event - the sync will happen when finalizing a track
1559 pcmbuf_monitor_track_change(true); 1982 change otherwise */
1560 } 1983 bool was_valid = valid_mp3entry(id3_get(PLAYING_ID3));
1561 1984
1562 codec_stop(); 1985 playing_id3_sync(info, -1);
1986
1987 if (!was_valid)
1988 {
1989 /* Playing id3 hadn't been updated yet because no valid track
1990 was yet available - treat like the first track */
1991 audio_playlist_track_change();
1992 }
1993 }
1563 } 1994 }
1564 else 1995 else
1565 { 1996 {
1997 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
1998 }
1999}
2000
2001/* Called when handles other than metadata handles have finished buffering
2002 (Q_AUDIO_HANDLE_FINISHED) */
2003static void audio_on_handle_finished(int hid)
2004{
2005 /* Right now, only audio handles should end up calling this */
2006 if (filling == STATE_END_OF_PLAYLIST)
2007 {
2008 struct track_info *info = track_list_last(0);
2009
2010 /* Really we don't know which order the handles will actually complete
2011 to zero bytes remaining since another thread is doing it - be sure
2012 it's the right one */
2013 if (info && info->audio_hid == hid)
2014 {
2015 /* This was the last track in the playlist and we now have all the
2016 data we need */
2017 filling_is_finished();
2018 }
2019 }
2020}
2021
2022/* Called to make an outstanding track skip the current track and to send the
2023 transition events */
2024static void audio_finalise_track_change(bool delayed)
2025{
2026 switch (skip_pending)
2027 {
2028 case TRACK_SKIP_NONE: /* Manual skip */
2029 break;
2030
2031 case TRACK_SKIP_AUTO:
2032 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2033 {
2034 int playlist_delta = skip_pending == TRACK_SKIP_AUTO ? 1 : 0;
2035 audio_playlist_track_finish();
2036
2037 if (!playlist_peek(playlist_delta, NULL, 0))
2038 {
2039 /* Track ended up rejected - push things ahead like the codec blew
2040 it (because it was never started and now we're here where it
2041 should have been decoding the next track by now) - next, a
2042 directory change or end of playback will most likely happen */
2043 skip_pending = TRACK_SKIP_NONE;
2044 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
2045 return;
2046 }
2047
2048 if (!playlist_delta)
2049 break;
2050
2051 playlist_peek_offset -= playlist_delta;
2052 if (playlist_next(playlist_delta) >= 0)
2053 break;
2054 /* What!? Disappear? Hopeless bleak despair */
2055 }
2056 /* Fallthrough */
2057 case TRACK_SKIP_AUTO_END_PLAYLIST:
2058 default: /* Invalid */
2059 filling = STATE_ENDED;
1566 audio_stop_playback(); 2060 audio_stop_playback();
2061 return;
2062 }
2063
2064 struct track_info *info = track_list_current(0);
2065 struct mp3entry *track_id3 = NULL;
2066
2067 id3_mutex_lock();
2068
2069 /* Update the current cuesheet if any and enabled */
2070 if (info)
2071 {
2072 buf_read_cuesheet(info->cuesheet_hid);
2073 track_id3 = bufgetid3(info->id3_hid);
2074 }
2075
2076 id3_write(PLAYING_ID3, track_id3);
2077
2078 if (delayed)
2079 {
2080 /* Delayed skip where codec is ahead of user's current track */
2081 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
2082 struct mp3entry *ply_id3 = id3_get(PLAYING_ID3);
2083 ply_id3->elapsed = ci_id3->elapsed;
2084 ply_id3->offset = ci_id3->offset;
1567 } 2085 }
2086
2087 /* The skip is technically over */
2088 skip_pending = TRACK_SKIP_NONE;
2089
2090 /* Sync the next track information */
2091 info = track_list_current(1);
2092
2093 id3_write(NEXTTRACK_ID3, info ? bufgetid3(info->id3_hid) :
2094 id3_get(UNBUFFERED_ID3));
2095
2096 id3_mutex_unlock();
2097
2098 audio_playlist_track_change();
1568} 2099}
1569 2100
1570static void audio_check_new_track(void) 2101/* Actually begin a transition and take care of the codec change - may complete
2102 it now or ask pcmbuf for notification depending on the type and what pcmbuf
2103 has to say */
2104static void audio_begin_track_change(bool auto_skip, int trackstat)
1571{ 2105{
1572 int track_count; 2106 /* Even if the new track is bad, the old track must be finished off */
1573 int old_track_ridx; 2107 bool finalised = pcmbuf_start_track_change(auto_skip);
1574 int i, idx;
1575 bool forward;
1576 struct mp3entry *temp;
1577 2108
1578 if (ci.new_track == 0) 2109 if (finalised)
1579 { 2110 {
1580 ci.new_track++; 2111 /* pcmbuf says that the transition happens now - complete it */
1581 automatic_skip = true; 2112 audio_finalise_track_change(false);
2113
2114 if (play_status == PLAY_STOPPED)
2115 return; /* Stopped us */
2116 }
2117
2118 if (!auto_skip)
2119 audio_clear_paused_pcm();
2120
2121 if (trackstat >= LOAD_TRACK_OK)
2122 {
2123 struct track_info *info = track_list_current(0);
2124
2125 if (info->audio_hid < 0)
2126 return;
2127
2128 /* Everything needed for the codec is ready - start it */
2129 if (audio_start_codec(auto_skip))
2130 {
2131 if (finalised)
2132 playing_id3_sync(info, -1);
2133 return;
2134 }
2135
2136 trackstat = LOAD_TRACK_ERR_START_CODEC;
1582 } 2137 }
1583 2138
1584 track_count = audio_track_count(); 2139 audio_handle_track_load_status(trackstat);
1585 old_track_ridx = track_ridx; 2140}
2141
2142/* Transition to end-of-playlist state and begin wait for PCM to finish */
2143static void audio_monitor_end_of_playlist(void)
2144{
2145 skip_pending = TRACK_SKIP_AUTO_END_PLAYLIST;
2146 filling = STATE_ENDING;
2147 pcmbuf_monitor_track_change(true);
2148}
2149
2150/* Codec has completed decoding the track
2151 (usually Q_AUDIO_CODEC_COMPLETE) */
2152static void audio_on_codec_complete(int status)
2153{
2154 logf("%s(%d)", __func__, status);
1586 2155
1587 /* Now it's good time to send track finish events. */ 2156 if (play_status == PLAY_STOPPED)
1588 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3); 2157 return;
1589 /* swap the mp3entry pointers */
1590 temp = thistrack_id3;
1591 thistrack_id3 = othertrack_id3;
1592 othertrack_id3 = temp;
1593 ci.id3 = thistrack_id3;
1594 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1595 2158
1596 if (dir_skip) 2159 /* If it didn't notify us first, don't expect "seek complete" message
2160 since the codec can't post it now - do things like it would have
2161 done */
2162 audio_complete_codec_seek();
2163
2164 if (play_status == PLAY_PAUSED || skip_pending != TRACK_SKIP_NONE)
1597 { 2165 {
1598 dir_skip = false; 2166 /* Old-hay on the ip-skay - codec has completed decoding
1599 /* regardless of the return value we need to rebuffer. 2167
1600 if it fails the old playlist will resume, else the 2168 Paused: We're not sounding it, so just remember that it happened
1601 next dir will start playing */ 2169 and the resume will begin the transition
1602 playlist_next_dir(ci.new_track); 2170
1603 ci.new_track = 0; 2171 Skipping: There was already a skip in progress, remember it and
1604 audio_rebuffer(); 2172 allow no further progress until the PCM from the previous
1605 goto skip_done; 2173 song has finished
2174 */
2175 codec_skip_pending = true;
2176 codec_skip_status = status;
2177 return;
1606 } 2178 }
1607 2179
1608 if (new_playlist) 2180 codec_skip_pending = false;
1609 ci.new_track = 0;
1610 2181
1611 /* If the playlist isn't that big */ 2182 if (status >= 0)
1612 if (automatic_skip)
1613 { 2183 {
1614 while (!playlist_check(ci.new_track)) 2184 /* Normal automatic skip */
2185 ab_end_of_track_report();
2186 }
2187
2188 int trackstat = LOAD_TRACK_OK;
2189
2190 automatic_skip = true;
2191 skip_pending = TRACK_SKIP_AUTO;
2192
2193 /* Does this track have an entry allocated? */
2194 struct track_info *info = track_list_advance_current(1);
2195
2196 if (!info || info->audio_hid < 0)
2197 {
2198 bool end_of_playlist = false;
2199
2200 if (info)
1615 { 2201 {
1616 if (ci.new_track >= 0) 2202 /* Track load is not complete - it might have stopped on a
2203 full buffer without reaching the audio handle or we just
2204 arrived at it early
2205
2206 If this type is atomic and we couldn't get the audio,
2207 perhaps it would need to wrap to make the allocation and
2208 handles are in the way - to maximize the liklihood it can
2209 be allocated, clear all handles to reset the buffer and
2210 its indexes to 0 - for packet audio, this should not be an
2211 issue and a pointless full reload of all the track's
2212 metadata may be avoided */
2213
2214 struct mp3entry *track_id3 = bufgetid3(info->id3_hid);
2215
2216 if (track_id3 &&
2217 get_audio_base_data_type(track_id3->codectype)
2218 == TYPE_PACKET_AUDIO)
1617 { 2219 {
1618 audio_last_track(true); 2220 /* Continue filling after this track */
2221 audio_reset_and_rebuffer(TRACK_LIST_KEEP_CURRENT, 1);
2222 audio_begin_track_change(true, trackstat);
1619 return; 2223 return;
1620 } 2224 }
1621 ci.new_track++; 2225 /* else rebuffer at this track; status applies to the track we
2226 want */
2227 }
2228 else if (!playlist_peek(1, NULL, 0))
2229 {
2230 /* Play sequence is complete - directory change or other playlist
2231 resequencing - the playlist must now be advanced in order to
2232 continue since a peek ahead to the next track is not possible */
2233 skip_pending = TRACK_SKIP_AUTO_NEW_PLAYLIST;
2234 end_of_playlist = playlist_next(1) < 0;
2235 }
2236
2237 if (!end_of_playlist)
2238 {
2239 trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL,
2240 skip_pending == TRACK_SKIP_AUTO ? 0 : -1);
2241
2242 if (trackstat == LOAD_TRACK_ERR_NO_MORE)
2243 {
2244 /* Failed to find anything afterall - do playlist switchover
2245 instead */
2246 skip_pending = TRACK_SKIP_AUTO_NEW_PLAYLIST;
2247 end_of_playlist = playlist_next(1) < 0;
2248 }
2249 }
2250
2251 if (end_of_playlist)
2252 {
2253 audio_monitor_end_of_playlist();
2254 return;
2255 }
2256 }
2257
2258 audio_begin_track_change(true, trackstat);
2259}
2260
2261/* Called when codec completes seek operation
2262 (usually Q_AUDIO_CODEC_SEEK_COMPLETE) */
2263static void audio_on_codec_seek_complete(void)
2264{
2265 logf("%s()", __func__);
2266 audio_complete_codec_seek();
2267 codec_go();
2268}
2269
2270/* Called when PCM track change has completed
2271 (Q_AUDIO_TRACK_CHANGED) */
2272static void audio_on_track_changed(void)
2273{
2274 /* Finish whatever is pending so that the WPS is in sync */
2275 audio_finalise_track_change(true);
2276
2277 if (codec_skip_pending)
2278 {
2279 /* Codec got ahead completing a short track - complete the
2280 codec's skip and begin the next */
2281 codec_skip_pending = false;
2282 audio_on_codec_complete(codec_skip_status);
2283 }
2284}
2285
2286/* Begin playback from an idle state, transition to a new playlist or
2287 invalidate the buffer and resume (if playing).
2288 (usually Q_AUDIO_PLAY, Q_AUDIO_REMAKE_AUDIO_BUFFER) */
2289static void audio_start_playback(size_t offset, unsigned int flags)
2290{
2291 enum play_status old_status = play_status;
2292
2293 if (flags & AUDIO_START_NEWBUF)
2294 {
2295 /* Mark the buffer dirty - if not playing, it will be reset next
2296 time */
2297 if (buffer_state == AUDIOBUF_STATE_INITIALIZED)
2298 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
2299 }
2300
2301 if (old_status != PLAY_STOPPED)
2302 {
2303 logf("%s(%lu): skipping", __func__, (unsigned long)offset);
2304
2305 halt_decoding_track(true);
2306
2307 automatic_skip = false;
2308 ff_rw_mode = false;
2309
2310 if (flags & AUDIO_START_RESTART)
2311 {
2312 /* Clear out some stuff to resume the current track where it
2313 left off */
2314 pcmbuf_play_stop();
2315 offset = id3_get(PLAYING_ID3)->offset;
2316 track_list_clear(TRACK_LIST_CLEAR_ALL);
2317 }
2318 else
2319 {
2320 /* This is more-or-less treated as manual track transition */
2321 /* Save resume information for current track */
2322 audio_playlist_track_finish();
2323 track_list_clear(TRACK_LIST_CLEAR_ALL);
2324
2325 /* Indicate manual track change */
2326 pcmbuf_start_track_change(false);
2327 audio_clear_paused_pcm();
2328 wipe_track_metadata(true);
1622 } 2329 }
2330
2331 /* Set after track finish event in case skip was in progress */
2332 skip_pending = TRACK_SKIP_NONE;
2333 }
2334 else
2335 {
2336 if (flags & AUDIO_START_RESTART)
2337 return; /* Must already be playing */
2338
2339 /* Cold playback start from a stopped state */
2340 logf("%s(%lu): starting", __func__, offset);
2341
2342 /* Set audio parameters */
2343#if INPUT_SRC_CAPS != 0
2344 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2345 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2346#endif
2347#ifndef PLATFORM_HAS_VOLUME_CHANGE
2348 sound_set_volume(global_settings.volume);
2349#endif
2350 /* Update our state */
2351 play_status = PLAY_PLAYING;
2352 }
2353
2354 /* Start fill from beginning of playlist */
2355 playlist_peek_offset = -1;
2356 buf_set_base_handle(-1);
2357
2358 /* Officially playing */
2359 queue_reply(&audio_queue, 1);
2360
2361 /* Add these now - finish event for the first id3 will most likely be sent
2362 immediately */
2363 add_event(BUFFER_EVENT_REBUFFER, false, buffer_event_rebuffer_callback);
2364 add_event(BUFFER_EVENT_FINISHED, false, buffer_event_finished_callback);
2365
2366 if (old_status == PLAY_STOPPED)
2367 {
2368 /* Send coldstart event */
2369 send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL);
1623 } 2370 }
1624 2371
1625 /* Update the playlist */ 2372 /* Fill the buffer */
1626 last_peek_offset -= ci.new_track; 2373 int trackstat = audio_fill_file_buffer();
2374
2375 if (trackstat >= LOAD_TRACK_OK)
2376 {
2377 /* This is the currently playing track - get metadata, stat */
2378 playing_id3_sync(track_list_current(0), offset);
1627 2379
1628 if (playlist_next(ci.new_track) < 0) 2380 if (valid_mp3entry(id3_get(PLAYING_ID3)))
2381 {
2382 /* Only if actually changing tracks... */
2383 if (!(flags & AUDIO_START_RESTART))
2384 audio_playlist_track_change();
2385 }
2386 }
2387 else
1629 { 2388 {
1630 /* End of list */ 2389 /* Found nothing playable */
1631 audio_last_track(automatic_skip); 2390 audio_handle_track_load_status(trackstat);
2391 }
2392}
2393
2394/* Stop playback and enter an idle state
2395 (usually Q_AUDIO_STOP) */
2396static void audio_stop_playback(void)
2397{
2398 logf("%s()", __func__);
2399
2400 if (play_status == PLAY_STOPPED)
2401 return;
2402
2403 /* Stop the codec and unload it */
2404 halt_decoding_track(true);
2405 pcmbuf_play_stop();
2406 codec_unload();
2407
2408 /* Save resume information - "filling" might have been set to
2409 "STATE_ENDED" by caller in order to facilitate end of playlist */
2410 audio_playlist_track_finish();
2411
2412 skip_pending = TRACK_SKIP_NONE;
2413 automatic_skip = false;
2414
2415 /* Close all tracks and mark them NULL */
2416 remove_event(BUFFER_EVENT_REBUFFER, buffer_event_rebuffer_callback);
2417 remove_event(BUFFER_EVENT_FINISHED, buffer_event_finished_callback);
2418 remove_event(BUFFER_EVENT_BUFFER_LOW, buffer_event_buffer_low_callback);
2419
2420 track_list_clear(TRACK_LIST_CLEAR_ALL);
2421
2422 /* Update our state */
2423 ff_rw_mode = false;
2424 play_status = PLAY_STOPPED;
2425
2426 wipe_track_metadata(true);
2427
2428 /* Go idle */
2429 filling = STATE_IDLE;
2430 cancel_cpu_boost();
2431}
2432
2433/* Pause the playback of the current track
2434 (Q_AUDIO_PAUSE) */
2435static void audio_on_pause(bool pause)
2436{
2437 logf("%s(%s)", __func__, pause ? "true" : "false");
2438
2439 if (play_status == PLAY_STOPPED || pause == (play_status == PLAY_PAUSED))
1632 return; 2440 return;
2441
2442 if (!ff_rw_mode)
2443 {
2444 /* Not in ff/rw mode - may set the state (otherwise this could make
2445 old data play because seek hasn't completed and cleared it) */
2446 pcmbuf_pause(pause);
1633 } 2447 }
1634 2448
1635 if (new_playlist) 2449 play_status = pause ? PLAY_PAUSED : PLAY_PLAYING;
2450
2451 if (!pause && codec_skip_pending)
1636 { 2452 {
1637 ci.new_track = 1; 2453 /* Actually do the skip that is due - resets the status flag */
1638 new_playlist = false; 2454 audio_on_codec_complete(codec_skip_status);
1639 } 2455 }
2456}
2457
2458/* Skip a certain number of tracks forwards or backwards
2459 (Q_AUDIO_SKIP) */
2460static void audio_on_skip(void)
2461{
2462 id3_mutex_lock();
2463
2464 /* Eat the delta to keep it synced, even if not playing */
2465 int toskip = skip_offset;
2466 skip_offset = 0;
1640 2467
1641 /* Save a pointer to the old track to allow later clearing */ 2468 logf("%s(): %d", __func__, toskip);
1642 prev_ti = CUR_TI; 2469
2470 id3_mutex_unlock();
2471
2472 if (play_status == PLAY_STOPPED)
2473 return;
1643 2474
1644 for (i = 0; i < ci.new_track; i++) 2475 /* Force codec to abort this track */
2476 halt_decoding_track(true);
2477
2478 /* Kill the ff/rw halt */
2479 ff_rw_mode = false;
2480
2481 /* Manual skip */
2482 automatic_skip = false;
2483
2484 /* If there was an auto skip in progress, there will be residual
2485 advancement of the playlist and/or track list so compensation will be
2486 required in order to end up in the right spot */
2487 int track_list_delta = toskip;
2488 int playlist_delta = toskip;
2489
2490 if (skip_pending != TRACK_SKIP_NONE)
1645 { 2491 {
1646 idx = (track_ridx + i) & MAX_TRACK_MASK; 2492 if (skip_pending != TRACK_SKIP_AUTO_END_PLAYLIST)
1647 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid); 2493 track_list_delta--;
1648 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid); 2494
1649 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset) 2495 if (skip_pending == TRACK_SKIP_AUTO_NEW_PLAYLIST)
2496 playlist_delta--;
2497 }
2498
2499 audio_playlist_track_finish();
2500 skip_pending = TRACK_SKIP_NONE;
2501
2502 /* Update the playlist current track now */
2503 while (playlist_next(playlist_delta) < 0)
2504 {
2505 /* Manual skip out of range (because the playlist wasn't updated
2506 yet by us and so the check in audio_skip returned 'ok') - bring
2507 back into range */
2508 int d = toskip < 0 ? 1 : -1;
2509
2510 while (!playlist_check(playlist_delta))
1650 { 2511 {
1651 /* We don't have all the audio data for that track, so clear it, 2512 if (playlist_delta == d)
1652 but keep the metadata. */
1653 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
1654 { 2513 {
1655 tracks[idx].audio_hid = -1; 2514 /* Had to move the opposite direction to correct, which is
1656 tracks[idx].filesize = 0; 2515 wrong - this is the end */
2516 filling = STATE_ENDED;
2517 audio_stop_playback();
2518 return;
1657 } 2519 }
2520
2521 playlist_delta += d;
2522 track_list_delta += d;
1658 } 2523 }
1659 } 2524 }
1660 2525
1661 /* Move to the new track */ 2526 /* Adjust things by how much the playlist was manually moved */
1662 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK; 2527 playlist_peek_offset -= playlist_delta;
1663 buf_set_base_handle(CUR_TI->audio_hid);
1664 2528
1665 if (automatic_skip) 2529 struct track_info *info = track_list_advance_current(track_list_delta);
1666 { 2530 int trackstat = LOAD_TRACK_OK;
1667 wps_offset = -ci.new_track;
1668 }
1669 2531
1670 /* If it is not safe to even skip this many track entries */ 2532 if (!info || info->audio_hid < 0)
1671 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
1672 { 2533 {
1673 ci.new_track = 0; 2534 /* We don't know the next track thus we know we don't have it */
1674 audio_rebuffer(); 2535 trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1);
1675 goto skip_done;
1676 } 2536 }
1677 2537
1678 forward = ci.new_track > 0; 2538 audio_begin_track_change(false, trackstat);
1679 ci.new_track = 0; 2539}
2540
2541/* Skip to the next/previous directory
2542 (Q_AUDIO_DIR_SKIP) */
2543static void audio_on_dir_skip(int direction)
2544{
2545 logf("%s(%d)", __func__, direction);
2546
2547 id3_mutex_lock();
2548 skip_offset = 0;
2549 id3_mutex_unlock();
2550
2551 if (play_status == PLAY_STOPPED)
2552 return;
2553
2554 /* Force codec to abort this track */
2555 halt_decoding_track(true);
2556
2557 /* Kill the ff/rw halt */
2558 ff_rw_mode = false;
2559
2560 /* Manual skip */
2561 automatic_skip = false;
2562
2563 audio_playlist_track_finish();
2564
2565 /* Unless automatic and gapless, skips do not pend */
2566 skip_pending = TRACK_SKIP_NONE;
2567
2568 /* Regardless of the return value we need to rebuffer. If it fails the old
2569 playlist will resume, else the next dir will start playing. */
2570 playlist_next_dir(direction);
2571
2572 wipe_track_metadata(false);
1680 2573
1681 /* If the target track is clearly not in memory */ 2574 int trackstat = audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1);
1682 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready) 2575
2576 if (trackstat == LOAD_TRACK_ERR_NO_MORE)
1683 { 2577 {
1684 audio_rebuffer(); 2578 /* The day the music died - finish-off whatever is playing and call it
1685 goto skip_done; 2579 quits */
2580 audio_monitor_end_of_playlist();
2581 return;
1686 } 2582 }
1687 2583
1688 /* When skipping backwards, it is possible that we've found a track that's 2584 audio_begin_track_change(false, trackstat);
1689 * buffered, but which is around the track-wrap and therefore not the track 2585}
1690 * we are looking for */ 2586
1691 if (!forward) 2587/* Enter seek mode in order to start a seek
2588 (Q_AUDIO_PRE_FF_REWIND) */
2589static void audio_on_pre_ff_rewind(void)
2590{
2591 logf("%s()", __func__);
2592
2593 if (play_status == PLAY_STOPPED || ff_rw_mode)
2594 return;
2595
2596 ff_rw_mode = true;
2597
2598 if (play_status == PLAY_PAUSED)
2599 return;
2600
2601 pcmbuf_pause(true);
2602}
2603
2604/* Seek the playback of the current track to the specified time
2605 (Q_AUDIO_FF_REWIND) */
2606static void audio_on_ff_rewind(long time)
2607{
2608 logf("%s(%ld)", __func__, time);
2609
2610 if (play_status == PLAY_STOPPED)
2611 return;
2612
2613 enum track_skip_type pending = skip_pending;
2614
2615 switch (pending)
2616 {
2617 case TRACK_SKIP_NONE: /* The usual case */
2618 case TRACK_SKIP_AUTO: /* Have to back it out (fun!) */
2619 case TRACK_SKIP_AUTO_END_PLAYLIST: /* Still have the last codec used */
1692 { 2620 {
1693 int cur_idx = track_ridx; 2621 struct mp3entry *id3 = id3_get(PLAYING_ID3);
1694 bool taginfo_ready = true; 2622 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
1695 /* We've wrapped the buffer backwards if new > old */ 2623
1696 bool wrap = track_ridx > old_track_ridx; 2624 automatic_skip = false;
2625
2626 /* Send event before clobbering the time */
2627 /* FIXME: Nasty, but the tagtree expects this so that rewinding and
2628 then skipping back to this track resumes properly. Something else
2629 should be sent. We're not _really_ finishing the track are we? */
2630 if (time == 0)
2631 send_event(PLAYBACK_EVENT_TRACK_FINISH, id3);
2632
2633 /* Prevent user codec time update - coerce to something that is
2634 innocuous concerning lookaheads */
2635 if (pending == TRACK_SKIP_NONE)
2636 skip_pending = TRACK_SKIP_AUTO_END_PLAYLIST;
2637
2638 id3->elapsed = time;
2639 queue_reply(&audio_queue, 1);
2640
2641 bool haltres = halt_decoding_track(pending == TRACK_SKIP_AUTO);
2642
2643 /* Need this set in case ff/rw mode + error but _after_ the codec
2644 halt that will reset it */
2645 codec_seeking = true;
1697 2646
1698 while (1) 2647 if (pending == TRACK_SKIP_AUTO)
1699 { 2648 {
1700 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK; 2649 if (!track_list_advance_current(-1))
2650 {
2651 /* Not in list - must rebuffer at the current playlist index */
2652 if (audio_reset_and_rebuffer(TRACK_LIST_CLEAR_ALL, -1)
2653 < LOAD_TRACK_OK)
2654 {
2655 /* Codec is stopped */
2656 break;
2657 }
2658 }
2659 }
1701 2660
1702 /* if we've advanced past the wrap when cur_idx is zeroed */ 2661 /* Set after audio_fill_file_buffer to disable playing id3 clobber if
1703 if (!cur_idx) 2662 rebuffer is needed */
1704 wrap = false; 2663 skip_pending = TRACK_SKIP_NONE;
2664 struct track_info *cur_info = track_list_current(0);
1705 2665
1706 /* if we aren't still on the wrap and we've caught the old track */ 2666 /* Track must complete the loading _now_ since a codec and audio
1707 if (!(wrap || cur_idx < old_track_ridx)) 2667 handle are needed in order to do the seek */
1708 break; 2668 if (cur_info->audio_hid < 0 &&
2669 audio_finish_load_track(cur_info) != LOAD_TRACK_READY)
2670 {
2671 /* Call above should push any load sequence - no need for
2672 halt_decoding_track here if no skip was pending here because
2673 there would not be a codec started if no audio handle was yet
2674 opened */
2675 break;
2676 }
1709 2677
1710 /* If we hit a track in between without valid tag info, bail */ 2678 if (pending == TRACK_SKIP_AUTO)
1711 if (!tracks[cur_idx].taginfo_ready) 2679 {
2680 if (!bufreadid3(cur_info->id3_hid, ci_id3) ||
2681 !audio_init_codec(cur_info, ci_id3))
1712 { 2682 {
1713 taginfo_ready = false; 2683 /* We should have still been able to get it - skip it and move
2684 onto the next one - like it or not this track is borken */
1714 break; 2685 break;
1715 } 2686 }
2687
2688 /* Set the codec API to the correct metadata and track info */
2689 ci.audio_hid = cur_info->audio_hid;
2690 ci.filesize = cur_info->filesize;
2691 buf_set_base_handle(cur_info->audio_hid);
1716 } 2692 }
1717 if (!taginfo_ready) 2693
2694 if (!haltres)
1718 { 2695 {
1719 audio_rebuffer(); 2696 /* If codec must be (re)started, reset the offset */
2697 ci_id3->offset = 0;
1720 } 2698 }
1721 }
1722 2699
1723skip_done: 2700 codec_seek(time);
1724 audio_update_trackinfo(); 2701 return;
1725 pcmbuf_start_track_change(automatic_skip); 2702 }
1726 2703
1727 if (get_codec_base_type(codec_loaded()) == 2704 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
1728 get_codec_base_type(thistrack_id3->codectype))
1729 { 2705 {
1730 /* codec is the same base type */ 2706 /* We cannot do this because the playlist must be reversed by one
1731 logf("New track loaded"); 2707 and it doesn't always return the same song when going backwards
1732 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE, false); 2708 across boundaries as forwards (either because of randomization
2709 or inconsistency in deciding what the previous track should be),
2710 therefore the whole operation would often end up as nonsense -
2711 lock out seeking for a couple seconds */
2712
2713 /* Sure as heck cancel seek mode too! */
2714 audio_ff_rewind_end();
2715 return;
2716 }
2717
2718 default:
2719 /* Won't see this */
2720 return;
1733 } 2721 }
1734 else 2722
2723 if (play_status == PLAY_STOPPED)
1735 { 2724 {
1736 /* a codec change is required */ 2725 /* Playback ended because of an error completing a track load */
1737 logf("New codec: %d/%d", thistrack_id3->codectype, codec_loaded()); 2726 return;
1738 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE, true);
1739 codec_load(tracks[track_ridx].codec_hid, thistrack_id3->codectype);
1740 tracks[track_ridx].codec_hid = -1; /* Codec thread will close it */
1741 } 2727 }
2728
2729 /* Always fake it as a codec start error which will handle mode
2730 cancellations and skip to the next track */
2731 audio_handle_track_load_status(LOAD_TRACK_ERR_START_CODEC);
1742} 2732}
1743 2733
1744unsigned long audio_prev_elapsed(void) 2734/* Invalidates all but currently playing track
2735 (Q_AUDIO_FLUSH) */
2736static void audio_on_audio_flush(void)
1745{ 2737{
1746 return prev_track_elapsed; 2738 logf("%s", __func__);
2739
2740 if (track_list_empty())
2741 return; /* Nothing to flush out */
2742
2743 switch (skip_pending)
2744 {
2745 case TRACK_SKIP_NONE:
2746 case TRACK_SKIP_AUTO_END_PLAYLIST:
2747 /* Remove all but the currently playing track from the list and
2748 refill after that */
2749 track_list_clear(TRACK_LIST_KEEP_CURRENT);
2750 playlist_peek_offset = 0;
2751 id3_write_locked(UNBUFFERED_ID3, NULL);
2752 audio_update_and_announce_next_track(NULL);
2753
2754 /* Ignore return since it's about the next track, not this one */
2755 audio_fill_file_buffer();
2756
2757 if (skip_pending == TRACK_SKIP_NONE)
2758 break;
2759
2760 /* There's now a track after this one now - convert to auto skip -
2761 no skip should pend right now because multiple flush messages can
2762 be fired which would cause a restart in the below cases */
2763 skip_pending = TRACK_SKIP_NONE;
2764 audio_clear_track_notifications();
2765 audio_queue_post(Q_AUDIO_CODEC_COMPLETE, CODEC_OK);
2766 break;
2767
2768 case TRACK_SKIP_AUTO:
2769 case TRACK_SKIP_AUTO_NEW_PLAYLIST:
2770 /* Precisely removing what it already decoded for the next track is
2771 not possible so a restart is required in order to continue the
2772 currently playing track without the now invalid future track
2773 playing */
2774 audio_start_playback(0, AUDIO_START_RESTART);
2775 break;
2776
2777 default: /* Nothing else is a state */
2778 break;
2779 }
1747} 2780}
1748 2781
1749void audio_set_prev_elapsed(unsigned long setting) 2782#ifdef AUDIO_HAVE_RECORDING
2783/* Load the requested encoder type
2784 (Q_AUDIO_LOAD_ENCODER) */
2785static void audio_on_load_encoder(int afmt)
1750{ 2786{
1751 prev_track_elapsed = setting; 2787 bool res = true;
2788
2789 if (play_status != PLAY_STOPPED)
2790 audio_stop_playback(); /* Can't load both types at once */
2791 else
2792 codec_unload(); /* Encoder still loaded, stop and unload it */
2793
2794 if (afmt != AFMT_UNKNOWN)
2795 {
2796 res = codec_load(-1, afmt | CODEC_TYPE_ENCODER);
2797 if (res)
2798 codec_go(); /* These are run immediately */
2799 }
2800
2801 queue_reply(&audio_queue, res);
1752} 2802}
2803#endif /* AUDIO_HAVE_RECORDING */
1753 2804
1754/* Stop the codec and reset the PCM buffer */ 2805static void audio_thread(void)
1755static void audio_stop_codec_flush(void)
1756{ 2806{
1757 bool pcm_playing; 2807 struct queue_event ev;
1758 2808
1759 pcmbuf_pause(true); 2809 pcm_postinit();
1760 2810
1761 codec_stop(); 2811 filling = STATE_IDLE;
1762 2812
1763 pcm_play_lock(); 2813 while (1)
2814 {
2815 switch (filling)
2816 {
2817 /* Active states */
2818 case STATE_FULL:
2819 case STATE_END_OF_PLAYLIST:
2820 if (buf_get_watermark() == 0)
2821 {
2822 /* End of buffering for now, let's calculate the watermark,
2823 register for a low buffer event and unboost */
2824 audio_update_filebuf_watermark(0);
2825 add_event(BUFFER_EVENT_BUFFER_LOW, true,
2826 buffer_event_buffer_low_callback);
2827 }
2828 /* Fall-through */
2829 case STATE_FINISHED:
2830 /* All data was buffered */
2831 cancel_cpu_boost();
2832 /* Fall-through */
2833 case STATE_FILLING:
2834 case STATE_ENDING:
2835 if (audio_pcmbuf_track_change_scan())
2836 {
2837 /* Transfer notification to audio queue event */
2838 ev.id = Q_AUDIO_TRACK_CHANGED;
2839 ev.data = 1;
2840 }
2841 else
2842 {
2843 /* If doing auto skip, poll pcmbuf track notifications a bit
2844 faster to promply detect the transition */
2845 queue_wait_w_tmo(&audio_queue, &ev,
2846 skip_pending == TRACK_SKIP_NONE ?
2847 HZ/2 : HZ/10);
2848 }
2849 break;
1764 2850
1765 pcm_playing = pcm_is_playing(); 2851 /* Idle states */
2852 default:
2853 queue_wait(&audio_queue, &ev);
1766 2854
1767 pcmbuf_play_stop(); 2855#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
1768 queue_clear(&pcmbuf_queue); 2856 switch (ev.id)
2857 {
2858#ifdef AUDIO_HAVE_RECORDING
2859 /* Must monitor the encoder message for recording so it can remove
2860 it if we process the insertion before it does. It cannot simply
2861 be removed from under recording however. */
2862 case Q_AUDIO_LOAD_ENCODER:
2863 break;
2864#endif
2865 case SYS_USB_DISCONNECTED:
2866 filling = STATE_IDLE;
2867 break;
2868
2869 default:
2870 if (filling == STATE_USB)
2871 continue;
2872 }
2873#endif /* CONFIG_PLATFORM */
2874 }
2875
2876 switch (ev.id)
2877 {
2878 /** Codec and track change messages **/
2879 case Q_AUDIO_CODEC_COMPLETE:
2880 /* Codec is done processing track and has gone idle */
2881 LOGFQUEUE("audio < Q_AUDIO_CODEC_COMPLETE: %ld", (long)ev.data);
2882 audio_on_codec_complete(ev.data);
2883 break;
2884
2885 case Q_AUDIO_CODEC_SEEK_COMPLETE:
2886 /* Codec is done seeking */
2887 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
2888 audio_on_codec_seek_complete();
2889 break;
2890
2891 case Q_AUDIO_TRACK_CHANGED:
2892 /* PCM track change done */
2893 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2894 audio_on_track_changed();
2895 break;
2896
2897 /** Control messages **/
2898 case Q_AUDIO_PLAY:
2899 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2900 audio_start_playback(ev.data, 0);
2901 break;
2902
2903 case Q_AUDIO_STOP:
2904 LOGFQUEUE("audio < Q_AUDIO_STOP");
2905 audio_stop_playback();
2906 if (ev.data != 0)
2907 queue_clear(&audio_queue);
2908 break;
2909
2910 case Q_AUDIO_PAUSE:
2911 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2912 audio_on_pause(ev.data);
2913 break;
2914
2915 case Q_AUDIO_SKIP:
2916 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2917 audio_on_skip();
2918 break;
1769 2919
1770 if (pcm_playing) 2920 case Q_AUDIO_DIR_SKIP:
1771 pcmbuf_pause(paused); 2921 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2922 audio_on_dir_skip(ev.data);
2923 break;
2924
2925 case Q_AUDIO_PRE_FF_REWIND:
2926 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2927 audio_on_pre_ff_rewind();
2928 break;
2929
2930 case Q_AUDIO_FF_REWIND:
2931 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2932 audio_on_ff_rewind(ev.data);
2933 break;
2934
2935 case Q_AUDIO_FLUSH:
2936 LOGFQUEUE("audio < Q_AUDIO_FLUSH: %d", (int)ev.data);
2937 audio_on_audio_flush();
2938 break;
1772 2939
1773 pcm_play_unlock(); 2940 /** Buffering messages **/
2941 case Q_AUDIO_BUFFERING:
2942 /* some buffering event */
2943 LOGFQUEUE("audio < Q_AUDIO_BUFFERING: %d", (int)ev.data);
2944 audio_on_buffering(ev.data);
2945 break;
2946
2947 case Q_AUDIO_FILL_BUFFER:
2948 /* continue buffering next track */
2949 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
2950 audio_on_fill_buffer();
2951 break;
2952
2953 case Q_AUDIO_FINISH_LOAD_TRACK:
2954 /* metadata is buffered */
2955 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD_TRACK");
2956 audio_on_finish_load_track(ev.data);
2957 break;
2958
2959 case Q_AUDIO_HANDLE_FINISHED:
2960 /* some other type is buffered */
2961 LOGFQUEUE("audio < Q_AUDIO_HANDLE_FINISHED");
2962 audio_on_handle_finished(ev.data);
2963 break;
2964
2965 /** Miscellaneous messages **/
2966 case Q_AUDIO_REMAKE_AUDIO_BUFFER:
2967 /* buffer needs to be reinitialized */
2968 LOGFQUEUE("audio < Q_AUDIO_REMAKE_AUDIO_BUFFER");
2969 audio_start_playback(0, AUDIO_START_RESTART | AUDIO_START_NEWBUF);
2970 break;
2971
2972#ifdef HAVE_DISK_STORAGE
2973 case Q_AUDIO_UPDATE_WATERMARK:
2974 /* buffering watermark needs updating */
2975 LOGFQUEUE("audio < Q_AUDIO_UPDATE_WATERMARK: %d", (int)ev.data);
2976 audio_update_filebuf_watermark(ev.data);
2977 break;
2978#endif /* HAVE_DISK_STORAGE */
2979
2980#ifdef AUDIO_HAVE_RECORDING
2981 case Q_AUDIO_LOAD_ENCODER:
2982 /* load an encoder for recording */
2983 LOGFQUEUE("audio < Q_AUDIO_LOAD_ENCODER: %d", (int)ev.data);
2984 audio_on_load_encoder(ev.data);
2985 break;
2986#endif /* AUDIO_HAVE_RECORDING */
2987
2988#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2989 case SYS_USB_CONNECTED:
2990 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2991 audio_stop_playback();
2992#ifdef PLAYBACK_VOICE
2993 voice_stop();
2994#endif
2995 filling = STATE_USB;
2996 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2997 break;
2998#endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) */
2999
3000 case SYS_TIMEOUT:
3001 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3002 break;
3003
3004 default:
3005 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
3006 break;
3007 } /* end switch */
3008 } /* end while */
1774} 3009}
1775 3010
1776static void audio_stop_playback(void) 3011
3012/* --- Buffering callbacks --- */
3013
3014/* Called when fullness is below the watermark level */
3015static void buffer_event_buffer_low_callback(void *data)
1777{ 3016{
1778 if (playing) 3017 logf("low buffer callback");
1779 { 3018 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: buffer low");
1780 /* If we were playing, save resume information */ 3019 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_BUFFER_LOW);
1781 struct mp3entry *id3 = NULL; 3020 (void)data;
3021}
1782 3022
1783 if (!ci.stop_codec) 3023/* Called when handles must be discarded in order to buffer new data */
1784 id3 = audio_current_track(); 3024static void buffer_event_rebuffer_callback(void *data)
3025{
3026 logf("rebuffer callback");
3027 LOGFQUEUE("buffering > audio Q_AUDIO_BUFFERING: rebuffer");
3028 audio_queue_post(Q_AUDIO_BUFFERING, BUFFER_EVENT_REBUFFER);
3029 (void)data;
3030}
1785 3031
1786 /* Save the current playing spot, or NULL if the playlist has ended */ 3032/* A handle has completed buffering and all required data is available */
1787 playlist_update_resume_info(id3); 3033static void buffer_event_finished_callback(void *data)
3034{
3035 int hid = *(const int *)data;
3036 const enum data_type htype = buf_handle_data_type(hid);
1788 3037
1789 /* Now it's good time to send track finish events. Do this 3038 logf("handle %d finished buffering (type:%u)", hid, (unsigned)htype);
1790 only if this hasn't been done already as part of a track
1791 switch. */
1792 if (id3 == thistrack_id3)
1793 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1794 3039
1795 /* TODO: Create auto bookmark too? */ 3040 /* Limit queue traffic */
3041 switch (htype)
3042 {
3043 case TYPE_ID3:
3044 /* The metadata handle for the last loaded track has been buffered.
3045 We can ask the audio thread to load the rest of the track's data. */
3046 LOGFQUEUE("buffering > audio Q_AUDIO_FINISH_LOAD_TRACK: %d", hid);
3047 audio_queue_post(Q_AUDIO_FINISH_LOAD_TRACK, hid);
3048 break;
1796 3049
1797 prev_track_elapsed = othertrack_id3->elapsed; 3050 case TYPE_PACKET_AUDIO:
3051 /* Strip any useless trailing tags that are left. */
3052 strip_tags(hid);
3053 /* Fall-through */
3054 case TYPE_ATOMIC_AUDIO:
3055 LOGFQUEUE("buffering > audio Q_AUDIO_HANDLE_FINISHED: %d", hid);
3056 audio_queue_post(Q_AUDIO_HANDLE_FINISHED, hid);
3057 break;
1798 3058
1799 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback); 3059 default:
3060 /* Don't care to know about these */
3061 break;
1800 } 3062 }
3063}
1801 3064
1802 audio_stop_codec_flush();
1803 paused = false;
1804 playing = false;
1805 track_load_started = false;
1806 3065
1807 filling = STATE_IDLE; 3066/** -- Codec callbacks -- **/
3067
3068/* Update elapsed times with latency-adjusted values */
3069void audio_codec_update_elapsed(unsigned long value)
3070{
3071#ifdef AB_REPEAT_ENABLE
3072 ab_position_report(value);
3073#endif
3074
3075 unsigned long latency = pcmbuf_get_latency();
3076
3077 if (LIKELY(value >= latency))
3078 {
3079 unsigned long elapsed = value - latency;
3080
3081 if (elapsed > value || elapsed < value - 2)
3082 value = elapsed;
3083 }
3084 else
3085 {
3086 value = 0;
3087 }
1808 3088
1809 /* Mark all entries null. */ 3089 /* Track codec: used later when updating the playing at the user
1810 audio_clear_track_entries(); 3090 transition */
3091 id3_get(CODEC_ID3)->elapsed = value;
1811 3092
1812 /* Close all tracks */ 3093 /* If a skip is pending, the PCM buffer is updating the time on the
1813 audio_release_tracks(); 3094 previous song */
3095 if (LIKELY(skip_pending == TRACK_SKIP_NONE))
3096 id3_get(PLAYING_ID3)->elapsed = value;
1814} 3097}
1815 3098
1816static void audio_play_start(size_t offset) 3099/* Update offsets with latency-adjusted values */
3100void audio_codec_update_offset(size_t value)
1817{ 3101{
1818 int i; 3102 struct mp3entry *ci_id3 = id3_get(CODEC_ID3);
3103 unsigned long latency = pcmbuf_get_latency() * ci_id3->bitrate / 8;
1819 3104
1820 send_event(PLAYBACK_EVENT_START_PLAYBACK, NULL); 3105 if (LIKELY(value >= latency))
1821#if INPUT_SRC_CAPS != 0 3106 {
1822 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); 3107 value -= latency;
1823 audio_set_output_source(AUDIO_SRC_PLAYBACK); 3108 }
1824#endif 3109 else
3110 {
3111 value = 0;
3112 }
1825 3113
1826 paused = false; 3114 /* Track codec: used later when updating the playing id3 at the user
1827 audio_stop_codec_flush(); 3115 transition */
3116 ci_id3->offset = value;
1828 3117
1829 playing = true; 3118 /* If a skip is pending, the PCM buffer is updating the time on the
1830 track_load_started = false; 3119 previous song */
3120 if (LIKELY(skip_pending == TRACK_SKIP_NONE))
3121 id3_get(PLAYING_ID3)->offset = value;
3122}
1831 3123
1832 ci.new_track = 0;
1833 ci.seek_time = 0;
1834 wps_offset = 0;
1835 3124
1836#ifndef PLATFORM_HAS_VOLUME_CHANGE 3125/** --- Pcmbuf callbacks --- **/
1837 sound_set_volume(global_settings.volume);
1838#endif
1839 track_widx = track_ridx = 0;
1840 buf_set_base_handle(-1);
1841 3126
1842 /* Clear all track entries. */ 3127/* Between the codec and PCM track change, we need to keep updating the
1843 for (i = 0; i < MAX_TRACK; i++) { 3128 * "elapsed" value of the previous (to the codec, but current to the
1844 clear_track_info(&tracks[i]); 3129 * user/PCM/WPS) track, so that the progressbar reaches the end. */
3130void audio_pcmbuf_position_callback(unsigned int time)
3131{
3132 struct mp3entry *id3 = id3_get(PLAYING_ID3);
3133
3134 time += id3->elapsed;
3135
3136 id3->elapsed = MIN(time, id3->length);
3137}
3138
3139/* Post message from pcmbuf that the end of the previous track has just
3140 * been played */
3141void audio_pcmbuf_track_change(bool pcmbuf)
3142{
3143 if (pcmbuf)
3144 {
3145 /* Notify of the change in special-purpose semaphore object */
3146 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
3147 audio_pcmbuf_track_change_post();
1845 } 3148 }
3149 else
3150 {
3151 /* Safe to post directly to the queue */
3152 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
3153 audio_queue_post(Q_AUDIO_TRACK_CHANGED, 0);
3154 }
3155}
1846 3156
1847 last_peek_offset = -1; 3157/* May pcmbuf start PCM playback when the buffer is full enough? */
3158bool audio_pcmbuf_may_play(void)
3159{
3160 return play_status == PLAY_PLAYING && !ff_rw_mode;
3161}
1848 3162
1849 /* Officially playing */
1850 queue_reply(&audio_queue, 1);
1851 3163
1852 audio_fill_file_buffer(true, offset); 3164/** -- External interfaces -- **/
1853 3165
1854 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback); 3166/* Return the playback and recording status */
3167int audio_status(void)
3168{
3169 unsigned int ret = play_status;
3170
3171#ifdef AUDIO_HAVE_RECORDING
3172 /* Do this here for constitency with mpeg.c version */
3173 ret |= pcm_rec_status();
3174#endif
1855 3175
1856 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED"); 3176 return (int)ret;
1857 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1858} 3177}
1859 3178
3179/* Clear all accumulated audio errors for playback and recording */
3180void audio_error_clear(void)
3181{
3182#ifdef AUDIO_HAVE_RECORDING
3183 pcm_rec_error_clear();
3184#endif
3185}
1860 3186
1861/* Invalidates all but currently playing track. */ 3187/* Get a copy of the id3 data for the for current track + offset + skip delta */
1862static void audio_invalidate_tracks(void) 3188bool audio_peek_track(struct mp3entry *id3, int offset)
1863{ 3189{
1864 if (audio_have_tracks()) 3190 bool retval = false;
3191
3192 id3_mutex_lock();
3193
3194 if (play_status != PLAY_STOPPED)
1865 { 3195 {
1866 last_peek_offset = 0; 3196 id3->path[0] = '\0'; /* Null path means it should be filled now */
1867 track_widx = track_ridx; 3197 retval = audio_get_track_metadata(offset + skip_offset, id3) &&
3198 id3->path[0] != '\0';
3199 }
1868 3200
1869 /* Mark all other entries null (also buffered wrong metadata). */ 3201 id3_mutex_unlock();
1870 audio_clear_track_entries();
1871 3202
1872 track_widx = (track_widx + 1) & MAX_TRACK_MASK; 3203 return retval;
3204}
3205
3206/* Return the mp3entry for the currently playing track */
3207struct mp3entry * audio_current_track(void)
3208{
3209 struct mp3entry *id3;
1873 3210
1874 audio_fill_file_buffer(false, 0); 3211 id3_mutex_lock();
1875 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3); 3212
3213#ifdef AUDIO_FAST_SKIP_PREVIEW
3214 if (skip_offset != 0)
3215 {
3216 /* This is a peekahead */
3217 id3 = id3_get(PLAYING_PEEK_ID3);
3218 audio_peek_track(id3, 0);
1876 } 3219 }
3220 else
3221#endif
3222 {
3223 /* Normal case */
3224 id3 = id3_get(PLAYING_ID3);
3225 audio_get_track_metadata(0, id3);
3226 }
3227
3228 id3_mutex_unlock();
3229
3230 return id3;
1877} 3231}
1878 3232
1879static void audio_new_playlist(void) 3233/* Obtains the mp3entry for the next track from the current */
3234struct mp3entry * audio_next_track(void)
1880{ 3235{
1881 /* Prepare to start a new fill from the beginning of the playlist */ 3236 struct mp3entry *id3 = id3_get(NEXTTRACK_ID3);
1882 last_peek_offset = -1;
1883 3237
1884 /* Signal the codec to initiate a track change forward */ 3238 id3_mutex_lock();
1885 new_playlist = true;
1886 ci.new_track = 1;
1887 3239
1888 if (audio_have_tracks()) 3240#ifdef AUDIO_FAST_SKIP_PREVIEW
3241 if (skip_offset != 0)
3242 {
3243 /* This is a peekahead */
3244 if (!audio_peek_track(id3, 1))
3245 id3 = NULL;
3246 }
3247 else
3248#endif
1889 { 3249 {
1890 if (paused) 3250 /* Normal case */
1891 skipped_during_pause = true; 3251 if (!audio_get_track_metadata(1, id3))
1892 track_widx = track_ridx; 3252 id3 = NULL;
1893 audio_clear_track_entries(); 3253 }
1894 3254
1895 track_widx = (track_widx + 1) & MAX_TRACK_MASK; 3255 id3_mutex_unlock();
1896 3256
1897 /* Mark the current track as invalid to prevent skipping back to it */ 3257 return id3;
1898 CUR_TI->taginfo_ready = false; 3258}
1899 }
1900 3259
1901 /* Officially playing */ 3260/* Start playback at the specified offset */
1902 queue_reply(&audio_queue, 1); 3261void audio_play(long offset)
3262{
3263 logf("audio_play");
1903 3264
1904 audio_fill_file_buffer(false, 0); 3265#ifdef PLAYBACK_VOICE
3266 /* Truncate any existing voice output so we don't have spelling
3267 * etc. over the first part of the played track */
3268 talk_force_shutup();
3269#endif
3270
3271 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
3272 audio_queue_send(Q_AUDIO_PLAY, offset);
1905} 3273}
1906 3274
1907/* Called on manual track skip */ 3275/* Stop playback if playing */
1908static void audio_initiate_track_change(long direction) 3276void audio_stop(void)
1909{ 3277{
1910 logf("audio_initiate_track_change(%ld)", direction); 3278 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
3279 audio_queue_send(Q_AUDIO_STOP, 0);
3280}
1911 3281
1912 ci.new_track += direction; 3282/* Pause playback if playing */
1913 wps_offset -= direction; 3283void audio_pause(void)
1914 if (paused) 3284{
1915 skipped_during_pause = true; 3285 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
3286 audio_queue_send(Q_AUDIO_PAUSE, true);
3287}
3288
3289/* This sends a stop message and the audio thread will dump all its
3290 subsequent messages */
3291void audio_hard_stop(void)
3292{
3293 /* Stop playback */
3294 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
3295 audio_queue_send(Q_AUDIO_STOP, 1);
3296#ifdef PLAYBACK_VOICE
3297 voice_stop();
3298#endif
1916} 3299}
1917 3300
1918/* Called on manual dir skip */ 3301/* Resume playback if paused */
1919static void audio_initiate_dir_change(long direction) 3302void audio_resume(void)
1920{ 3303{
1921 dir_skip = true; 3304 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
1922 ci.new_track = direction; 3305 audio_queue_send(Q_AUDIO_PAUSE, false);
1923 if (paused)
1924 skipped_during_pause = true;
1925} 3306}
1926 3307
1927/* Called when PCM track change is complete */ 3308/* Skip the specified number of tracks forward or backward from the current */
1928static void audio_finalise_track_change(void) 3309void audio_skip(int offset)
1929{ 3310{
1930 logf("audio_finalise_track_change"); 3311 id3_mutex_lock();
3312
3313 /* If offset has to be backed-out to stay in range, no skip is done */
3314 int accum = skip_offset + offset;
1931 3315
1932 if (automatic_skip) 3316 while (offset != 0 && !playlist_check(accum))
1933 { 3317 {
1934 wps_offset = 0; 3318 offset += offset < 0 ? 1 : -1;
1935 automatic_skip = false; 3319 accum = skip_offset + offset;
3320 }
1936 3321
1937 /* Invalidate prevtrack_id3 */ 3322 if (offset != 0)
1938 memset(othertrack_id3, 0, sizeof(struct mp3entry)); 3323 {
3324 /* Accumulate net manual skip count since the audio thread last
3325 processed one */
3326 skip_offset = accum;
1939 3327
1940 if (prev_ti && prev_ti->audio_hid < 0) 3328 if (global_settings.beep)
1941 { 3329 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
1942 /* No audio left so we clear all the track info. */ 3330
1943 clear_track_info(prev_ti); 3331 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset);
1944 } 3332
3333#ifdef AUDIO_FAST_SKIP_PREVIEW
3334 /* Do this before posting so that the audio thread can correct us
3335 when things settle down - additionally, if audio gets a message
3336 and the delta is zero, the Q_AUDIO_SKIP handler (audio_on_skip)
3337 handler a skip event with the correct info but doesn't skip */
3338 send_event(PLAYBACK_EVENT_TRACK_SKIP, NULL);
3339#endif /* AUDIO_FAST_SKIP_PREVIEW */
3340
3341 /* Playback only needs the final state even if more than one is
3342 processed because it wasn't removed in time */
3343 queue_remove_from_head(&audio_queue, Q_AUDIO_SKIP);
3344 audio_queue_post(Q_AUDIO_SKIP, 0);
1945 } 3345 }
1946 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3); 3346 else
1947 playlist_update_resume_info(audio_current_track()); 3347 {
3348 /* No more tracks */
3349 if (global_settings.beep)
3350 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
3351 }
3352
3353 id3_mutex_unlock();
1948} 3354}
1949 3355
1950static void audio_seek_complete(void) 3356/* Skip one track forward from the current */
3357void audio_next(void)
1951{ 3358{
1952 logf("audio_seek_complete"); 3359 audio_skip(1);
3360}
1953 3361
1954 if (!playing) 3362/* Skip one track backward from the current */
1955 return; 3363void audio_prev(void)
3364{
3365 audio_skip(-1);
3366}
1956 3367
1957 /* If seeking-while-playing, pcm_is_paused() is true. 3368/* Move one directory forward */
1958 * If seeking-while-paused, audio_status PAUSE is true. 3369void audio_next_dir(void)
1959 * A seamless seek skips this section. */ 3370{
1960 ci.seek_time = 0; 3371 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
3372 audio_queue_post(Q_AUDIO_DIR_SKIP, 1);
3373}
1961 3374
1962 pcm_play_lock(); 3375/* Move one directory backward */
3376void audio_prev_dir(void)
3377{
3378 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
3379 audio_queue_post(Q_AUDIO_DIR_SKIP, -1);
3380}
1963 3381
1964 if (pcm_is_paused() || paused) 3382/* Pause playback in order to start a seek that flushes the old audio */
1965 { 3383void audio_pre_ff_rewind(void)
1966 /* Clear the buffer */ 3384{
1967 pcmbuf_play_stop(); 3385 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
3386 audio_queue_post(Q_AUDIO_PRE_FF_REWIND, 0);
3387}
1968 3388
1969 /* If seeking-while-playing, resume PCM playback */ 3389/* Seek to the new time in the current track */
1970 if (!paused) 3390void audio_ff_rewind(long time)
1971 pcmbuf_pause(false); 3391{
1972 } 3392 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
3393 audio_queue_post(Q_AUDIO_FF_REWIND, time);
3394}
1973 3395
1974 pcm_play_unlock(); 3396/* Clear all but the currently playing track then rebuffer */
3397void audio_flush_and_reload_tracks(void)
3398{
3399 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
3400 audio_queue_post(Q_AUDIO_FLUSH, 0);
1975} 3401}
1976 3402
1977static void audio_codec_status_message(long reason, int status) 3403/* Return the pointer to the main audio buffer, optionally preserving
3404 voicing */
3405unsigned char * audio_get_buffer(bool talk_buf, size_t *buffer_size)
1978{ 3406{
1979 /* TODO: Push the errors up to the normal UI somewhere */ 3407 unsigned char *buf, *end;
1980 switch (reason) 3408
3409 if (audio_is_initialized)
1981 { 3410 {
1982 case Q_CODEC_LOAD_DISK: 3411 audio_hard_stop();
1983 case Q_CODEC_LOAD: 3412 }
1984 if (!playing) 3413 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
1985 return;
1986 3414
1987 if (status < 0) 3415 if (buffer_size == NULL)
3416 {
3417 /* Special case for talk_init to use since it already knows it's
3418 trashed */
3419 buffer_state = AUDIOBUF_STATE_TRASHED;
3420 return NULL;
3421 }
3422
3423 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
3424 || !talk_voice_required())
3425 {
3426 logf("get buffer: talk, audio");
3427 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
3428 the talk buffer is not needed because voice isn't being used, or
3429 could be AUDIOBUF_STATE_TRASHED already. If state is
3430 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
3431 without the caller knowing what's going on. Changing certain settings
3432 may move it to a worse condition but the memory in use by something
3433 else will remain undisturbed.
3434 */
3435 if (buffer_state != AUDIOBUF_STATE_TRASHED)
1988 { 3436 {
1989 splash(HZ*2, "Codec failure"); 3437 talk_buffer_steal();
1990 audio_check_new_track(); 3438 buffer_state = AUDIOBUF_STATE_TRASHED;
1991 } 3439 }
1992 break;
1993 3440
1994#ifdef AUDIO_HAVE_RECORDING 3441 buf = audiobuf;
1995 case Q_ENCODER_LOAD_DISK: 3442 end = audiobufend;
1996 if (status < 0)
1997 splash(HZ*2, "Encoder failure");
1998 break;
1999#endif /* AUDIO_HAVE_RECORDING */
2000 } 3443 }
3444 else
3445 {
3446 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
3447 still AUDIOBUF_STATE_INITIALIZED */
3448 /* Skip talk buffer and move pcm buffer to end to maximize available
3449 contiguous memory - no audio running means voice will not need the
3450 swap space */
3451 logf("get buffer: audio");
3452 buf = audiobuf + talk_get_bufsize();
3453 end = audiobufend - pcmbuf_init(audiobufend);
3454 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
3455 }
3456
3457 *buffer_size = end - buf;
3458
3459 return buf;
2001} 3460}
2002 3461
2003/* 3462#ifdef HAVE_RECORDING
2004 * Layout audio buffer as follows - iram buffer depends on target: 3463/* Stop audio, voice and obtain all available buffer space */
2005 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|] 3464unsigned char * audio_get_recording_buffer(size_t *buffer_size)
2006 */
2007static void audio_reset_buffer(void)
2008{ 3465{
2009 /* see audio_get_recording_buffer if this is modified */ 3466 audio_hard_stop();
2010 logf("audio_reset_buffer"); 3467 talk_buffer_steal();
2011 3468
2012 /* If the setup of anything allocated before the file buffer is 3469 unsigned char *end = audiobufend;
2013 changed, do check the adjustments after the buffer_alloc call 3470 buffer_state = AUDIOBUF_STATE_TRASHED;
2014 as it will likely be affected and need sliding over */ 3471 *buffer_size = end - audiobuf;
2015 3472
2016 /* Initially set up file buffer as all space available */ 3473 return (unsigned char *)audiobuf;
2017 filebuf = audiobuf + talk_get_bufsize(); 3474}
2018 filebuflen = audiobufend - filebuf; 3475#endif /* HAVE_RECORDING */
2019 3476
2020 ALIGN_BUFFER(filebuf, filebuflen, sizeof (intptr_t)); 3477/* Restore audio buffer to a particular state (one more valid than the current
3478 state) */
3479bool audio_restore_playback(int type)
3480{
3481 switch (type)
3482 {
3483 case AUDIO_WANT_PLAYBACK:
3484 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
3485 audio_reset_buffer();
3486 return true;
3487 case AUDIO_WANT_VOICE:
3488 if (buffer_state == AUDIOBUF_STATE_TRASHED)
3489 audio_reset_buffer();
3490 return true;
3491 default:
3492 return false;
3493 }
3494}
2021 3495
2022 /* Subtract whatever the pcm buffer says it used plus the guard buffer */ 3496/* Has the playback buffer been completely claimed? */
2023 size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) + GUARD_BUFSIZE; 3497bool audio_buffer_state_trashed(void)
3498{
3499 return buffer_state == AUDIOBUF_STATE_TRASHED;
3500}
2024 3501
2025 /* Make sure filebuflen is a pointer sized multiple after adjustment */
2026 pcmbuf_size = ALIGN_UP(pcmbuf_size, sizeof (intptr_t));
2027 3502
2028 if(pcmbuf_size > filebuflen) 3503/** --- Miscellaneous public interfaces --- **/
2029 panicf("%s(): EOM (%zu > %zu)", __func__, pcmbuf_size, filebuflen);
2030 3504
2031 filebuflen -= pcmbuf_size; 3505#ifdef HAVE_ALBUMART
2032 buffering_reset(filebuf, filebuflen); 3506/* Return which album art handle is current for the user in the given slot */
3507int playback_current_aa_hid(int slot)
3508{
3509 if ((unsigned)slot < MAX_MULTIPLE_AA)
3510 {
3511 struct track_info *info = track_list_user_current(skip_offset);
2033 3512
2034 /* Clear any references to the file buffer */ 3513 if (!info && abs(skip_offset) <= 1)
2035 buffer_state = AUDIOBUF_STATE_INITIALIZED; 3514 {
3515 /* Give the actual position a go */
3516 info = track_list_user_current(0);
3517 }
2036 3518
2037#if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE) 3519 if (info)
2038 /* Make sure everything adds up - yes, some info is a bit redundant but 3520 return info->aa_hid[slot];
2039 aids viewing and the sumation of certain variables should add up to
2040 the location of others. */
2041 {
2042 size_t pcmbufsize;
2043 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
2044 logf("fbuf: %08X", (unsigned)filebuf);
2045 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
2046 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
2047 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
2048 logf("pcmb: %08X", (unsigned)pcmbuf);
2049 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
2050 } 3521 }
2051#endif 3522
3523 return ERR_HANDLE_NOT_FOUND;
2052} 3524}
2053 3525
2054static void audio_thread(void) 3526/* Find an album art slot that doesn't match the dimensions of another that
3527 is already claimed - increment the use count if it is */
3528int playback_claim_aa_slot(struct dim *dim)
2055{ 3529{
2056 struct queue_event ev; 3530 int i;
2057
2058 pcm_postinit();
2059
2060 audio_thread_ready = true;
2061 3531
2062 while (1) 3532 /* First try to find a slot already having the size to reuse it since we
3533 don't want albumart of the same size buffered multiple times */
3534 FOREACH_ALBUMART(i)
2063 { 3535 {
2064 switch (filling) { 3536 struct albumart_slot *slot = &albumart_slots[i];
2065 case STATE_IDLE:
2066 queue_wait(&audio_queue, &ev);
2067 break;
2068 3537
2069#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 3538 if (slot->dim.width == dim->width &&
2070 case STATE_USB: 3539 slot->dim.height == dim->height)
2071 queue_wait(&audio_queue, &ev); 3540 {
2072 switch (ev.id) { 3541 slot->used++;
2073#ifdef AUDIO_HAVE_RECORDING 3542 return i;
2074 /* Must monitor the encoder message for recording so it can 3543 }
2075 remove it if we process the insertion before it does. It 3544 }
2076 cannot simply be removed from under recording however. */
2077 case Q_AUDIO_LOAD_ENCODER:
2078 break;
2079#endif
2080 case SYS_USB_DISCONNECTED:
2081 filling = STATE_IDLE;
2082 default:
2083 continue;
2084 }
2085 break;
2086#endif /* CONFIG_PLATFORM */
2087 3545
2088 default: 3546 /* Size is new, find a free slot */
2089 /* End of buffering, let's calculate the watermark and 3547 FOREACH_ALBUMART(i)
2090 unboost */ 3548 {
2091 set_filebuf_watermark(); 3549 if (!albumart_slots[i].used)
2092 cancel_cpu_boost(); 3550 {
2093 /* Fall-through */ 3551 albumart_slots[i].used++;
2094 case STATE_FILLING: 3552 albumart_slots[i].dim = *dim;
2095 case STATE_ENDING: 3553 return i;
2096 if (!pcmbuf_queue_scan(&ev))
2097 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
2098 break;
2099 } 3554 }
3555 }
2100 3556
2101 switch (ev.id) { 3557 /* Sorry, no free slot */
3558 return -1;
3559}
2102 3560
2103 case Q_AUDIO_FILL_BUFFER: 3561/* Invalidate the albumart_slot - decrement the use count if > 0 */
2104 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data); 3562void playback_release_aa_slot(int slot)
2105 audio_fill_file_buffer((bool)ev.data, 0); 3563{
2106 break; 3564 if ((unsigned)slot < MAX_MULTIPLE_AA)
3565 {
3566 struct albumart_slot *aa_slot = &albumart_slots[slot];
2107 3567
2108 case Q_AUDIO_FINISH_LOAD: 3568 if (aa_slot->used > 0)
2109 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD"); 3569 aa_slot->used--;
2110 audio_finish_load_track(); 3570 }
2111 buf_set_base_handle(CUR_TI->audio_hid); 3571}
2112 break; 3572#endif /* HAVE_ALBUMART */
2113 3573
2114 case Q_AUDIO_PLAY:
2115 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2116 if (playing && ev.data <= 0)
2117 audio_new_playlist();
2118 else
2119 {
2120 audio_stop_playback();
2121 audio_play_start((size_t)ev.data);
2122 }
2123 break;
2124 3574
2125 case Q_AUDIO_STOP: 3575#ifdef HAVE_RECORDING
2126 LOGFQUEUE("audio < Q_AUDIO_STOP"); 3576/* Load an encoder and run it */
2127 if (playing) 3577bool audio_load_encoder(int afmt)
2128 audio_stop_playback(); 3578{
2129 if (ev.data != 0) 3579#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2130 queue_clear(&audio_queue); 3580 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt);
2131 break; 3581 return audio_queue_send(Q_AUDIO_LOAD_ENCODER, afmt) != 0;
3582#else
3583 (void)afmt;
3584 return true;
3585#endif
3586}
2132 3587
2133 case Q_AUDIO_PAUSE: 3588/* Stop an encoder and unload it */
2134 LOGFQUEUE("audio < Q_AUDIO_PAUSE"); 3589void audio_remove_encoder(void)
2135 if (!(bool) ev.data && skipped_during_pause 3590{
2136#ifdef HAVE_CROSSFADE 3591#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2137 && !pcmbuf_is_crossfade_active() 3592 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
3593 audio_queue_send(Q_AUDIO_LOAD_ENCODER, AFMT_UNKNOWN);
2138#endif 3594#endif
2139 ) 3595}
2140 pcmbuf_play_stop(); /* Flush old track on resume after skip */ 3596#endif /* HAVE_RECORDING */
2141 skipped_during_pause = false;
2142 if (!playing)
2143 break;
2144 pcmbuf_pause((bool)ev.data);
2145 paused = (bool)ev.data;
2146 break;
2147 3597
2148 case Q_AUDIO_SKIP: 3598/* Is an automatic skip in progress? If called outside transistion callbacks,
2149 LOGFQUEUE("audio < Q_AUDIO_SKIP"); 3599 indicates the last skip type at the time it was processed and isn't very
2150 audio_initiate_track_change((long)ev.data); 3600 meaningful. */
2151 break; 3601bool audio_automatic_skip(void)
3602{
3603 return automatic_skip;
3604}
2152 3605
2153 case Q_AUDIO_PRE_FF_REWIND: 3606/* Would normally calculate byte offset from an elapsed time but is not
2154 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND"); 3607 used on SWCODEC */
2155 if (!playing) 3608int audio_get_file_pos(void)
2156 break; 3609{
2157 pcmbuf_pause(true); 3610 return 0;
2158 break; 3611}
2159 3612
2160 case Q_AUDIO_FF_REWIND: 3613/* Return the elasped time of the track previous to the current */
2161 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND"); 3614unsigned long audio_prev_elapsed(void)
2162 if (!playing) 3615{
2163 break; 3616 return prev_track_elapsed;
3617}
2164 3618
2165 if (filling == STATE_ENDING) 3619/* Is the audio thread ready to accept commands? */
2166 { 3620bool audio_is_thread_ready(void)
2167 /* Temp workaround: There is no codec available */ 3621{
2168 if (!paused) 3622 return filling != STATE_BOOT;
2169 pcmbuf_pause(false); 3623}
2170 break;
2171 }
2172 3624
2173 if ((long)ev.data == 0) 3625/* Return total file buffer length after accounting for the talk buf */
2174 { 3626size_t audio_get_filebuflen(void)
2175 /* About to restart the track - send track finish 3627{
2176 events if not already done. */ 3628 return buf_length();
2177 if (thistrack_id3 == audio_current_track()) 3629}
2178 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
2179 }
2180 3630
2181 if (automatic_skip) 3631/* How many tracks exist on the buffer - full or partial */
2182 { 3632int audio_track_count(void)
2183 /* An automatic track skip is in progress. Finalize it, 3633 __attribute__((alias("track_list_count")));
2184 then go back to the previous track */
2185 audio_finalise_track_change();
2186 ci.new_track = -1;
2187 }
2188 ci.seek_time = (long)ev.data+1;
2189 break;
2190 3634
2191 case Q_AUDIO_CHECK_NEW_TRACK: 3635/* Return total ringbuffer space occupied - ridx to widx */
2192 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK"); 3636long audio_filebufused(void)
2193 audio_check_new_track(); 3637{
2194 break; 3638 return buf_used();
3639}
2195 3640
2196 case Q_AUDIO_DIR_SKIP:
2197 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2198 audio_initiate_dir_change(ev.data);
2199 break;
2200 3641
2201 case Q_AUDIO_FLUSH: 3642/** -- Settings -- **/
2202 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2203 audio_invalidate_tracks();
2204 break;
2205 3643
2206 case Q_AUDIO_TRACK_CHANGED: 3644/* Enable or disable cuesheet support and allocate/don't allocate the
2207 /* PCM track change done */ 3645 extra associated resources */
2208 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED"); 3646void audio_set_cuesheet(int enable)
2209 /* Set new playlist position for resuming. */ 3647{
2210 playlist_update_resume_index(); 3648 if (play_status == PLAY_STOPPED || !enable != !get_current_cuesheet())
2211 if (filling != STATE_ENDING) 3649 {
2212 audio_finalise_track_change(); 3650 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
2213 else if (playing) 3651 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
2214 audio_stop_playback(); 3652 }
2215 break; 3653}
2216 3654
2217 case Q_AUDIO_SEEK_COMPLETE: 3655#ifdef HAVE_DISK_STORAGE
2218 /* Codec seek done */ 3656/* Set the audio antiskip buffer margin by index */
2219 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE"); 3657void audio_set_buffer_margin(int setting)
2220 audio_seek_complete(); 3658{
2221 codec_ack_msg(Q_AUDIO_SEEK_COMPLETE, false); 3659 static const unsigned short lookup[] =
2222 break; 3660 { 5, 15, 30, 60, 120, 180, 300, 600 };
2223 3661
2224 case Q_CODEC_LOAD: 3662 if ((unsigned)setting >= ARRAYLEN(lookup))
2225 case Q_CODEC_LOAD_DISK: 3663 setting = 0;
2226#ifdef AUDIO_HAVE_RECORDING
2227 case Q_ENCODER_LOAD_DISK:
2228#endif
2229 /* These are received when a codec has finished normally or
2230 upon a codec error */
2231 audio_codec_status_message(ev.id, ev.data);
2232 break;
2233 3664
2234#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 3665 logf("buffer margin: %u", (unsigned)lookup[setting]);
2235 case SYS_USB_CONNECTED:
2236 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2237 if (playing)
2238 audio_stop_playback();
2239#ifdef PLAYBACK_VOICE
2240 voice_stop();
2241#endif
2242 filling = STATE_USB;
2243 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2244 break;
2245#endif
2246 3666
2247#ifdef AUDIO_HAVE_RECORDING 3667 LOGFQUEUE("audio > audio Q_AUDIO_UPDATE_WATERMARK: %u",
2248 case Q_AUDIO_LOAD_ENCODER: 3668 (unsigned)lookup[setting]);
2249 if (playing) 3669 audio_queue_post(Q_AUDIO_UPDATE_WATERMARK, lookup[setting]);
2250 audio_stop_playback(); 3670}
2251 else 3671#endif /* HAVE_DISK_STORAGE */
2252 codec_stop(); /* If encoder still loaded, stop it */
2253 3672
2254 if (ev.data == AFMT_UNKNOWN) 3673#ifdef HAVE_CROSSFADE
2255 break; 3674/* Take necessary steps to enable or disable the crossfade setting */
3675void audio_set_crossfade(int enable)
3676{
3677 /* Tell it the next setting to use */
3678 pcmbuf_request_crossfade_enable(enable);
2256 3679
2257 queue_reply(&audio_queue, 3680 /* Return if size hasn't changed or this is too early to determine
2258 codec_load(-1, ev.data | CODEC_TYPE_ENCODER)); 3681 which in the second case there's no way we could be playing
2259 break; 3682 anything at all */
2260#endif /* AUDIO_HAVE_RECORDING */ 3683 if (!pcmbuf_is_same_size())
3684 {
3685 LOGFQUEUE("audio >| audio Q_AUDIO_REMAKE_AUDIO_BUFFER");
3686 audio_queue_send(Q_AUDIO_REMAKE_AUDIO_BUFFER, 0);
3687 }
3688}
3689#endif /* HAVE_CROSSFADE */
2261 3690
2262 case SYS_TIMEOUT:
2263 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2264 break;
2265 3691
2266 default: 3692/** -- Startup -- **/
2267 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2268 break;
2269 } /* end switch */
2270 } /* end while */
2271}
2272 3693
2273/* Initialize the audio system - called from init() in main.c. 3694/* Initialize the audio system - called from init() in main.c */
2274 * Last function because of all the references to internal symbols
2275 */
2276void audio_init(void) 3695void audio_init(void)
2277{ 3696{
2278 unsigned int audio_thread_id;
2279
2280 /* Can never do this twice */ 3697 /* Can never do this twice */
2281 if (audio_is_initialized) 3698 if (audio_is_initialized)
2282 { 3699 {
@@ -2290,31 +3707,20 @@ void audio_init(void)
2290 to send messages. Thread creation will be delayed however so nothing 3707 to send messages. Thread creation will be delayed however so nothing
2291 starts running until ready if something yields such as talk_init. */ 3708 starts running until ready if something yields such as talk_init. */
2292 queue_init(&audio_queue, true); 3709 queue_init(&audio_queue, true);
2293 queue_init(&pcmbuf_queue, false); 3710
3711 mutex_init(&id3_mutex);
2294 3712
2295 pcm_init(); 3713 pcm_init();
2296 3714
2297 codec_init_codec_api(); 3715 codec_init_codec_api();
2298 3716
2299 thistrack_id3 = &mp3entry_buf[0];
2300 othertrack_id3 = &mp3entry_buf[1];
2301
2302 /* cuesheet support */
2303 if (global_settings.cuesheet)
2304 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2305
2306 /* initialize the buffer */
2307 filebuf = audiobuf;
2308
2309 /* audio_reset_buffer must to know the size of voice buffer so init
2310 talk first */
2311 talk_init();
2312
2313 make_codec_thread(); 3717 make_codec_thread();
2314 3718
3719 /* This thread does buffer, so match its priority */
2315 audio_thread_id = create_thread(audio_thread, audio_stack, 3720 audio_thread_id = create_thread(audio_thread, audio_stack,
2316 sizeof(audio_stack), CREATE_THREAD_FROZEN, 3721 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2317 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) 3722 audio_thread_name
3723 IF_PRIO(, MIN(PRIORITY_BUFFERING, PRIORITY_USER_INTERFACE))
2318 IF_COP(, CPU)); 3724 IF_COP(, CPU));
2319 3725
2320 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list, 3726 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
@@ -2324,39 +3730,21 @@ void audio_init(void)
2324 voice_thread_init(); 3730 voice_thread_init();
2325#endif 3731#endif
2326 3732
3733 /* audio_reset_buffer must to know the size of voice buffer so init
3734 talk first */
3735 talk_init();
3736
2327#ifdef HAVE_CROSSFADE 3737#ifdef HAVE_CROSSFADE
2328 /* Set crossfade setting for next buffer init which should be about... */ 3738 /* Set crossfade setting for next buffer init which should be about... */
2329 pcmbuf_request_crossfade_enable(global_settings.crossfade); 3739 pcmbuf_request_crossfade_enable(global_settings.crossfade);
2330#endif 3740#endif
2331 3741
2332 /* initialize the buffering system */ 3742 /* Initialize the buffering system */
2333 3743 track_list_init();
2334 buffering_init(); 3744 buffering_init();
2335 /* ...now! Set up the buffers */ 3745 /* ...now! Set up the buffers */
2336 audio_reset_buffer(); 3746 audio_reset_buffer();
2337 3747
2338 int i;
2339 for(i = 0; i < MAX_TRACK; i++)
2340 {
2341 tracks[i].audio_hid = -1;
2342 tracks[i].id3_hid = -1;
2343 tracks[i].codec_hid = -1;
2344 tracks[i].cuesheet_hid = -1;
2345 }
2346#ifdef HAVE_ALBUMART
2347 FOREACH_ALBUMART(i)
2348 {
2349 int j;
2350 for (j = 0; j < MAX_TRACK; j++)
2351 {
2352 tracks[j].aa_hid[i] = -1;
2353 }
2354 }
2355#endif
2356
2357 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2358 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2359
2360 /* Probably safe to say */ 3748 /* Probably safe to say */
2361 audio_is_initialized = true; 3749 audio_is_initialized = true;
2362 3750
@@ -2365,26 +3753,10 @@ void audio_init(void)
2365 audio_set_buffer_margin(global_settings.buffer_margin); 3753 audio_set_buffer_margin(global_settings.buffer_margin);
2366#endif 3754#endif
2367 3755
2368 /* it's safe to let the threads run now */ 3756 /* It's safe to let the threads run now */
2369#ifdef PLAYBACK_VOICE 3757#ifdef PLAYBACK_VOICE
2370 voice_thread_resume(); 3758 voice_thread_resume();
2371#endif 3759#endif
2372 codec_thread_resume(); 3760 codec_thread_resume();
2373 thread_thaw(audio_thread_id); 3761 thread_thaw(audio_thread_id);
2374
2375} /* audio_init */
2376
2377bool audio_is_thread_ready(void)
2378{
2379 return audio_thread_ready;
2380}
2381
2382size_t audio_get_filebuflen(void)
2383{
2384 return filebuflen;
2385}
2386
2387int get_audio_hid()
2388{
2389 return CUR_TI->audio_hid;
2390} 3762}