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 unsigned char *malloc_buf
= NULL
; /* Start of malloc buffer (A/C-) */
120 static size_t filebuflen
= 0; /* Size of buffer (A/C-) */
121 /* FIXME: make buf_ridx (C/A-) */
123 /* Possible arrangements of the buffer */
124 enum audio_buffer_state
126 AUDIOBUF_STATE_TRASHED
= -1, /* trashed; must be reset */
127 AUDIOBUF_STATE_INITIALIZED
= 0, /* voice+audio OR audio-only */
128 AUDIOBUF_STATE_VOICED_ONLY
= 1, /* voice-only */
130 static int buffer_state
= AUDIOBUF_STATE_TRASHED
; /* Buffer state */
132 /* These are used to store the current and next (or prev if the current is the last)
133 * mp3entry's in a round-robin system. This guarentees that the pointer returned
134 * by audio_current/next_track will be valid for the full duration of the
135 * currently playing track */
136 static struct mp3entry mp3entry_buf
[2];
137 struct mp3entry
*thistrack_id3
, /* the currently playing track */
138 *othertrack_id3
; /* prev track during track-change-transition, or end of playlist,
139 * next track otherwise */
140 static struct mp3entry unbuffered_id3
; /* the id3 for the first unbuffered track */
142 /* for cuesheet support */
143 static struct cuesheet
*curr_cue
= NULL
;
146 #define MAX_MULTIPLE_AA SKINNABLE_SCREENS_COUNT
150 static struct albumart_slot
{
151 struct dim dim
; /* holds width, height of the albumart */
152 int used
; /* counter, increments if something uses it */
153 } albumart_slots
[MAX_MULTIPLE_AA
];
155 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
159 #define MAX_TRACK 128
160 #define MAX_TRACK_MASK (MAX_TRACK-1)
162 /* Track info structure about songs in the file buffer (A/C-) */
163 static struct track_info
{
164 int audio_hid
; /* The ID for the track's buffer handle */
165 int id3_hid
; /* The ID for the track's metadata handle */
166 int codec_hid
; /* The ID for the track's codec handle */
168 int aa_hid
[MAX_MULTIPLE_AA
];/* The ID for the track's album art handle */
170 int cuesheet_hid
; /* The ID for the track's parsed cueesheet handle */
172 size_t filesize
; /* File total length */
174 bool taginfo_ready
; /* Is metadata read */
178 static volatile int track_ridx
= 0; /* Track being decoded (A/C-) */
179 static int track_widx
= 0; /* Track being buffered (A) */
180 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
182 static struct track_info
*prev_ti
= NULL
; /* Pointer to the previously played
185 /* Information used only for filling the buffer */
186 /* Playlist steps from playing track to next track to be buffered (A) */
187 static int last_peek_offset
= 0;
189 /* Scrobbler support */
190 static unsigned long prev_track_elapsed
= 0; /* Previous track elapsed time (C/A-)*/
192 /* Track change controls */
193 static bool automatic_skip
= false; /* Who initiated in-progress skip? (A) */
194 extern bool track_transition
; /* Are we in a track transition? */
195 static bool dir_skip
= false; /* Is a directory skip pending? (A) */
196 static bool new_playlist
= false; /* Are we starting a new playlist? (A) */
197 static int wps_offset
= 0; /* Pending track change offset, to keep WPS responsive (A) */
198 static bool skipped_during_pause
= false; /* Do we need to clear the PCM buffer when playback resumes (A) */
200 static bool start_play_g
= false; /* Used by audio_load_track to notify
201 audio_finish_load_track about start_play */
203 /* True when a track load is in progress, i.e. audio_load_track() has returned
204 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
205 * audio_load_track() to get called twice in a row, which would cause problems.
207 static bool track_load_started
= false;
209 #ifdef HAVE_DISK_STORAGE
210 static size_t buffer_margin
= 5; /* Buffer margin aka anti-skip buffer (A/C-) */
214 struct event_queue audio_queue SHAREDBSS_ATTR
;
215 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR
;
217 extern struct codec_api ci
;
218 extern unsigned int codec_thread_id
;
220 /* Multiple threads */
221 /* Set the watermark to trigger buffer fill (A/C) */
222 static void set_filebuf_watermark(void);
225 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR
;
226 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
227 static const char audio_thread_name
[] = "audio";
229 static void audio_thread(void);
230 static void audio_initiate_track_change(long direction
);
231 static bool audio_have_tracks(void);
232 static void audio_reset_buffer(void);
233 static void audio_stop_playback(void);
235 /**************************************/
238 /** Pcmbuf callbacks */
240 /* Between the codec and PCM track change, we need to keep updating the
241 * "elapsed" value of the previous (to the codec, but current to the
242 * user/PCM/WPS) track, so that the progressbar reaches the end.
243 * During that transition, the WPS will display othertrack_id3. */
244 void audio_pcmbuf_position_callback(unsigned int time
)
246 time
+= othertrack_id3
->elapsed
;
247 othertrack_id3
->elapsed
= (time
>= othertrack_id3
->length
)
248 ? othertrack_id3
->length
: time
;
251 /* Post message from pcmbuf that the end of the previous track
252 * has just been played. */
253 void audio_post_track_change(bool pcmbuf
)
257 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
258 queue_post(&pcmbuf_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
262 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
263 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
267 /* Scan the pcmbuf queue and return true if a message pulled */
268 static bool pcmbuf_queue_scan(struct queue_event
*ev
)
270 if (!queue_empty(&pcmbuf_queue
))
272 /* Transfer message to audio queue */
274 /* Pull message - never, ever any blocking call! */
275 queue_wait_w_tmo(&pcmbuf_queue
, ev
, 0);
284 /** Helper functions */
286 static struct mp3entry
*bufgetid3(int handle_id
)
291 struct mp3entry
*id3
;
292 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
294 if (ret
!= sizeof(struct mp3entry
))
300 static bool bufreadid3(int handle_id
, struct mp3entry
*id3out
)
302 struct mp3entry
*id3
= bufgetid3(handle_id
);
306 copy_mp3entry(id3out
, id3
);
313 static bool clear_track_info(struct track_info
*track
)
315 /* bufclose returns true if the handle is not found, or if it is closed
316 * successfully, so these checks are safe on non-existant handles */
320 if (track
->codec_hid
>= 0) {
321 if (bufclose(track
->codec_hid
))
322 track
->codec_hid
= -1;
327 if (track
->id3_hid
>= 0) {
328 if (bufclose(track
->id3_hid
))
334 if (track
->audio_hid
>= 0) {
335 if (bufclose(track
->audio_hid
))
336 track
->audio_hid
= -1;
346 if (track
->aa_hid
[i
] >= 0) {
347 if (bufclose(track
->aa_hid
[i
]))
348 track
->aa_hid
[i
] = -1;
356 if (track
->cuesheet_hid
>= 0) {
357 if (bufclose(track
->cuesheet_hid
))
358 track
->cuesheet_hid
= -1;
364 track
->taginfo_ready
= false;
369 /* --- External interfaces --- */
371 /* This sends a stop message and the audio thread will dump all it's
372 subsequenct messages */
373 void audio_hard_stop(void)
376 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
377 queue_send(&audio_queue
, Q_AUDIO_STOP
, 1);
378 #ifdef PLAYBACK_VOICE
383 bool audio_restore_playback(int type
)
387 case AUDIO_WANT_PLAYBACK
:
388 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
389 audio_reset_buffer();
391 case AUDIO_WANT_VOICE
:
392 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
393 audio_reset_buffer();
400 unsigned char *audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
402 unsigned char *buf
, *end
;
404 if (audio_is_initialized
)
408 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
410 /* Reset the buffering thread so that it doesn't try to use the data */
411 buffering_reset(filebuf
, filebuflen
);
413 if (buffer_size
== NULL
)
415 /* Special case for talk_init to use since it already knows it's
417 buffer_state
= AUDIOBUF_STATE_TRASHED
;
421 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
422 || !talk_voice_required())
424 logf("get buffer: talk, audio");
425 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
426 the talk buffer is not needed because voice isn't being used, or
427 could be AUDIOBUF_STATE_TRASHED already. If state is
428 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
429 without the caller knowing what's going on. Changing certain settings
430 may move it to a worse condition but the memory in use by something
431 else will remain undisturbed.
433 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
436 buffer_state
= AUDIOBUF_STATE_TRASHED
;
444 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
445 still AUDIOBUF_STATE_INITIALIZED */
446 /* Skip talk buffer and move pcm buffer to end to maximize available
447 contiguous memory - no audio running means voice will not need the
449 logf("get buffer: audio");
450 buf
= audiobuf
+ talk_get_bufsize();
451 end
= audiobufend
- pcmbuf_init(audiobufend
);
452 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
455 *buffer_size
= end
- buf
;
460 bool audio_buffer_state_trashed(void)
462 return buffer_state
== AUDIOBUF_STATE_TRASHED
;
465 #ifdef HAVE_RECORDING
466 unsigned char *audio_get_recording_buffer(size_t *buffer_size
)
468 /* Stop audio, voice and obtain all available buffer space */
472 unsigned char *end
= audiobufend
;
473 buffer_state
= AUDIOBUF_STATE_TRASHED
;
474 *buffer_size
= end
- audiobuf
;
476 return (unsigned char *)audiobuf
;
479 bool audio_load_encoder(int afmt
)
481 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
482 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: %d", afmt
);
483 return queue_send(&audio_queue
, Q_AUDIO_LOAD_ENCODER
, afmt
) > 0;
488 } /* audio_load_encoder */
490 void audio_remove_encoder(void)
492 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
493 LOGFQUEUE("audio >| Q_AUDIO_LOAD_ENCODER: NULL");
494 queue_send(&audio_queue
, Q_AUDIO_LOAD_ENCODER
, AFMT_UNKNOWN
);
496 } /* audio_remove_encoder */
498 #endif /* HAVE_RECORDING */
501 struct mp3entry
* audio_current_track(void)
503 const char *filename
;
504 struct playlist_track_info trackinfo
;
506 int offset
= ci
.new_track
+ wps_offset
;
507 struct mp3entry
*write_id3
;
509 cur_idx
= (track_ridx
+ offset
) & MAX_TRACK_MASK
;
511 if (cur_idx
== track_ridx
&& *thistrack_id3
->path
)
514 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
516 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
517 thistrack_id3
->cuesheet
= curr_cue
;
519 return thistrack_id3
;
521 else if (automatic_skip
&& offset
== -1 && *othertrack_id3
->path
)
523 /* We're in a track transition. The codec has moved on to the next track,
524 but the audio being played is still the same (now previous) track.
525 othertrack_id3.elapsed is being updated in an ISR by
526 codec_pcmbuf_position_callback */
527 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
529 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
530 othertrack_id3
->cuesheet
= curr_cue
;
532 return othertrack_id3
;
537 /* Codec may be using thistrack_id3, so it must not be overwritten.
538 If this is a manual skip, othertrack_id3 will become
539 thistrack_id3 in audio_check_new_track().
540 FIXME: If this is an automatic skip, it probably means multiple
541 short tracks fit in the PCM buffer. Overwriting othertrack_id3
542 can lead to an incorrect value later.
543 Note that othertrack_id3 may also be used for next track.
545 write_id3
= othertrack_id3
;
549 write_id3
= thistrack_id3
;
552 if (tracks
[cur_idx
].id3_hid
>= 0)
554 /* The current track's info has been buffered but not read yet, so get it */
555 if (bufreadid3(tracks
[cur_idx
].id3_hid
, write_id3
))
559 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
560 we have and return that. */
562 memset(write_id3
, 0, sizeof(struct mp3entry
));
564 playlist_get_track_info(NULL
, playlist_next(0)+wps_offset
, &trackinfo
);
565 filename
= trackinfo
.filename
;
567 filename
= "No file!";
569 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
570 if (tagcache_fill_tags(write_id3
, filename
))
574 strlcpy(write_id3
->path
, filename
, sizeof(write_id3
->path
));
575 write_id3
->title
= strrchr(write_id3
->path
, '/');
576 if (!write_id3
->title
)
577 write_id3
->title
= &write_id3
->path
[0];
584 struct mp3entry
* audio_next_track(void)
587 int offset
= ci
.new_track
+ wps_offset
;
589 if (!audio_have_tracks())
592 if (wps_offset
== -1 && *thistrack_id3
->path
)
594 /* We're in a track transition. The next track for the WPS is the one
595 currently being decoded. */
596 return thistrack_id3
;
599 next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
601 if (tracks
[next_idx
].id3_hid
>= 0)
603 if (bufreadid3(tracks
[next_idx
].id3_hid
, othertrack_id3
))
604 return othertrack_id3
;
609 if (next_idx
== track_widx
)
611 /* The next track hasn't been buffered yet, so we return the static
612 version of its metadata. */
613 return &unbuffered_id3
;
619 /* gets a copy of the id3 data */
620 bool audio_peek_track(struct mp3entry
* id3
, int offset
)
623 int new_offset
= ci
.new_track
+ wps_offset
+ offset
;
625 if (!audio_have_tracks())
627 next_idx
= (track_ridx
+ new_offset
) & MAX_TRACK_MASK
;
629 if (tracks
[next_idx
].id3_hid
>= 0)
630 return bufreadid3(tracks
[next_idx
].id3_hid
, id3
);
637 int playback_current_aa_hid(int slot
)
642 int offset
= ci
.new_track
+ wps_offset
;
644 cur_idx
= track_ridx
+ offset
;
645 cur_idx
&= MAX_TRACK_MASK
;
646 return tracks
[cur_idx
].aa_hid
[slot
];
649 int playback_claim_aa_slot(struct dim
*dim
)
653 /* first try to find a slot already having the size to reuse it
654 * since we don't want albumart of the same size buffered multiple times */
657 struct albumart_slot
*slot
= &albumart_slots
[i
];
658 if (slot
->dim
.width
== dim
->width
659 && slot
->dim
.height
== dim
->height
)
665 /* size is new, find a free slot */
668 if (!albumart_slots
[i
].used
)
670 albumart_slots
[i
].used
++;
671 albumart_slots
[i
].dim
= *dim
;
675 /* sorry, no free slot */
679 void playback_release_aa_slot(int slot
)
681 /* invalidate the albumart_slot */
682 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
684 if (aa_slot
->used
> 0)
689 void audio_play(long offset
)
693 #ifdef PLAYBACK_VOICE
694 /* Truncate any existing voice output so we don't have spelling
695 * etc. over the first part of the played track */
700 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
701 /* Don't return until playback has actually started */
702 queue_send(&audio_queue
, Q_AUDIO_PLAY
, offset
);
705 void audio_stop(void)
708 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
709 /* Don't return until playback has actually stopped */
710 queue_send(&audio_queue
, Q_AUDIO_STOP
, 0);
713 void audio_pause(void)
715 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
716 /* Don't return until playback has actually paused */
717 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, true);
720 void audio_resume(void)
722 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
723 /* Don't return until playback has actually resumed */
724 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, false);
727 void audio_skip(int direction
)
729 if (playlist_check(ci
.new_track
+ wps_offset
+ direction
))
731 if (global_settings
.beep
)
732 pcmbuf_beep(2000, 100, 2500*global_settings
.beep
);
734 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction
);
735 queue_post(&audio_queue
, Q_AUDIO_SKIP
, direction
);
736 /* Update wps while our message travels inside deep playback queues. */
737 wps_offset
+= direction
;
741 /* No more tracks. */
742 if (global_settings
.beep
)
743 pcmbuf_beep(1000, 100, 1500*global_settings
.beep
);
747 void audio_next(void)
752 void audio_prev(void)
757 void audio_next_dir(void)
759 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
760 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, 1);
763 void audio_prev_dir(void)
765 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
766 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, -1);
769 void audio_pre_ff_rewind(void)
771 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
772 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
775 void audio_ff_rewind(long newpos
)
777 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
778 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, newpos
);
781 void audio_flush_and_reload_tracks(void)
783 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
784 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
787 void audio_error_clear(void)
789 #ifdef AUDIO_HAVE_RECORDING
790 pcm_rec_error_clear();
794 int audio_status(void)
799 ret
|= AUDIO_STATUS_PLAY
;
802 ret
|= AUDIO_STATUS_PAUSE
;
804 #ifdef HAVE_RECORDING
805 /* Do this here for constitency with mpeg.c version */
806 /* FIXME: pcm_rec_status() is deprecated */
807 ret
|= pcm_rec_status();
813 bool audio_automatic_skip(void)
815 return automatic_skip
;
818 int audio_get_file_pos(void)
823 #ifdef HAVE_DISK_STORAGE
824 void audio_set_buffer_margin(int setting
)
826 static const unsigned short lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
827 buffer_margin
= lookup
[setting
];
828 logf("buffer margin: %ld", (long)buffer_margin
);
829 set_filebuf_watermark();
833 #ifdef HAVE_CROSSFADE
834 /* Take necessary steps to enable or disable the crossfade setting */
835 void audio_set_crossfade(int enable
)
841 /* Tell it the next setting to use */
842 pcmbuf_request_crossfade_enable(enable
);
844 /* Return if size hasn't changed or this is too early to determine
845 which in the second case there's no way we could be playing
847 if (pcmbuf_is_same_size()) return;
850 was_playing
= playing
;
852 /* Playback has to be stopped before changing the buffer size */
855 /* Store the track resume position */
856 offset
= thistrack_id3
->offset
;
859 /* Blast it - audio buffer will have to be setup again next time
861 audio_get_buffer(true, &size
);
863 /* Restart playback if audio was running previously */
869 /* --- Routines called from multiple threads --- */
871 static void set_filebuf_watermark(void)
874 return; /* Audio buffers not yet set up */
876 #ifdef HAVE_DISK_STORAGE
878 int spinup
= ata_spinup_time();
880 seconds
= (spinup
/ HZ
) + 1;
884 seconds
+= buffer_margin
;
890 /* bitrate of last track in buffer dictates watermark */
891 struct mp3entry
* id3
= NULL
;
892 if (tracks
[track_widx
].taginfo_ready
)
893 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
895 id3
= bufgetid3(tracks
[track_widx
-1].id3_hid
);
897 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx
, track_widx
);
900 size_t bytes
= id3
->bitrate
* (1000/8) * seconds
;
901 buf_set_watermark(bytes
);
902 logf("fwmark: %d", bytes
);
905 /* --- Buffering callbacks --- */
907 static void buffering_low_buffer_callback(void *data
)
910 logf("low buffer callback");
912 if (filling
== STATE_FULL
|| filling
== STATE_END_OF_PLAYLIST
) {
914 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
915 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
919 static void buffering_handle_rebuffer_callback(void *data
)
922 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
923 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
926 static void buffering_handle_finished_callback(void *data
)
928 logf("handle %d finished buffering", *(int*)data
);
929 int hid
= (*(int*)data
);
931 if (hid
== tracks
[track_widx
].id3_hid
)
933 int offset
= ci
.new_track
+ wps_offset
;
934 int next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
935 /* The metadata handle for the last loaded track has been buffered.
936 We can ask the audio thread to load the rest of the track's data. */
937 LOGFQUEUE("audio > audio Q_AUDIO_FINISH_LOAD");
938 queue_post(&audio_queue
, Q_AUDIO_FINISH_LOAD
, 0);
939 if (tracks
[next_idx
].id3_hid
== hid
)
940 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
, NULL
);
944 /* This is most likely an audio handle, so we strip the useless
945 trailing tags that are left. */
948 if (hid
== tracks
[track_widx
-1].audio_hid
949 && filling
== STATE_END_OF_PLAYLIST
)
951 /* This was the last track in the playlist.
952 We now have all the data we need. */
953 logf("last track finished buffering");
954 filling
= STATE_FINISHED
;
960 /* --- Audio thread --- */
962 static bool audio_have_tracks(void)
964 return (audio_track_count() != 0);
967 static int audio_free_track_count(void)
969 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
970 return MAX_TRACK
- 1 - audio_track_count();
973 int audio_track_count(void)
975 /* Calculate difference from track_ridx to track_widx
976 * taking into account a possible wrap-around. */
977 return (MAX_TRACK
+ track_widx
- track_ridx
) & MAX_TRACK_MASK
;
980 long audio_filebufused(void)
982 return (long) buf_used();
985 /* Update track info after successful a codec track change */
986 static void audio_update_trackinfo(void)
990 /* Load the curent track's metadata into curtrack_id3 */
991 if (CUR_TI
->id3_hid
>= 0)
992 bufreadid3(CUR_TI
->id3_hid
, thistrack_id3
);
994 /* Reset current position */
995 thistrack_id3
->elapsed
= 0;
998 /* Ignoring resume position for automatic track change if so configured */
999 resume
= global_settings
.autoresume_enable
&&
1000 (!automatic_skip
/* Resume all manually selected tracks */
1001 || global_settings
.autoresume_automatic
== AUTORESUME_NEXTTRACK_ALWAYS
1002 || (global_settings
.autoresume_automatic
!= AUTORESUME_NEXTTRACK_NEVER
1003 /* Not never resume? */
1004 && autoresumable(thistrack_id3
))); /* Pass Resume filter? */
1009 thistrack_id3
->offset
= 0;
1012 logf("audio_update_trackinfo: Set offset for %s to %lX\n",
1013 thistrack_id3
->title
, thistrack_id3
->offset
);
1015 /* Update the codec API */
1016 ci
.filesize
= CUR_TI
->filesize
;
1017 ci
.id3
= thistrack_id3
;
1019 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1022 /* Clear tracks between write and read, non inclusive */
1023 static void audio_clear_track_entries(void)
1025 int cur_idx
= track_widx
;
1027 logf("Clearing tracks: r%d/w%d", track_ridx
, track_widx
);
1029 /* Loop over all tracks from write-to-read */
1032 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1034 if (cur_idx
== track_ridx
)
1037 clear_track_info(&tracks
[cur_idx
]);
1041 /* Clear all tracks */
1042 static bool audio_release_tracks(void)
1046 logf("releasing all tracks");
1048 for(i
= 0; i
< MAX_TRACK
; i
++)
1050 cur_idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1051 if (!clear_track_info(&tracks
[cur_idx
]))
1058 static bool audio_loadcodec(bool start_play
)
1060 int prev_track
, hid
;
1061 char codec_path
[MAX_PATH
]; /* Full path to codec */
1062 const struct mp3entry
*id3
, *prev_id3
;
1064 if (tracks
[track_widx
].id3_hid
< 0) {
1068 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1072 const char *codec_fn
= get_codec_filename(id3
->codectype
);
1073 if (codec_fn
== NULL
)
1076 tracks
[track_widx
].codec_hid
= -1;
1080 /* Load the codec directly from disk and save some memory. */
1081 track_ridx
= track_widx
;
1082 ci
.filesize
= CUR_TI
->filesize
;
1083 ci
.id3
= thistrack_id3
;
1084 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1086 return codec_load(-1, id3
->codectype
);
1090 /* If we already have another track than this one buffered */
1091 if (track_widx
!= track_ridx
)
1093 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
1095 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1096 prev_id3
= bufgetid3(tracks
[prev_track
].id3_hid
);
1098 /* If the previous codec is the same as this one and the current
1099 * one is the correct one, there is no need to put another copy of
1100 * it on the file buffer */
1101 if (id3
&& prev_id3
)
1103 int codt
= get_codec_base_type(id3
->codectype
);
1104 int prev_codt
= get_codec_base_type(prev_id3
->codectype
);
1105 int cod_loaded
= get_codec_base_type(codec_loaded());
1107 if (codt
== prev_codt
&& codt
== cod_loaded
)
1109 logf("Reusing prev. codec");
1116 codec_get_full_path(codec_path
, codec_fn
);
1118 hid
= tracks
[track_widx
].codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1120 /* not an error if codec load it supported, will load it from disk
1121 * application builds don't support it
1123 if (hid
< 0 && hid
!= ERR_UNSUPPORTED_TYPE
)
1127 logf("Loaded codec");
1129 logf("Buffering codec unsupported, load later from disk");
1134 /* Load metadata for the next track (with bufopen). The rest of the track
1135 loading will be handled by audio_finish_load_track once the metadata has been
1136 actually loaded by the buffering thread. */
1137 static bool audio_load_track(size_t offset
, bool start_play
)
1139 char name_buf
[MAX_PATH
+ 1];
1140 const char *trackname
;
1143 if (track_load_started
) {
1144 /* There is already a track load in progress, so track_widx hasn't been
1145 incremented yet. Loading another track would overwrite the one that
1146 hasn't finished loading. */
1147 logf("audio_load_track(): a track load is already in progress");
1151 start_play_g
= start_play
; /* will be read by audio_finish_load_track */
1153 /* Stop buffer filling if there is no free track entries.
1154 Don't fill up the last track entry (we wan't to store next track
1156 if (!audio_free_track_count())
1158 logf("No free tracks");
1163 tracks
[track_widx
].taginfo_ready
= false;
1165 logf("Buffering track: r%d/w%d", track_ridx
, track_widx
);
1166 /* Get track name from current playlist read position. */
1167 while ((trackname
= playlist_peek(last_peek_offset
, name_buf
,
1168 sizeof(name_buf
))) != NULL
)
1170 /* Handle broken playlists. */
1171 fd
= open(trackname
, O_RDONLY
);
1174 logf("Open failed");
1175 /* Skip invalid entry from playlist. */
1176 playlist_skip_entry(NULL
, last_peek_offset
);
1184 logf("End-of-playlist");
1185 memset(&unbuffered_id3
, 0, sizeof(struct mp3entry
));
1186 filling
= STATE_END_OF_PLAYLIST
;
1188 if (thistrack_id3
->length
== 0 && thistrack_id3
->filesize
== 0)
1190 /* Stop playback if no valid track was found. */
1191 audio_stop_playback();
1197 tracks
[track_widx
].filesize
= filesize(fd
);
1199 if (offset
> tracks
[track_widx
].filesize
)
1202 /* Set default values */
1205 buf_set_watermark(filebuflen
/2);
1206 dsp_configure(ci
.dsp
, DSP_RESET
, 0);
1207 playlist_update_resume_info(audio_current_track());
1210 /* Get track metadata if we don't already have it. */
1211 if (tracks
[track_widx
].id3_hid
< 0)
1213 tracks
[track_widx
].id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
);
1215 if (tracks
[track_widx
].id3_hid
< 0)
1217 /* Buffer is full. */
1218 get_metadata(&unbuffered_id3
, fd
, trackname
);
1221 logf("buffer is full for now (get metadata)");
1222 filling
= STATE_FULL
;
1226 if (track_widx
== track_ridx
)
1228 /* TODO: Superfluos buffering call? */
1229 buf_request_buffer_handle(tracks
[track_widx
].id3_hid
);
1230 if (bufreadid3(tracks
[track_widx
].id3_hid
, thistrack_id3
))
1232 thistrack_id3
->offset
= offset
;
1233 logf("audio_load_track: set offset for %s to %lX\n",
1234 thistrack_id3
->title
,
1238 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1243 playlist_update_resume_info(audio_current_track());
1248 track_load_started
= true; /* Remember that we've started loading a track */
1252 #ifdef HAVE_ALBUMART
1253 /* Load any album art for the file */
1254 static void audio_load_albumart(struct mp3entry
*track_id3
)
1260 struct bufopen_bitmap_data user_data
;
1261 int hid
= ERR_HANDLE_NOT_FOUND
;
1263 /* albumart_slots may change during a yield of bufopen,
1264 * but that's no problem */
1265 if (tracks
[track_widx
].aa_hid
[i
] >= 0 || !albumart_slots
[i
].used
)
1268 memset(&user_data
, 0, sizeof(user_data
));
1269 user_data
.dim
= &(albumart_slots
[i
].dim
);
1271 /* we can only decode jpeg for embedded AA */
1272 if (track_id3
->embed_albumart
&& track_id3
->albumart
.type
== AA_TYPE_JPG
)
1274 user_data
.embedded_albumart
= &(track_id3
->albumart
);
1275 hid
= bufopen(track_id3
->path
, 0, TYPE_BITMAP
, &user_data
);
1278 if (hid
< 0 && hid
!= ERR_BUFFER_FULL
)
1280 /* no embedded AA or it couldn't be loaded, try other sources */
1281 char path
[MAX_PATH
];
1283 if (find_albumart(track_id3
, path
, sizeof(path
),
1284 &(albumart_slots
[i
].dim
)))
1286 user_data
.embedded_albumart
= NULL
;
1287 hid
= bufopen(path
, 0, TYPE_BITMAP
, &user_data
);
1291 if (hid
== ERR_BUFFER_FULL
)
1293 filling
= STATE_FULL
;
1294 logf("buffer is full for now (get album art)");
1298 logf("Album art loading failed");
1301 tracks
[track_widx
].aa_hid
[i
] = hid
;
1306 /* Second part of the track loading: We now have the metadata available, so we
1307 can load the codec, the album art and finally the audio data.
1308 This is called on the audio thread after the buffering thread calls the
1309 buffering_handle_finished_callback callback. */
1310 static void audio_finish_load_track(void)
1312 size_t file_offset
= 0;
1314 bool start_play
= start_play_g
;
1316 track_load_started
= false;
1318 if (tracks
[track_widx
].id3_hid
< 0) {
1319 logf("No metadata");
1323 struct mp3entry
*track_id3
;
1325 if (track_widx
== track_ridx
)
1326 track_id3
= thistrack_id3
;
1328 track_id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1330 if (track_id3
->length
== 0 && track_id3
->filesize
== 0)
1332 logf("audio_finish_load_track: invalid metadata");
1334 /* Invalid metadata */
1335 bufclose(tracks
[track_widx
].id3_hid
);
1336 tracks
[track_widx
].id3_hid
= -1;
1338 /* Skip invalid entry from playlist. */
1339 playlist_skip_entry(NULL
, last_peek_offset
--);
1341 /* load next track */
1342 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play
);
1343 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, start_play
);
1347 /* Try to load a cuesheet for the track */
1350 char cuepath
[MAX_PATH
];
1351 if (look_for_cuesheet_file(track_id3
->path
, cuepath
))
1354 tracks
[track_widx
].cuesheet_hid
=
1355 bufalloc(NULL
, sizeof(struct cuesheet
), TYPE_CUESHEET
);
1356 if (tracks
[track_widx
].cuesheet_hid
>= 0)
1358 bufgetdata(tracks
[track_widx
].cuesheet_hid
,
1359 sizeof(struct cuesheet
), &temp
);
1360 struct cuesheet
*cuesheet
= (struct cuesheet
*)temp
;
1361 if (!parse_cuesheet(cuepath
, cuesheet
))
1363 bufclose(tracks
[track_widx
].cuesheet_hid
);
1364 track_id3
->cuesheet
= NULL
;
1370 #ifdef HAVE_ALBUMART
1371 audio_load_albumart(track_id3
);
1374 /* Load the codec. */
1375 if (!audio_loadcodec(start_play
))
1377 if (tracks
[track_widx
].codec_hid
== ERR_BUFFER_FULL
)
1379 /* No space for codec on buffer, not an error */
1380 filling
= STATE_FULL
;
1384 /* This is an error condition, either no codec was found, or reading
1385 * the codec file failed part way through, either way, skip the track */
1386 /* FIXME: We should not use splashf from audio thread! */
1387 splashf(HZ
*2, "No codec for: %s", track_id3
->path
);
1388 /* Skip invalid entry from playlist. */
1389 playlist_skip_entry(NULL
, last_peek_offset
);
1393 track_id3
->elapsed
= 0;
1394 offset
= track_id3
->offset
;
1395 size_t resume_rewind
= (global_settings
.resume_rewind
*
1396 track_id3
->bitrate
* 1000) / 8;
1398 if (offset
< resume_rewind
)
1404 offset
-= resume_rewind
;
1407 enum data_type type
= TYPE_PACKET_AUDIO
;
1409 switch (track_id3
->codectype
) {
1414 file_offset
= offset
;
1420 file_offset
= offset
;
1421 track_id3
->elapsed
= track_id3
->length
/ 2;
1428 logf("Loading atomic %d",track_id3
->codectype
);
1429 type
= TYPE_ATOMIC_AUDIO
;
1433 /* no special treatment needed */
1437 track_id3
->offset
= offset
;
1439 logf("load track: %s", track_id3
->path
);
1441 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1442 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1443 else if (track_id3
->first_frame_offset
)
1444 file_offset
= track_id3
->first_frame_offset
;
1448 tracks
[track_widx
].audio_hid
= bufopen(track_id3
->path
, file_offset
, type
,
1451 /* No space left, not an error */
1452 if (tracks
[track_widx
].audio_hid
== ERR_BUFFER_FULL
)
1454 filling
= STATE_FULL
;
1455 logf("buffer is full for now (load audio)");
1458 else if (tracks
[track_widx
].audio_hid
< 0)
1460 /* another error, do not continue either */
1461 logf("Could not add audio data handle");
1465 /* All required data is now available for the codec -- unless the
1466 autoresume feature is in effect. In the latter case, the codec
1467 must wait until after PLAYBACK_EVENT_TRACK_BUFFER, which may
1468 generate a resume position. */
1469 #ifdef HAVE_TAGCACHE
1470 if (! global_settings
.autoresume_enable
)
1472 tracks
[track_widx
].taginfo_ready
= true;
1476 ci
.curpos
=file_offset
;
1477 buf_request_buffer_handle(tracks
[track_widx
].audio_hid
);
1480 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, track_id3
);
1482 #ifdef HAVE_TAGCACHE
1483 /* In case the autoresume feature has been enabled, finally all
1484 required data is available for the codec. */
1485 if (global_settings
.autoresume_enable
)
1486 tracks
[track_widx
].taginfo_ready
= true;
1489 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1491 /* load next track */
1492 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1493 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1498 static void audio_fill_file_buffer(bool start_play
, size_t offset
)
1500 trigger_cpu_boost();
1502 /* No need to rebuffer if there are track skips pending,
1503 * however don't cancel buffering on skipping while filling. */
1504 if (ci
.new_track
!= 0 && filling
!= STATE_FILLING
)
1506 filling
= STATE_FILLING
;
1508 /* Must reset the buffer before use if trashed or voice only - voice
1509 file size shouldn't have changed so we can go straight from
1510 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1511 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1512 audio_reset_buffer();
1514 logf("Starting buffer fill");
1517 audio_clear_track_entries();
1519 /* Save the current resume position once. */
1520 playlist_update_resume_info(audio_current_track());
1522 audio_load_track(offset
, start_play
);
1525 static void audio_rebuffer(void)
1527 logf("Forcing rebuffer");
1529 clear_track_info(CUR_TI
);
1531 /* Reset track pointers */
1532 track_widx
= track_ridx
;
1533 audio_clear_track_entries();
1535 /* Reset a possibly interrupted track load */
1536 track_load_started
= false;
1538 /* Fill the buffer */
1539 last_peek_offset
= -1;
1542 if (!CUR_TI
->taginfo_ready
)
1543 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1545 audio_fill_file_buffer(false, 0);
1548 /* Called on request from the codec to get a new track. This is the codec part
1549 of the track transition. */
1550 static void audio_last_track(bool automatic
)
1555 automatic_skip
= false;
1557 if (filling
!= STATE_ENDING
)
1559 /* Monitor remaining PCM before stopping */
1560 filling
= STATE_ENDING
;
1561 pcmbuf_monitor_track_change(true);
1568 audio_stop_playback();
1572 static void audio_check_new_track(void)
1578 struct mp3entry
*temp
;
1580 if (ci
.new_track
== 0)
1583 automatic_skip
= true;
1586 track_count
= audio_track_count();
1587 old_track_ridx
= track_ridx
;
1589 /* Now it's good time to send track finish events. */
1590 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
1591 /* swap the mp3entry pointers */
1592 temp
= thistrack_id3
;
1593 thistrack_id3
= othertrack_id3
;
1594 othertrack_id3
= temp
;
1595 ci
.id3
= thistrack_id3
;
1596 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1601 /* regardless of the return value we need to rebuffer.
1602 if it fails the old playlist will resume, else the
1603 next dir will start playing */
1604 playlist_next_dir(ci
.new_track
);
1613 /* If the playlist isn't that big */
1616 while (!playlist_check(ci
.new_track
))
1618 if (ci
.new_track
>= 0)
1620 audio_last_track(true);
1627 /* Update the playlist */
1628 last_peek_offset
-= ci
.new_track
;
1630 if (playlist_next(ci
.new_track
) < 0)
1633 audio_last_track(automatic_skip
);
1640 new_playlist
= false;
1643 /* Save a pointer to the old track to allow later clearing */
1646 for (i
= 0; i
< ci
.new_track
; i
++)
1648 idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1649 struct mp3entry
*id3
= bufgetid3(tracks
[idx
].id3_hid
);
1650 ssize_t offset
= buf_handle_offset(tracks
[idx
].audio_hid
);
1651 if (!id3
|| offset
< 0 || (unsigned)offset
> id3
->first_frame_offset
)
1653 /* We don't have all the audio data for that track, so clear it,
1654 but keep the metadata. */
1655 if (tracks
[idx
].audio_hid
>= 0 && bufclose(tracks
[idx
].audio_hid
))
1657 tracks
[idx
].audio_hid
= -1;
1658 tracks
[idx
].filesize
= 0;
1663 /* Move to the new track */
1664 track_ridx
= (track_ridx
+ ci
.new_track
) & MAX_TRACK_MASK
;
1665 buf_set_base_handle(CUR_TI
->audio_hid
);
1669 wps_offset
= -ci
.new_track
;
1672 /* If it is not safe to even skip this many track entries */
1673 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
1680 forward
= ci
.new_track
> 0;
1683 /* If the target track is clearly not in memory */
1684 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
1690 /* When skipping backwards, it is possible that we've found a track that's
1691 * buffered, but which is around the track-wrap and therefore not the track
1692 * we are looking for */
1695 int cur_idx
= track_ridx
;
1696 bool taginfo_ready
= true;
1697 /* We've wrapped the buffer backwards if new > old */
1698 bool wrap
= track_ridx
> old_track_ridx
;
1702 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1704 /* if we've advanced past the wrap when cur_idx is zeroed */
1708 /* if we aren't still on the wrap and we've caught the old track */
1709 if (!(wrap
|| cur_idx
< old_track_ridx
))
1712 /* If we hit a track in between without valid tag info, bail */
1713 if (!tracks
[cur_idx
].taginfo_ready
)
1715 taginfo_ready
= false;
1726 audio_update_trackinfo();
1727 pcmbuf_start_track_change(automatic_skip
);
1729 if (get_codec_base_type(codec_loaded()) ==
1730 get_codec_base_type(thistrack_id3
->codectype
))
1732 /* codec is the same base type */
1733 logf("New track loaded");
1734 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE
, false);
1738 /* a codec change is required */
1739 logf("New codec: %d/%d", thistrack_id3
->codectype
, codec_loaded());
1740 codec_ack_msg(Q_CODEC_REQUEST_COMPLETE
, true);
1741 codec_load(tracks
[track_ridx
].codec_hid
, thistrack_id3
->codectype
);
1742 tracks
[track_ridx
].codec_hid
= -1; /* Codec thread will close it */
1746 unsigned long audio_prev_elapsed(void)
1748 return prev_track_elapsed
;
1751 void audio_set_prev_elapsed(unsigned long setting
)
1753 prev_track_elapsed
= setting
;
1756 /* Stop the codec and reset the PCM buffer */
1757 static void audio_stop_codec_flush(void)
1767 pcm_playing
= pcm_is_playing();
1770 queue_clear(&pcmbuf_queue
);
1773 pcmbuf_pause(paused
);
1778 static void audio_stop_playback(void)
1782 /* If we were playing, save resume information */
1783 struct mp3entry
*id3
= NULL
;
1786 id3
= audio_current_track();
1788 /* Save the current playing spot, or NULL if the playlist has ended */
1789 playlist_update_resume_info(id3
);
1791 /* Now it's good time to send track finish events. Do this
1792 only if this hasn't been done already as part of a track
1794 if (id3
== thistrack_id3
)
1795 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
1797 /* TODO: Create auto bookmark too? */
1799 prev_track_elapsed
= othertrack_id3
->elapsed
;
1801 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffering_low_buffer_callback
);
1804 audio_stop_codec_flush();
1807 track_load_started
= false;
1809 filling
= STATE_IDLE
;
1811 /* Mark all entries null. */
1812 audio_clear_track_entries();
1814 /* Close all tracks */
1815 audio_release_tracks();
1818 static void audio_play_start(size_t offset
)
1822 send_event(PLAYBACK_EVENT_START_PLAYBACK
, NULL
);
1823 #if INPUT_SRC_CAPS != 0
1824 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1825 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
1829 audio_stop_codec_flush();
1832 track_load_started
= false;
1838 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 malloc_buf
= audiobuf
+ talk_get_bufsize();
2019 /* Align the malloc buf to line size.
2020 * Especially important to cf targets that do line reads/writes.
2021 * Also for targets which need aligned DMA storage buffers */
2022 malloc_buf
= (unsigned char *)(((uintptr_t)malloc_buf
+ (CACHEALIGN_SIZE
- 1)) & ~(CACHEALIGN_SIZE
- 1));
2023 filebuf
= malloc_buf
; /* filebuf line align implied */
2024 filebuflen
= (audiobufend
- filebuf
) & ~(CACHEALIGN_SIZE
- 1);
2026 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
2027 const size_t pcmbuf_size
= pcmbuf_init(filebuf
+ filebuflen
) +GUARD_BUFSIZE
;
2028 if(pcmbuf_size
> filebuflen
)
2029 panicf("%s(): EOM (%zu > %zu)", __func__
, pcmbuf_size
, filebuflen
);
2031 filebuflen
-= pcmbuf_size
;
2033 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
2034 will already be line aligned */
2037 buffering_reset(filebuf
, filebuflen
);
2039 /* Clear any references to the file buffer */
2040 buffer_state
= AUDIOBUF_STATE_INITIALIZED
;
2042 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
2043 /* Make sure everything adds up - yes, some info is a bit redundant but
2044 aids viewing and the sumation of certain variables should add up to
2045 the location of others. */
2048 const unsigned char *pcmbuf
= pcmbuf_get_meminfo(&pcmbufsize
);
2049 logf("mabuf: %08X", (unsigned)malloc_buf
);
2050 logf("fbuf: %08X", (unsigned)filebuf
);
2051 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
2052 logf("gbuf: %08X", (unsigned)(filebuf
+ filebuflen
));
2053 logf("gbufe: %08X", (unsigned)(filebuf
+ filebuflen
+ GUARD_BUFSIZE
));
2054 logf("pcmb: %08X", (unsigned)pcmbuf
);
2055 logf("pcmbe: %08X", (unsigned)(pcmbuf
+ pcmbufsize
));
2060 static void audio_thread(void)
2062 struct queue_event ev
;
2066 audio_thread_ready
= true;
2072 queue_wait(&audio_queue
, &ev
);
2075 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2077 queue_wait(&audio_queue
, &ev
);
2079 #ifdef AUDIO_HAVE_RECORDING
2080 /* Must monitor the encoder message for recording so it can
2081 remove it if we process the insertion before it does. It
2082 cannot simply be removed from under recording however. */
2083 case Q_AUDIO_LOAD_ENCODER
:
2086 case SYS_USB_DISCONNECTED
:
2087 filling
= STATE_IDLE
;
2092 #endif /* CONFIG_PLATFORM */
2095 /* End of buffering, let's calculate the watermark and
2097 set_filebuf_watermark();
2102 if (!pcmbuf_queue_scan(&ev
))
2103 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
2109 case Q_AUDIO_FILL_BUFFER
:
2110 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev
.data
);
2111 audio_fill_file_buffer((bool)ev
.data
, 0);
2114 case Q_AUDIO_FINISH_LOAD
:
2115 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2116 audio_finish_load_track();
2117 buf_set_base_handle(CUR_TI
->audio_hid
);
2121 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2122 if (playing
&& ev
.data
<= 0)
2123 audio_new_playlist();
2126 audio_stop_playback();
2127 audio_play_start((size_t)ev
.data
);
2132 LOGFQUEUE("audio < Q_AUDIO_STOP");
2134 audio_stop_playback();
2136 queue_clear(&audio_queue
);
2140 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2141 if (!(bool) ev
.data
&& skipped_during_pause
2142 #ifdef HAVE_CROSSFADE
2143 && !pcmbuf_is_crossfade_active()
2146 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2147 skipped_during_pause
= false;
2150 pcmbuf_pause((bool)ev
.data
);
2151 paused
= (bool)ev
.data
;
2155 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2156 audio_initiate_track_change((long)ev
.data
);
2159 case Q_AUDIO_PRE_FF_REWIND
:
2160 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2166 case Q_AUDIO_FF_REWIND
:
2167 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2171 if (filling
== STATE_ENDING
)
2173 /* Temp workaround: There is no codec available */
2175 pcmbuf_pause(false);
2179 if ((long)ev
.data
== 0)
2181 /* About to restart the track - send track finish
2182 events if not already done. */
2183 if (thistrack_id3
== audio_current_track())
2184 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
2189 /* An automatic track skip is in progress. Finalize it,
2190 then go back to the previous track */
2191 audio_finalise_track_change();
2194 ci
.seek_time
= (long)ev
.data
+1;
2197 case Q_AUDIO_CHECK_NEW_TRACK
:
2198 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2199 audio_check_new_track();
2202 case Q_AUDIO_DIR_SKIP
:
2203 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2204 audio_initiate_dir_change(ev
.data
);
2208 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2209 audio_invalidate_tracks();
2212 case Q_AUDIO_TRACK_CHANGED
:
2213 /* PCM track change done */
2214 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2215 if (filling
!= STATE_ENDING
)
2216 audio_finalise_track_change();
2218 audio_stop_playback();
2221 case Q_AUDIO_SEEK_COMPLETE
:
2222 /* Codec seek done */
2223 LOGFQUEUE("audio < Q_AUDIO_SEEK_COMPLETE");
2224 audio_seek_complete();
2225 codec_ack_msg(Q_AUDIO_SEEK_COMPLETE
, false);
2229 case Q_CODEC_LOAD_DISK
:
2230 #ifdef AUDIO_HAVE_RECORDING
2231 case Q_ENCODER_LOAD_DISK
:
2233 /* These are received when a codec has finished normally or
2234 upon a codec error */
2235 audio_codec_status_message(ev
.id
, ev
.data
);
2238 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
2239 case SYS_USB_CONNECTED
:
2240 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2242 audio_stop_playback();
2243 #ifdef PLAYBACK_VOICE
2246 filling
= STATE_USB
;
2247 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2251 #ifdef AUDIO_HAVE_RECORDING
2252 case Q_AUDIO_LOAD_ENCODER
:
2254 audio_stop_playback();
2256 codec_stop(); /* If encoder still loaded, stop it */
2258 if (ev
.data
== AFMT_UNKNOWN
)
2261 queue_reply(&audio_queue
,
2262 codec_load(-1, ev
.data
| CODEC_TYPE_ENCODER
));
2264 #endif /* AUDIO_HAVE_RECORDING */
2267 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2271 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2277 /* Initialize the audio system - called from init() in main.c.
2278 * Last function because of all the references to internal symbols
2280 void audio_init(void)
2282 unsigned int audio_thread_id
;
2284 /* Can never do this twice */
2285 if (audio_is_initialized
)
2287 logf("audio: already initialized");
2291 logf("audio: initializing");
2293 /* Initialize queues before giving control elsewhere in case it likes
2294 to send messages. Thread creation will be delayed however so nothing
2295 starts running until ready if something yields such as talk_init. */
2296 queue_init(&audio_queue
, true);
2297 queue_init(&pcmbuf_queue
, false);
2301 codec_init_codec_api();
2303 thistrack_id3
= &mp3entry_buf
[0];
2304 othertrack_id3
= &mp3entry_buf
[1];
2306 /* cuesheet support */
2307 if (global_settings
.cuesheet
)
2308 curr_cue
= (struct cuesheet
*)buffer_alloc(sizeof(struct cuesheet
));
2310 /* initialize the buffer */
2313 /* audio_reset_buffer must to know the size of voice buffer so init
2317 make_codec_thread();
2319 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
2320 sizeof(audio_stack
), CREATE_THREAD_FROZEN
,
2321 audio_thread_name
IF_PRIO(, PRIORITY_USER_INTERFACE
)
2324 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
2327 #ifdef PLAYBACK_VOICE
2328 voice_thread_init();
2331 #ifdef HAVE_CROSSFADE
2332 /* Set crossfade setting for next buffer init which should be about... */
2333 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
2336 /* initialize the buffering system */
2339 /* ...now! Set up the buffers */
2340 audio_reset_buffer();
2343 for(i
= 0; i
< MAX_TRACK
; i
++)
2345 tracks
[i
].audio_hid
= -1;
2346 tracks
[i
].id3_hid
= -1;
2347 tracks
[i
].codec_hid
= -1;
2348 tracks
[i
].cuesheet_hid
= -1;
2350 #ifdef HAVE_ALBUMART
2354 for (j
= 0; j
< MAX_TRACK
; j
++)
2356 tracks
[j
].aa_hid
[i
] = -1;
2361 add_event(BUFFER_EVENT_REBUFFER
, false, buffering_handle_rebuffer_callback
);
2362 add_event(BUFFER_EVENT_FINISHED
, false, buffering_handle_finished_callback
);
2364 /* Probably safe to say */
2365 audio_is_initialized
= true;
2367 sound_settings_apply();
2368 #ifdef HAVE_DISK_STORAGE
2369 audio_set_buffer_margin(global_settings
.buffer_margin
);
2372 /* it's safe to let the threads run now */
2373 #ifdef PLAYBACK_VOICE
2374 voice_thread_resume();
2376 codec_thread_resume();
2377 thread_thaw(audio_thread_id
);
2381 bool audio_is_thread_ready(void)
2383 return audio_thread_ready
;
2386 size_t audio_get_filebuflen(void)
2393 return CUR_TI
->audio_hid
;