1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005-2007 Miika Pekkarinen
11 * Copyright (C) 2007-2008 Nicolas Pennequin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
24 * play whilst audio is paused */
29 #include "codec_thread.h"
32 #include "buffering.h"
33 #include "voice_thread.h"
43 #ifdef HAVE_LCD_BITMAP
55 #include "pcm_record.h"
58 #define PLAYBACK_VOICE
60 /* amount of guess-space to allow for codecs that must hunt and peck
61 * for their correct seeek target, 32k seems a good size */
62 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
64 /* Define LOGF_ENABLE to enable logf output in this file */
65 /*#define LOGF_ENABLE*/
68 /* macros to enable logf for queues
69 logging on SYS_TIMEOUT can be disabled */
71 /* Define this for logf output of all queuing except SYS_TIMEOUT */
72 #define PLAYBACK_LOGQUEUES
73 /* Define this to logf SYS_TIMEOUT messages */
74 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
77 #ifdef PLAYBACK_LOGQUEUES
78 #define LOGFQUEUE logf
80 #define LOGFQUEUE(...)
83 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
84 #define LOGFQUEUE_SYS_TIMEOUT logf
86 #define LOGFQUEUE_SYS_TIMEOUT(...)
90 static enum filling_state
{
91 STATE_IDLE
, /* audio is stopped: nothing to do */
92 STATE_FILLING
, /* adding tracks to the buffer */
93 STATE_FULL
, /* can't add any more tracks */
94 STATE_END_OF_PLAYLIST
, /* all remaining tracks have been added */
95 STATE_FINISHED
, /* all remaining tracks are fully buffered */
96 STATE_ENDING
, /* audio playback is ending */
97 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
98 STATE_USB
, /* USB mode, ignore most messages */
102 /* As defined in plugins/lib/xxx2wav.h */
103 #define GUARD_BUFSIZE (32*1024)
105 bool audio_is_initialized
= false;
106 static bool audio_thread_ready SHAREDBSS_ATTR
= false;
108 /* Variables are commented with the threads that use them: *
109 * A=audio, C=codec, V=voice. A suffix of - indicates that *
110 * the variable is read but not updated on that thread. */
111 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
113 /* Main state control */
114 static volatile bool playing SHAREDBSS_ATTR
= false;/* Is audio playing? (A) */
115 static volatile bool paused SHAREDBSS_ATTR
= false; /* Is audio paused? (A/C-) */
117 /* Ring buffer where compressed audio and codecs are loaded */
118 static unsigned char *filebuf
= NULL
; /* Start of buffer (A/C-) */
119 static size_t filebuflen
= 0; /* Size of buffer (A/C-) */
120 /* FIXME: make buf_ridx (C/A-) */
122 /* Possible arrangements of the buffer */
123 enum audio_buffer_state
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 */
129 static int buffer_state
= AUDIOBUF_STATE_TRASHED
; /* Buffer state */
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 */
135 static struct mp3entry mp3entry_buf
[2];
136 struct mp3entry
*thistrack_id3
, /* the currently playing track */
137 *othertrack_id3
; /* prev track during track-change-transition, or end of playlist,
138 * next track otherwise */
139 static struct mp3entry unbuffered_id3
; /* the id3 for the first unbuffered track */
141 /* for cuesheet support */
142 static struct cuesheet
*curr_cue
= NULL
;
145 #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
149 static struct albumart_slot
{
150 struct dim dim
; /* holds width, height of the albumart */
151 int used
; /* counter, increments if something uses it */
152 } albumart_slots
[MAX_MULTIPLE_AA
];
154 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
158 #define MAX_TRACK 128
159 #define MAX_TRACK_MASK (MAX_TRACK-1)
161 /* Track info structure about songs in the file buffer (A/C-) */
162 static struct track_info
{
163 int audio_hid
; /* The ID for the track's buffer handle */
164 int id3_hid
; /* The ID for the track's metadata handle */
165 int codec_hid
; /* The ID for the track's codec handle */
167 int aa_hid
[MAX_MULTIPLE_AA
];/* The ID for the track's album art handle */
169 int cuesheet_hid
; /* The ID for the track's parsed cueesheet handle */
171 size_t filesize
; /* File total length */
173 bool taginfo_ready
; /* Is metadata read */
177 static volatile int track_ridx
= 0; /* Track being decoded (A/C-) */
178 static int track_widx
= 0; /* Track being buffered (A) */
179 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
181 static struct track_info
*prev_ti
= NULL
; /* Pointer to the previously played
184 /* Information used only for filling the buffer */
185 /* Playlist steps from playing track to next track to be buffered (A) */
186 static int last_peek_offset
= 0;
188 /* Scrobbler support */
189 static unsigned long prev_track_elapsed
= 0; /* Previous track elapsed time (C/A-)*/
191 /* Track change controls */
192 static bool automatic_skip
= false; /* Who initiated in-progress skip? (A) */
193 extern bool track_transition
; /* Are we in a track transition? */
194 static bool dir_skip
= false; /* Is a directory skip pending? (A) */
195 static bool new_playlist
= false; /* Are we starting a new playlist? (A) */
196 static int wps_offset
= 0; /* Pending track change offset, to keep WPS responsive (A) */
197 static bool skipped_during_pause
= false; /* Do we need to clear the PCM buffer when playback resumes (A) */
199 static bool start_play_g
= false; /* Used by audio_load_track to notify
200 audio_finish_load_track about start_play */
202 /* True when a track load is in progress, i.e. audio_load_track() has returned
203 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
204 * audio_load_track() to get called twice in a row, which would cause problems.
206 static bool track_load_started
= false;
208 #ifdef HAVE_DISK_STORAGE
209 static size_t buffer_margin
= 5; /* Buffer margin aka anti-skip buffer (A/C-) */
213 struct event_queue audio_queue SHAREDBSS_ATTR
;
214 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR
;
216 extern struct codec_api ci
;
217 extern unsigned int codec_thread_id
;
219 /* Multiple threads */
220 /* Set the watermark to trigger buffer fill (A/C) */
221 static void set_filebuf_watermark(void);
224 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR
;
225 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
226 static const char audio_thread_name
[] = "audio";
228 static void audio_thread(void);
229 static void audio_initiate_track_change(long direction
);
230 static bool audio_have_tracks(void);
231 static void audio_reset_buffer(void);
232 static void audio_stop_playback(void);
234 /**************************************/
236 /** Pcmbuf callbacks */
238 /* Between the codec and PCM track change, we need to keep updating the
239 * "elapsed" value of the previous (to the codec, but current to the
240 * user/PCM/WPS) track, so that the progressbar reaches the end.
241 * During that transition, the WPS will display othertrack_id3. */
242 void audio_pcmbuf_position_callback(unsigned int time
)
244 time
+= othertrack_id3
->elapsed
;
245 othertrack_id3
->elapsed
= (time
>= othertrack_id3
->length
)
246 ? othertrack_id3
->length
: time
;
249 /* Post message from pcmbuf that the end of the previous track
250 * has just been played. */
251 void audio_post_track_change(bool pcmbuf
)
255 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
256 queue_post(&pcmbuf_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
260 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
261 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
265 /* Scan the pcmbuf queue and return true if a message pulled */
266 static bool pcmbuf_queue_scan(struct queue_event
*ev
)
268 if (!queue_empty(&pcmbuf_queue
))
270 /* Transfer message to audio queue */
272 /* Pull message - never, ever any blocking call! */
273 queue_wait_w_tmo(&pcmbuf_queue
, ev
, 0);
282 /** Helper functions */
284 static struct mp3entry
*bufgetid3(int handle_id
)
289 struct mp3entry
*id3
;
290 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
292 if (ret
!= sizeof(struct mp3entry
))
298 static bool bufreadid3(int handle_id
, struct mp3entry
*id3out
)
300 struct mp3entry
*id3
= bufgetid3(handle_id
);
304 copy_mp3entry(id3out
, id3
);
311 static bool clear_track_info(struct track_info
*track
)
313 /* bufclose returns true if the handle is not found, or if it is closed
314 * successfully, so these checks are safe on non-existant handles */
318 if (track
->codec_hid
>= 0) {
319 if (bufclose(track
->codec_hid
))
320 track
->codec_hid
= -1;
325 if (track
->id3_hid
>= 0) {
326 if (bufclose(track
->id3_hid
))
332 if (track
->audio_hid
>= 0) {
333 if (bufclose(track
->audio_hid
))
334 track
->audio_hid
= -1;
344 if (track
->aa_hid
[i
] >= 0) {
345 if (bufclose(track
->aa_hid
[i
]))
346 track
->aa_hid
[i
] = -1;
354 if (track
->cuesheet_hid
>= 0) {
355 if (bufclose(track
->cuesheet_hid
))
356 track
->cuesheet_hid
= -1;
362 track
->taginfo_ready
= false;
367 /* --- External interfaces --- */
369 /* This sends a stop message and the audio thread will dump all it's
370 subsequenct messages */
371 void audio_hard_stop(void)
374 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
375 queue_send(&audio_queue
, Q_AUDIO_STOP
, 1);
376 #ifdef PLAYBACK_VOICE
381 bool audio_restore_playback(int type
)
385 case AUDIO_WANT_PLAYBACK
:
386 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
387 audio_reset_buffer();
389 case AUDIO_WANT_VOICE
:
390 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
391 audio_reset_buffer();
398 unsigned char *audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
400 unsigned char *buf
, *end
;
402 if (audio_is_initialized
)
406 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
408 /* Reset the buffering thread so that it doesn't try to use the data */
409 buffering_reset(filebuf
, filebuflen
);
411 if (buffer_size
== NULL
)
413 /* Special case for talk_init to use since it already knows it's
415 buffer_state
= AUDIOBUF_STATE_TRASHED
;
419 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
420 || !talk_voice_required())
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.
431 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
434 buffer_state
= AUDIOBUF_STATE_TRASHED
;
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
447 logf("get buffer: audio");
448 buf
= audiobuf
+ talk_get_bufsize();
449 end
= audiobufend
- pcmbuf_init(audiobufend
);
450 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
453 *buffer_size
= end
- buf
;
458 bool audio_buffer_state_trashed(void)
460 return buffer_state
== AUDIOBUF_STATE_TRASHED
;
463 #ifdef HAVE_RECORDING
464 unsigned char *audio_get_recording_buffer(size_t *buffer_size
)
466 /* Stop audio, voice and obtain all available buffer space */
470 unsigned char *end
= audiobufend
;
471 buffer_state
= AUDIOBUF_STATE_TRASHED
;
472 *buffer_size
= end
- audiobuf
;
474 return (unsigned char *)audiobuf
;
477 bool audio_load_encoder(int afmt
)
479 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
480 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
481 return queue_send(&audio_queue
, Q_AUDIO_LOAD_ENCODER
, afmt
) > 0;
486 } /* audio_load_encoder */
488 void audio_remove_encoder(void)
490 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
491 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
492 queue_send(&audio_queue
, Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
494 } /* audio_remove_encoder */
496 #endif /* HAVE_RECORDING */
499 struct mp3entry
* audio_current_track(void)
501 const char *filename
;
502 struct playlist_track_info trackinfo
;
504 int offset
= ci
.new_track
+ wps_offset
;
505 struct mp3entry
*write_id3
;
507 cur_idx
= (track_ridx
+ offset
) & MAX_TRACK_MASK
;
509 if (cur_idx
== track_ridx
&& *thistrack_id3
->path
)
512 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
514 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
515 thistrack_id3
->cuesheet
= curr_cue
;
517 return thistrack_id3
;
519 else if (automatic_skip
&& offset
== -1 && *othertrack_id3
->path
)
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
)
527 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
528 othertrack_id3
->cuesheet
= curr_cue
;
530 return othertrack_id3
;
535 /* Codec may be using thistrack_id3, so it must not be overwritten.
536 If this is a manual skip, othertrack_id3 will become
537 thistrack_id3 in audio_check_new_track().
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.
543 write_id3
= othertrack_id3
;
547 write_id3
= thistrack_id3
;
550 if (tracks
[cur_idx
].id3_hid
>= 0)
552 /* The current track's info has been buffered but not read yet, so get it */
553 if (bufreadid3(tracks
[cur_idx
].id3_hid
, write_id3
))
557 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
558 we have and return that. */
560 memset(write_id3
, 0, sizeof(struct mp3entry
));
562 playlist_get_track_info(NULL
, playlist_next(0)+wps_offset
, &trackinfo
);
563 filename
= trackinfo
.filename
;
565 filename
= "No file!";
567 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
568 if (tagcache_fill_tags(write_id3
, filename
))
572 strlcpy(write_id3
->path
, filename
, sizeof(write_id3
->path
));
573 write_id3
->title
= strrchr(write_id3
->path
, '/');
574 if (!write_id3
->title
)
575 write_id3
->title
= &write_id3
->path
[0];
582 struct mp3entry
* audio_next_track(void)
585 int offset
= ci
.new_track
+ wps_offset
;
587 if (!audio_have_tracks())
590 if (wps_offset
== -1 && *thistrack_id3
->path
)
592 /* We're in a track transition. The next track for the WPS is the one
593 currently being decoded. */
594 return thistrack_id3
;
597 next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
599 if (tracks
[next_idx
].id3_hid
>= 0)
601 if (bufreadid3(tracks
[next_idx
].id3_hid
, othertrack_id3
))
602 return othertrack_id3
;
607 if (next_idx
== track_widx
)
609 /* The next track hasn't been buffered yet, so we return the static
610 version of its metadata. */
611 return &unbuffered_id3
;
617 /* gets a copy of the id3 data */
618 bool audio_peek_track(struct mp3entry
* id3
, int offset
)
621 int new_offset
= ci
.new_track
+ wps_offset
+ offset
;
623 if (!audio_have_tracks())
625 next_idx
= (track_ridx
+ new_offset
) & MAX_TRACK_MASK
;
627 if (tracks
[next_idx
].id3_hid
>= 0)
628 return bufreadid3(tracks
[next_idx
].id3_hid
, id3
);
635 int playback_current_aa_hid(int slot
)
640 int offset
= ci
.new_track
+ wps_offset
;
642 cur_idx
= track_ridx
+ offset
;
643 cur_idx
&= MAX_TRACK_MASK
;
644 return tracks
[cur_idx
].aa_hid
[slot
];
647 int playback_claim_aa_slot(struct dim
*dim
)
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 */
655 struct albumart_slot
*slot
= &albumart_slots
[i
];
656 if (slot
->dim
.width
== dim
->width
657 && slot
->dim
.height
== dim
->height
)
663 /* size is new, find a free slot */
666 if (!albumart_slots
[i
].used
)
668 albumart_slots
[i
].used
++;
669 albumart_slots
[i
].dim
= *dim
;
673 /* sorry, no free slot */
677 void playback_release_aa_slot(int slot
)
679 /* invalidate the albumart_slot */
680 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
682 if (aa_slot
->used
> 0)
687 void audio_play(long offset
)
691 #ifdef PLAYBACK_VOICE
692 /* Truncate any existing voice output so we don't have spelling
693 * etc. over the first part of the played track */
698 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
699 /* Don't return until playback has actually started */
700 queue_send(&audio_queue
, Q_AUDIO_PLAY
, offset
);
703 void audio_stop(void)
706 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
707 /* Don't return until playback has actually stopped */
708 queue_send(&audio_queue
, Q_AUDIO_STOP
, 0);
711 void audio_pause(void)
713 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
714 /* Don't return until playback has actually paused */
715 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, true);
718 void audio_resume(void)
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);
725 void audio_skip(int direction
)
727 if (playlist_check(ci
.new_track
+ wps_offset
+ direction
))
729 if (global_settings
.beep
)
730 pcmbuf_beep(2000, 100, 2500*global_settings
.beep
);
732 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction
);
733 queue_post(&audio_queue
, Q_AUDIO_SKIP
, direction
);
734 /* Update wps while our message travels inside deep playback queues. */
735 wps_offset
+= direction
;
739 /* No more tracks. */
740 if (global_settings
.beep
)
741 pcmbuf_beep(1000, 100, 1500*global_settings
.beep
);
745 void audio_next(void)
750 void audio_prev(void)
755 void audio_next_dir(void)
757 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
758 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, 1);
761 void audio_prev_dir(void)
763 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
764 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, -1);
767 void audio_pre_ff_rewind(void)
769 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
770 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
773 void audio_ff_rewind(long newpos
)
775 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
776 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, newpos
);
779 void audio_flush_and_reload_tracks(void)
781 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
782 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
785 void audio_error_clear(void)
787 #ifdef AUDIO_HAVE_RECORDING
788 pcm_rec_error_clear();
792 int audio_status(void)
797 ret
|= AUDIO_STATUS_PLAY
;
800 ret
|= AUDIO_STATUS_PAUSE
;
802 #ifdef HAVE_RECORDING
803 /* Do this here for constitency with mpeg.c version */
804 /* FIXME: pcm_rec_status() is deprecated */
805 ret
|= pcm_rec_status();
811 bool audio_automatic_skip(void)
813 return automatic_skip
;
816 int audio_get_file_pos(void)
821 #ifdef HAVE_DISK_STORAGE
822 void audio_set_buffer_margin(int setting
)
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();
831 #ifdef HAVE_CROSSFADE
832 /* Take necessary steps to enable or disable the crossfade setting */
833 void audio_set_crossfade(int enable
)
839 /* Tell it the next setting to use */
840 pcmbuf_request_crossfade_enable(enable
);
842 /* Return if size hasn't changed or this is too early to determine
843 which in the second case there's no way we could be playing
845 if (pcmbuf_is_same_size()) return;
848 was_playing
= playing
;
850 /* Playback has to be stopped before changing the buffer size */
853 /* Store the track resume position */
854 offset
= thistrack_id3
->offset
;
857 /* Blast it - audio buffer will have to be setup again next time
859 audio_get_buffer(true, &size
);
861 /* Restart playback if audio was running previously */
867 /* --- Routines called from multiple threads --- */
869 static void set_filebuf_watermark(void)
872 return; /* Audio buffers not yet set up */
874 #ifdef HAVE_DISK_STORAGE
876 int spinup
= ata_spinup_time();
878 seconds
= (spinup
/ HZ
) + 1;
882 seconds
+= buffer_margin
;
888 /* bitrate of last track in buffer dictates watermark */
889 struct mp3entry
* id3
= NULL
;
890 if (tracks
[track_widx
].taginfo_ready
)
891 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
893 id3
= bufgetid3(tracks
[track_widx
-1].id3_hid
);
895 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx
, track_widx
);
898 size_t bytes
= id3
->bitrate
* (1000/8) * seconds
;
899 buf_set_watermark(bytes
);
900 logf("fwmark: %d", bytes
);
903 /* --- Buffering callbacks --- */
905 static void buffering_low_buffer_callback(void *data
)
908 logf("low buffer callback");
910 if (filling
== STATE_FULL
|| filling
== STATE_END_OF_PLAYLIST
) {
912 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
913 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
917 static void buffering_handle_rebuffer_callback(void *data
)
920 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
921 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
924 static void buffering_handle_finished_callback(void *data
)
926 logf("handle %d finished buffering", *(int*)data
);
927 int hid
= (*(int*)data
);
929 if (hid
== tracks
[track_widx
].id3_hid
)
931 int offset
= ci
.new_track
+ wps_offset
;
932 int next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
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
);
942 /* This is most likely an audio handle, so we strip the useless
943 trailing tags that are left. */
946 if (hid
== tracks
[track_widx
-1].audio_hid
947 && filling
== STATE_END_OF_PLAYLIST
)
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
;
958 /* --- Audio thread --- */
960 static bool audio_have_tracks(void)
962 return (audio_track_count() != 0);
965 static int audio_free_track_count(void)
967 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
968 return MAX_TRACK
- 1 - audio_track_count();
971 int audio_track_count(void)
973 /* Calculate difference from track_ridx to track_widx
974 * taking into account a possible wrap-around. */
975 return (MAX_TRACK
+ track_widx
- track_ridx
) & MAX_TRACK_MASK
;
978 long audio_filebufused(void)
980 return (long) buf_used();
983 /* Update track info after successful a codec track change */
984 static void audio_update_trackinfo(void)
988 /* Load the curent track's metadata into curtrack_id3 */
989 if (CUR_TI
->id3_hid
>= 0)
990 bufreadid3(CUR_TI
->id3_hid
, thistrack_id3
);
992 /* Reset current position */
993 thistrack_id3
->elapsed
= 0;
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? */
1007 thistrack_id3
->offset
= 0;
1010 logf("audio_update_trackinfo: Set offset for %s to %lX\n",
1011 thistrack_id3
->title
, thistrack_id3
->offset
);
1013 /* Update the codec API */
1014 ci
.filesize
= CUR_TI
->filesize
;
1015 ci
.id3
= thistrack_id3
;
1017 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1020 /* Clear tracks between write and read, non inclusive */
1021 static void audio_clear_track_entries(void)
1023 int cur_idx
= track_widx
;
1025 logf("Clearing tracks: r%d/w%d", track_ridx
, track_widx
);
1027 /* Loop over all tracks from write-to-read */
1030 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1032 if (cur_idx
== track_ridx
)
1035 clear_track_info(&tracks
[cur_idx
]);
1039 /* Clear all tracks */
1040 static bool audio_release_tracks(void)
1044 logf("releasing all tracks");
1046 for(i
= 0; i
< MAX_TRACK
; i
++)
1048 cur_idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1049 if (!clear_track_info(&tracks
[cur_idx
]))
1056 static bool audio_loadcodec(bool start_play
)
1058 int prev_track
, hid
;
1059 char codec_path
[MAX_PATH
]; /* Full path to codec */
1060 const struct mp3entry
*id3
, *prev_id3
;
1062 if (tracks
[track_widx
].id3_hid
< 0) {
1066 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1070 const char *codec_fn
= get_codec_filename(id3
->codectype
);
1071 if (codec_fn
== NULL
)
1074 tracks
[track_widx
].codec_hid
= -1;
1078 /* Load the codec directly from disk and save some memory. */
1079 track_ridx
= track_widx
;
1080 ci
.filesize
= CUR_TI
->filesize
;
1081 ci
.id3
= thistrack_id3
;
1082 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1084 return codec_load(-1, id3
->codectype
);
1088 /* If we already have another track than this one buffered */
1089 if (track_widx
!= track_ridx
)
1091 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
1093 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1094 prev_id3
= bufgetid3(tracks
[prev_track
].id3_hid
);
1096 /* If the previous codec is the same as this one and the current
1097 * one is the correct one, there is no need to put another copy of
1098 * it on the file buffer */
1099 if (id3
&& prev_id3
)
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());
1105 if (codt
== prev_codt
&& codt
== cod_loaded
)
1107 logf("Reusing prev. codec");
1114 codec_get_full_path(codec_path
, codec_fn
);
1116 hid
= tracks
[track_widx
].codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1118 /* not an error if codec load it supported, will load it from disk
1119 * application builds don't support it
1121 if (hid
< 0 && hid
!= ERR_UNSUPPORTED_TYPE
)
1125 logf("Loaded codec");
1127 logf("Buffering codec unsupported, load later from disk");
1132 /* Load metadata for the next track (with bufopen). The rest of the track
1133 loading will be handled by audio_finish_load_track once the metadata has been
1134 actually loaded by the buffering thread. */
1135 static bool audio_load_track(size_t offset
, bool start_play
)
1137 char name_buf
[MAX_PATH
+ 1];
1138 const char *trackname
;
1141 if (track_load_started
) {
1142 /* There is already a track load in progress, so track_widx hasn't been
1143 incremented yet. Loading another track would overwrite the one that
1144 hasn't finished loading. */
1145 logf("audio_load_track(): a track load is already in progress");
1149 start_play_g
= start_play
; /* will be read by audio_finish_load_track */
1151 /* Stop buffer filling if there is no free track entries.
1152 Don't fill up the last track entry (we wan't to store next track
1154 if (!audio_free_track_count())
1156 logf("No free tracks");
1161 tracks
[track_widx
].taginfo_ready
= false;
1163 logf("Buffering track: r%d/w%d", track_ridx
, track_widx
);
1164 /* Get track name from current playlist read position. */
1165 while ((trackname
= playlist_peek(last_peek_offset
, name_buf
,
1166 sizeof(name_buf
))) != NULL
)
1168 /* Handle broken playlists. */
1169 fd
= open(trackname
, O_RDONLY
);
1172 logf("Open failed");
1173 /* Skip invalid entry from playlist. */
1174 playlist_skip_entry(NULL
, last_peek_offset
);
1182 logf("End-of-playlist");
1183 memset(&unbuffered_id3
, 0, sizeof(struct mp3entry
));
1184 filling
= STATE_END_OF_PLAYLIST
;
1186 if (thistrack_id3
->length
== 0 && thistrack_id3
->filesize
== 0)
1188 /* Stop playback if no valid track was found. */
1189 audio_stop_playback();
1195 tracks
[track_widx
].filesize
= filesize(fd
);
1197 if (offset
> tracks
[track_widx
].filesize
)
1200 /* Set default values */
1203 buf_set_watermark(filebuflen
/2);
1204 dsp_configure(ci
.dsp
, DSP_RESET
, 0);
1205 playlist_update_resume_info(audio_current_track());
1208 /* Get track metadata if we don't already have it. */
1209 if (tracks
[track_widx
].id3_hid
< 0)
1211 tracks
[track_widx
].id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
);
1213 if (tracks
[track_widx
].id3_hid
< 0)
1215 /* Buffer is full. */
1216 get_metadata(&unbuffered_id3
, fd
, trackname
);
1219 logf("buffer is full for now (get metadata)");
1220 filling
= STATE_FULL
;
1224 if (track_widx
== track_ridx
)
1226 /* TODO: Superfluos buffering call? */
1227 buf_request_buffer_handle(tracks
[track_widx
].id3_hid
);
1228 if (bufreadid3(tracks
[track_widx
].id3_hid
, thistrack_id3
))
1230 thistrack_id3
->offset
= offset
;
1231 logf("audio_load_track: set offset for %s to %lX\n",
1232 thistrack_id3
->title
,
1236 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1241 playlist_update_resume_info(audio_current_track());
1246 track_load_started
= true; /* Remember that we've started loading a track */
1250 #ifdef HAVE_ALBUMART
1251 /* Load any album art for the file */
1252 static void audio_load_albumart(struct mp3entry
*track_id3
)
1258 struct bufopen_bitmap_data user_data
;
1259 int hid
= ERR_HANDLE_NOT_FOUND
;
1261 /* albumart_slots may change during a yield of bufopen,
1262 * but that's no problem */
1263 if (tracks
[track_widx
].aa_hid
[i
] >= 0 || !albumart_slots
[i
].used
)
1266 memset(&user_data
, 0, sizeof(user_data
));
1267 user_data
.dim
= &(albumart_slots
[i
].dim
);
1269 /* we can only decode jpeg for embedded AA */
1270 if (track_id3
->embed_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1272 user_data
.embedded_albumart
= &(track_id3
->albumart
);
1273 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1276 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1278 /* no embedded AA or it couldn't be loaded, try other sources */
1279 char path
[MAX_PATH
];
1281 if (find_albumart(track_id3
, path
, sizeof(path
),
1282 &(albumart_slots
[i
].dim
)))
1284 user_data
.embedded_albumart
= NULL
;
1285 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1289 if (hid
== ERR_BUFFER_FULL
)
1291 filling
= STATE_FULL
;
1292 logf("buffer is full for now (get album art)");
1296 logf("Album art loading failed");
1299 tracks
[track_widx
].aa_hid
[i
] = hid
;
1304 /* Second part of the track loading: We now have the metadata available, so we
1305 can load the codec, the album art and finally the audio data.
1306 This is called on the audio thread after the buffering thread calls the
1307 buffering_handle_finished_callback callback. */
1308 static void audio_finish_load_track(void)
1310 size_t file_offset
= 0;
1312 bool start_play
= start_play_g
;
1314 track_load_started
= false;
1316 if (tracks
[track_widx
].id3_hid
< 0) {
1317 logf("No metadata");
1321 struct mp3entry
*track_id3
;
1323 if (track_widx
== track_ridx
)
1324 track_id3
= thistrack_id3
;
1326 track_id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1328 if (track_id3
->length
== 0 && track_id3
->filesize
== 0)
1330 logf("audio_finish_load_track: invalid metadata");
1332 /* Invalid metadata */
1333 bufclose(tracks
[track_widx
].id3_hid
);
1334 tracks
[track_widx
].id3_hid
= -1;
1336 /* Skip invalid entry from playlist. */
1337 playlist_skip_entry(NULL
, last_peek_offset
--);
1339 /* load next track */
1340 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play
);
1341 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, start_play
);
1345 /* Try to load a cuesheet for the track */
1348 char cuepath
[MAX_PATH
];
1349 if (look_for_cuesheet_file(track_id3
->path
, cuepath
))
1352 tracks
[track_widx
].cuesheet_hid
=
1353 bufalloc(NULL
, sizeof(struct cuesheet
), TYPE_CUESHEET
);
1354 if (tracks
[track_widx
].cuesheet_hid
>= 0)
1356 bufgetdata(tracks
[track_widx
].cuesheet_hid
,
1357 sizeof(struct cuesheet
), &temp
);
1358 struct cuesheet
*cuesheet
= (struct cuesheet
*)temp
;
1359 if (!parse_cuesheet(cuepath
, cuesheet
))
1361 bufclose(tracks
[track_widx
].cuesheet_hid
);
1362 track_id3
->cuesheet
= NULL
;
1368 #ifdef HAVE_ALBUMART
1369 audio_load_albumart(track_id3
);
1372 /* Load the codec. */
1373 if (!audio_loadcodec(start_play
))
1375 if (tracks
[track_widx
].codec_hid
== ERR_BUFFER_FULL
)
1377 /* No space for codec on buffer, not an error */
1378 filling
= STATE_FULL
;
1382 /* This is an error condition, either no codec was found, or reading
1383 * the codec file failed part way through, either way, skip the track */
1384 /* FIXME: We should not use splashf from audio thread! */
1385 splashf(HZ
*2, "No codec for: %s", track_id3
->path
);
1386 /* Skip invalid entry from playlist. */
1387 playlist_skip_entry(NULL
, last_peek_offset
);
1391 track_id3
->elapsed
= 0;
1392 offset
= track_id3
->offset
;
1393 size_t resume_rewind
= (global_settings
.resume_rewind
*
1394 track_id3
->bitrate
* 1000) / 8;
1396 if (offset
< resume_rewind
)
1402 offset
-= resume_rewind
;
1405 enum data_type type
= TYPE_PACKET_AUDIO
;
1407 switch (track_id3
->codectype
) {
1412 file_offset
= offset
;
1418 file_offset
= offset
;
1419 track_id3
->elapsed
= track_id3
->length
/ 2;
1426 logf("Loading atomic %d",track_id3
->codectype
);
1427 type
= TYPE_ATOMIC_AUDIO
;
1431 /* no special treatment needed */
1435 track_id3
->offset
= offset
;
1437 logf("load track: %s", track_id3
->path
);
1439 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1440 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1441 else if (track_id3
->first_frame_offset
)
1442 file_offset
= track_id3
->first_frame_offset
;
1446 tracks
[track_widx
].audio_hid
= bufopen(track_id3
->path
, file_offset
, type
,
1449 /* No space left, not an error */
1450 if (tracks
[track_widx
].audio_hid
== ERR_BUFFER_FULL
)
1452 filling
= STATE_FULL
;
1453 logf("buffer is full for now (load audio)");
1456 else if (tracks
[track_widx
].audio_hid
< 0)
1458 /* another error, do not continue either */
1459 logf("Could not add audio data handle");
1463 /* All required data is now available for the codec -- unless the
1464 autoresume feature is in effect. In the latter case, the codec
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
)
1470 tracks
[track_widx
].taginfo_ready
= true;
1474 ci
.curpos
=file_offset
;
1475 buf_request_buffer_handle(tracks
[track_widx
].audio_hid
);
1478 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, track_id3
);
1480 #ifdef HAVE_TAGCACHE
1481 /* In case the autoresume feature has been enabled, finally all
1482 required data is available for the codec. */
1483 if (global_settings
.autoresume_enable
&& !offset
)
1484 tracks
[track_widx
].taginfo_ready
= true;
1487 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1489 /* load next track */
1490 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1491 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1496 static void audio_fill_file_buffer(bool start_play
, size_t offset
)
1498 trigger_cpu_boost();
1500 /* No need to rebuffer if there are track skips pending,
1501 * however don't cancel buffering on skipping while filling. */
1502 if (ci
.new_track
!= 0 && filling
!= STATE_FILLING
)
1504 filling
= STATE_FILLING
;
1506 /* 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
1508 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1509 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1510 audio_reset_buffer();
1512 logf("Starting buffer fill");
1515 audio_clear_track_entries();
1517 /* Save the current resume position once. */
1518 playlist_update_resume_info(audio_current_track());
1520 audio_load_track(offset
, start_play
);
1523 static void audio_rebuffer(void)
1525 logf("Forcing rebuffer");
1527 clear_track_info(CUR_TI
);
1529 /* Reset track pointers */
1530 track_widx
= track_ridx
;
1531 audio_clear_track_entries();
1533 /* Reset a possibly interrupted track load */
1534 track_load_started
= false;
1536 /* Fill the buffer */
1537 last_peek_offset
= -1;
1540 if (!CUR_TI
->taginfo_ready
)
1541 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1543 audio_fill_file_buffer(false, 0);
1546 /* Called on request from the codec to get a new track. This is the codec part
1547 of the track transition. */
1548 static void audio_last_track(bool automatic
)
1553 automatic_skip
= false;
1555 if (filling
!= STATE_ENDING
)
1557 /* Monitor remaining PCM before stopping */
1558 filling
= STATE_ENDING
;
1559 pcmbuf_monitor_track_change(true);
1566 audio_stop_playback();
1570 static void audio_check_new_track(void)
1576 struct mp3entry
*temp
;
1578 if (ci
.new_track
== 0)
1581 automatic_skip
= true;
1584 track_count
= audio_track_count();
1585 old_track_ridx
= track_ridx
;
1587 /* Now it's good time to send track finish events. */
1588 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
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
));
1599 /* regardless of the return value we need to rebuffer.
1600 if it fails the old playlist will resume, else the
1601 next dir will start playing */
1602 playlist_next_dir(ci
.new_track
);
1611 /* If the playlist isn't that big */
1614 while (!playlist_check(ci
.new_track
))
1616 if (ci
.new_track
>= 0)
1618 audio_last_track(true);
1625 /* Update the playlist */
1626 last_peek_offset
-= ci
.new_track
;
1628 if (playlist_next(ci
.new_track
) < 0)
1631 audio_last_track(automatic_skip
);
1638 new_playlist
= false;
1641 /* Save a pointer to the old track to allow later clearing */
1644 for (i
= 0; i
< ci
.new_track
; i
++)
1646 idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1647 struct mp3entry
*id3
= bufgetid3(tracks
[idx
].id3_hid
);
1648 ssize_t offset
= buf_handle_offset(tracks
[idx
].audio_hid
);
1649 if (!id3
|| offset
< 0 || (unsigned)offset
> id3
->first_frame_offset
)
1651 /* We don't have all the audio data for that track, so clear it,
1652 but keep the metadata. */
1653 if (tracks
[idx
].audio_hid
>= 0 && bufclose(tracks
[idx
].audio_hid
))
1655 tracks
[idx
].audio_hid
= -1;
1656 tracks
[idx
].filesize
= 0;
1661 /* Move to the new track */
1662 track_ridx
= (track_ridx
+ ci
.new_track
) & MAX_TRACK_MASK
;
1663 buf_set_base_handle(CUR_TI
->audio_hid
);
1667 wps_offset
= -ci
.new_track
;
1670 /* If it is not safe to even skip this many track entries */
1671 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
1678 forward
= ci
.new_track
> 0;
1681 /* If the target track is clearly not in memory */
1682 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
1688 /* When skipping backwards, it is possible that we've found a track that's
1689 * buffered, but which is around the track-wrap and therefore not the track
1690 * we are looking for */
1693 int cur_idx
= track_ridx
;
1694 bool taginfo_ready
= true;
1695 /* We've wrapped the buffer backwards if new > old */
1696 bool wrap
= track_ridx
> old_track_ridx
;
1700 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1702 /* if we've advanced past the wrap when cur_idx is zeroed */
1706 /* if we aren't still on the wrap and we've caught the old track */
1707 if (!(wrap
|| cur_idx
< old_track_ridx
))
1710 /* If we hit a track in between without valid tag info, bail */
1711 if (!tracks
[cur_idx
].taginfo_ready
)
1713 taginfo_ready
= false;
1724 audio_update_trackinfo();
1725 pcmbuf_start_track_change(automatic_skip
);
1727 if (get_codec_base_type(codec_loaded()) ==
1728 get_codec_base_type(thistrack_id3
->codectype
))
1730 /* codec is the same base type */
1731 logf("New track loaded");
1732 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE
, false);
1736 /* a codec change is required */
1737 logf("New codec: %d/%d", thistrack_id3
->codectype
, codec_loaded());
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 */
1744 unsigned long audio_prev_elapsed(void)
1746 return prev_track_elapsed
;
1749 void audio_set_prev_elapsed(unsigned long setting
)
1751 prev_track_elapsed
= setting
;
1754 /* Stop the codec and reset the PCM buffer */
1755 static void audio_stop_codec_flush(void)
1765 pcm_playing
= pcm_is_playing();
1768 queue_clear(&pcmbuf_queue
);
1771 pcmbuf_pause(paused
);
1776 static void audio_stop_playback(void)
1780 /* If we were playing, save resume information */
1781 struct mp3entry
*id3
= NULL
;
1784 id3
= audio_current_track();
1786 /* Save the current playing spot, or NULL if the playlist has ended */
1787 playlist_update_resume_info(id3
);
1789 /* Now it's good time to send track finish events. Do this
1790 only if this hasn't been done already as part of a track
1792 if (id3
== thistrack_id3
)
1793 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
1795 /* TODO: Create auto bookmark too? */
1797 prev_track_elapsed
= othertrack_id3
->elapsed
;
1799 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffering_low_buffer_callback
);
1802 audio_stop_codec_flush();
1805 track_load_started
= false;
1807 filling
= STATE_IDLE
;
1809 /* Mark all entries null. */
1810 audio_clear_track_entries();
1812 /* Close all tracks */
1813 audio_release_tracks();
1816 static void audio_play_start(size_t offset
)
1820 send_event(PLAYBACK_EVENT_START_PLAYBACK
, NULL
);
1821 #if INPUT_SRC_CAPS != 0
1822 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1823 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
1827 audio_stop_codec_flush();
1830 track_load_started
= false;
1836 #ifndef PLATFORM_HAS_VOLUME_CHANGE
1837 sound_set_volume(global_settings
.volume
);
1839 track_widx
= track_ridx
= 0;
1840 buf_set_base_handle(-1);
1842 /* Clear all track entries. */
1843 for (i
= 0; i
< MAX_TRACK
; i
++) {
1844 clear_track_info(&tracks
[i
]);
1847 last_peek_offset
= -1;
1849 /* Officially playing */
1850 queue_reply(&audio_queue
, 1);
1852 audio_fill_file_buffer(true, offset
);
1854 add_event(BUFFER_EVENT_BUFFER_LOW
, false, buffering_low_buffer_callback
);
1856 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1857 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1861 /* Invalidates all but currently playing track. */
1862 static void audio_invalidate_tracks(void)
1864 if (audio_have_tracks())
1866 last_peek_offset
= 0;
1867 track_widx
= track_ridx
;
1869 /* Mark all other entries null (also buffered wrong metadata). */
1870 audio_clear_track_entries();
1872 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1874 audio_fill_file_buffer(false, 0);
1875 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, thistrack_id3
);
1879 static void audio_new_playlist(void)
1881 /* Prepare to start a new fill from the beginning of the playlist */
1882 last_peek_offset
= -1;
1884 /* Signal the codec to initiate a track change forward */
1885 new_playlist
= true;
1888 if (audio_have_tracks())
1891 skipped_during_pause
= true;
1892 track_widx
= track_ridx
;
1893 audio_clear_track_entries();
1895 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1897 /* Mark the current track as invalid to prevent skipping back to it */
1898 CUR_TI
->taginfo_ready
= false;
1901 /* Officially playing */
1902 queue_reply(&audio_queue
, 1);
1904 audio_fill_file_buffer(false, 0);
1907 /* Called on manual track skip */
1908 static void audio_initiate_track_change(long direction
)
1910 logf("audio_initiate_track_change(%ld)", direction
);
1912 ci
.new_track
+= direction
;
1913 wps_offset
-= direction
;
1915 skipped_during_pause
= true;
1918 /* Called on manual dir skip */
1919 static void audio_initiate_dir_change(long direction
)
1922 ci
.new_track
= direction
;
1924 skipped_during_pause
= true;
1927 /* Called when PCM track change is complete */
1928 static void audio_finalise_track_change(void)
1930 logf("audio_finalise_track_change");
1935 automatic_skip
= false;
1937 /* Invalidate prevtrack_id3 */
1938 memset(othertrack_id3
, 0, sizeof(struct mp3entry
));
1940 if (prev_ti
&& prev_ti
->audio_hid
< 0)
1942 /* No audio left so we clear all the track info. */
1943 clear_track_info(prev_ti
);
1946 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, thistrack_id3
);
1947 playlist_update_resume_info(audio_current_track());
1950 static void audio_seek_complete(void)
1952 logf("audio_seek_complete");
1957 /* If seeking-while-playing, pcm_is_paused() is true.
1958 * If seeking-while-paused, audio_status PAUSE is true.
1959 * A seamless seek skips this section. */
1964 if (pcm_is_paused() || paused
)
1966 /* Clear the buffer */
1969 /* If seeking-while-playing, resume PCM playback */
1971 pcmbuf_pause(false);
1977 static void audio_codec_status_message(long reason
, int status
)
1979 /* TODO: Push the errors up to the normal UI somewhere */
1982 case Q_CODEC_LOAD_DISK
:
1989 splash(HZ
*2, "Codec failure");
1990 audio_check_new_track();
1994 #ifdef AUDIO_HAVE_RECORDING
1995 case Q_ENCODER_LOAD_DISK
:
1997 splash(HZ
*2, "Encoder failure");
1999 #endif /* AUDIO_HAVE_RECORDING */
2004 * Layout audio buffer as follows - iram buffer depends on target:
2005 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
2007 static void audio_reset_buffer(void)
2009 /* see audio_get_recording_buffer if this is modified */
2010 logf("audio_reset_buffer");
2012 /* If the setup of anything allocated before the file buffer is
2013 changed, do check the adjustments after the buffer_alloc call
2014 as it will likely be affected and need sliding over */
2016 /* Initially set up file buffer as all space available */
2017 filebuf
= audiobuf
+ talk_get_bufsize();
2018 filebuflen
= audiobufend
- filebuf
;
2020 ALIGN_BUFFER(filebuf
, filebuflen
, sizeof (intptr_t));
2022 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
2023 size_t pcmbuf_size
= pcmbuf_init(filebuf
+ filebuflen
) + GUARD_BUFSIZE
;
2025 /* Make sure filebuflen is a pointer sized multiple after adjustment */
2026 pcmbuf_size
= ALIGN_UP(pcmbuf_size
, sizeof (intptr_t));
2028 if(pcmbuf_size
> filebuflen
)
2029 panicf("%s(): EOM (%zu > %zu)", __func__
, pcmbuf_size
, filebuflen
);
2031 filebuflen
-= pcmbuf_size
;
2032 buffering_reset(filebuf
, filebuflen
);
2034 /* Clear any references to the file buffer */
2035 buffer_state
= AUDIOBUF_STATE_INITIALIZED
;
2037 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
2038 /* Make sure everything adds up - yes, some info is a bit redundant but
2039 aids viewing and the sumation of certain variables should add up to
2040 the location of others. */
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
));
2054 static void audio_thread(void)
2056 struct queue_event ev
;
2060 audio_thread_ready
= true;
2066 queue_wait(&audio_queue
, &ev
);
2069 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2071 queue_wait(&audio_queue
, &ev
);
2073 #ifdef AUDIO_HAVE_RECORDING
2074 /* Must monitor the encoder message for recording so it can
2075 remove it if we process the insertion before it does. It
2076 cannot simply be removed from under recording however. */
2077 case Q_AUDIO_LOAD_ENCODER
:
2080 case SYS_USB_DISCONNECTED
:
2081 filling
= STATE_IDLE
;
2086 #endif /* CONFIG_PLATFORM */
2089 /* End of buffering, let's calculate the watermark and
2091 set_filebuf_watermark();
2096 if (!pcmbuf_queue_scan(&ev
))
2097 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
2103 case Q_AUDIO_FILL_BUFFER
:
2104 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev
.data
);
2105 audio_fill_file_buffer((bool)ev
.data
, 0);
2108 case Q_AUDIO_FINISH_LOAD
:
2109 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2110 audio_finish_load_track();
2111 buf_set_base_handle(CUR_TI
->audio_hid
);
2115 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2116 if (playing
&& ev
.data
<= 0)
2117 audio_new_playlist();
2120 audio_stop_playback();
2121 audio_play_start((size_t)ev
.data
);
2126 LOGFQUEUE("audio < Q_AUDIO_STOP");
2128 audio_stop_playback();
2130 queue_clear(&audio_queue
);
2134 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2135 if (!(bool) ev
.data
&& skipped_during_pause
2136 #ifdef HAVE_CROSSFADE
2137 && !pcmbuf_is_crossfade_active()
2140 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2141 skipped_during_pause
= false;
2144 pcmbuf_pause((bool)ev
.data
);
2145 paused
= (bool)ev
.data
;
2149 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2150 audio_initiate_track_change((long)ev
.data
);
2153 case Q_AUDIO_PRE_FF_REWIND
:
2154 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2160 case Q_AUDIO_FF_REWIND
:
2161 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2165 if (filling
== STATE_ENDING
)
2167 /* Temp workaround: There is no codec available */
2169 pcmbuf_pause(false);
2173 if ((long)ev
.data
== 0)
2175 /* About to restart the track - send track finish
2176 events if not already done. */
2177 if (thistrack_id3
== audio_current_track())
2178 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
2183 /* An automatic track skip is in progress. Finalize it,
2184 then go back to the previous track */
2185 audio_finalise_track_change();
2188 ci
.seek_time
= (long)ev
.data
+1;
2191 case Q_AUDIO_CHECK_NEW_TRACK
:
2192 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2193 audio_check_new_track();
2196 case Q_AUDIO_DIR_SKIP
:
2197 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2198 audio_initiate_dir_change(ev
.data
);
2202 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2203 audio_invalidate_tracks();
2206 case Q_AUDIO_TRACK_CHANGED
:
2207 /* PCM track change done */
2208 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2209 /* Set new playlist position for resuming. */
2210 playlist_update_resume_index();
2211 if (filling
!= STATE_ENDING
)
2212 audio_finalise_track_change();
2214 audio_stop_playback();
2217 case Q_AUDIO_SEEK_COMPLETE
:
2218 /* Codec seek done */
2219 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
2220 audio_seek_complete();
2221 codec_ack_msg(Q_AUDIO_SEEK_COMPLETE
, false);
2225 case Q_CODEC_LOAD_DISK
:
2226 #ifdef AUDIO_HAVE_RECORDING
2227 case Q_ENCODER_LOAD_DISK
:
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
);
2234 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2235 case SYS_USB_CONNECTED
:
2236 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2238 audio_stop_playback();
2239 #ifdef PLAYBACK_VOICE
2242 filling
= STATE_USB
;
2243 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2247 #ifdef AUDIO_HAVE_RECORDING
2248 case Q_AUDIO_LOAD_ENCODER
:
2250 audio_stop_playback();
2252 codec_stop(); /* If encoder still loaded, stop it */
2254 if (ev
.data
== AFMT_UNKNOWN
)
2257 queue_reply(&audio_queue
,
2258 codec_load(-1, ev
.data
| CODEC_TYPE_ENCODER
));
2260 #endif /* AUDIO_HAVE_RECORDING */
2263 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2267 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2273 /* Initialize the audio system - called from init() in main.c.
2274 * Last function because of all the references to internal symbols
2276 void audio_init(void)
2278 unsigned int audio_thread_id
;
2280 /* Can never do this twice */
2281 if (audio_is_initialized
)
2283 logf("audio: already initialized");
2287 logf("audio: initializing");
2289 /* Initialize queues before giving control elsewhere in case it likes
2290 to send messages. Thread creation will be delayed however so nothing
2291 starts running until ready if something yields such as talk_init. */
2292 queue_init(&audio_queue
, true);
2293 queue_init(&pcmbuf_queue
, false);
2297 codec_init_codec_api();
2299 thistrack_id3
= &mp3entry_buf
[0];
2300 othertrack_id3
= &mp3entry_buf
[1];
2302 /* cuesheet support */
2303 if (global_settings
.cuesheet
)
2304 curr_cue
= (struct cuesheet
*)buffer_alloc(sizeof(struct cuesheet
));
2306 /* initialize the buffer */
2309 /* audio_reset_buffer must to know the size of voice buffer so init
2313 make_codec_thread();
2315 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
2316 sizeof(audio_stack
), CREATE_THREAD_FROZEN
,
2317 audio_thread_name
IF_PRIO(, PRIORITY_USER_INTERFACE
)
2320 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
2323 #ifdef PLAYBACK_VOICE
2324 voice_thread_init();
2327 #ifdef HAVE_CROSSFADE
2328 /* Set crossfade setting for next buffer init which should be about... */
2329 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
2332 /* initialize the buffering system */
2335 /* ...now! Set up the buffers */
2336 audio_reset_buffer();
2339 for(i
= 0; i
< MAX_TRACK
; i
++)
2341 tracks
[i
].audio_hid
= -1;
2342 tracks
[i
].id3_hid
= -1;
2343 tracks
[i
].codec_hid
= -1;
2344 tracks
[i
].cuesheet_hid
= -1;
2346 #ifdef HAVE_ALBUMART
2350 for (j
= 0; j
< MAX_TRACK
; j
++)
2352 tracks
[j
].aa_hid
[i
] = -1;
2357 add_event(BUFFER_EVENT_REBUFFER
, false, buffering_handle_rebuffer_callback
);
2358 add_event(BUFFER_EVENT_FINISHED
, false, buffering_handle_finished_callback
);
2360 /* Probably safe to say */
2361 audio_is_initialized
= true;
2363 sound_settings_apply();
2364 #ifdef HAVE_DISK_STORAGE
2365 audio_set_buffer_margin(global_settings
.buffer_margin
);
2368 /* it's safe to let the threads run now */
2369 #ifdef PLAYBACK_VOICE
2370 voice_thread_resume();
2372 codec_thread_resume();
2373 thread_thaw(audio_thread_id
);
2377 bool audio_is_thread_ready(void)
2379 return audio_thread_ready
;
2382 size_t audio_get_filebuflen(void)
2389 return CUR_TI
->audio_hid
;