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 */
28 #include "codec_thread.h"
31 #include "buffering.h"
32 #include "voice_thread.h"
42 #ifdef HAVE_LCD_BITMAP
53 #include "pcm_record.h"
56 #define PLAYBACK_VOICE
58 /* amount of guess-space to allow for codecs that must hunt and peck
59 * for their correct seeek target, 32k seems a good size */
60 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
62 /* Define LOGF_ENABLE to enable logf output in this file */
63 /*#define LOGF_ENABLE*/
66 /* macros to enable logf for queues
67 logging on SYS_TIMEOUT can be disabled */
69 /* Define this for logf output of all queuing except SYS_TIMEOUT */
70 #define PLAYBACK_LOGQUEUES
71 /* Define this to logf SYS_TIMEOUT messages */
72 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
75 #ifdef PLAYBACK_LOGQUEUES
76 #define LOGFQUEUE logf
78 #define LOGFQUEUE(...)
81 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
82 #define LOGFQUEUE_SYS_TIMEOUT logf
84 #define LOGFQUEUE_SYS_TIMEOUT(...)
88 static enum filling_state
{
89 STATE_IDLE
, /* audio is stopped: nothing to do */
90 STATE_FILLING
, /* adding tracks to the buffer */
91 STATE_FULL
, /* can't add any more tracks */
92 STATE_END_OF_PLAYLIST
, /* all remaining tracks have been added */
93 STATE_FINISHED
, /* all remaining tracks are fully buffered */
96 /* As defined in plugins/lib/xxx2wav.h */
97 #define GUARD_BUFSIZE (32*1024)
99 bool audio_is_initialized
= false;
100 static bool audio_thread_ready SHAREDBSS_ATTR
= false;
102 /* Variables are commented with the threads that use them: *
103 * A=audio, C=codec, V=voice. A suffix of - indicates that *
104 * the variable is read but not updated on that thread. */
105 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
107 /* Main state control */
108 static volatile bool playing SHAREDBSS_ATTR
= false;/* Is audio playing? (A) */
109 static volatile bool paused SHAREDBSS_ATTR
= false; /* Is audio paused? (A/C-) */
110 extern volatile bool audio_codec_loaded
; /* Codec loaded? (C/A-) */
112 /* Ring buffer where compressed audio and codecs are loaded */
113 static unsigned char *filebuf
= NULL
; /* Start of buffer (A/C-) */
114 static unsigned char *malloc_buf
= NULL
; /* Start of malloc buffer (A/C-) */
115 static size_t filebuflen
= 0; /* Size of buffer (A/C-) */
116 /* FIXME: make buf_ridx (C/A-) */
118 /* Possible arrangements of the buffer */
119 static int buffer_state
= AUDIOBUF_STATE_TRASHED
; /* Buffer state */
121 /* These are used to store the current and next (or prev if the current is the last)
122 * mp3entry's in a round-robin system. This guarentees that the pointer returned
123 * by audio_current/next_track will be valid for the full duration of the
124 * currently playing track */
125 static struct mp3entry mp3entry_buf
[2];
126 struct mp3entry
*thistrack_id3
, /* the currently playing track */
127 *othertrack_id3
; /* prev track during track-change-transition, or end of playlist,
128 * next track otherwise */
129 static struct mp3entry unbuffered_id3
; /* the id3 for the first unbuffered track */
131 /* for cuesheet support */
132 static struct cuesheet
*curr_cue
= NULL
;
135 #define MAX_MULTIPLE_AA 2
138 static struct albumart_slot
{
139 struct dim dim
; /* holds width, height of the albumart */
140 int used
; /* counter, increments if something uses it */
141 } albumart_slots
[MAX_MULTIPLE_AA
];
143 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
147 #define MAX_TRACK 128
148 #define MAX_TRACK_MASK (MAX_TRACK-1)
150 /* Track info structure about songs in the file buffer (A/C-) */
151 static struct track_info
{
152 int audio_hid
; /* The ID for the track's buffer handle */
153 int id3_hid
; /* The ID for the track's metadata handle */
154 int codec_hid
; /* The ID for the track's codec handle */
156 int aa_hid
[MAX_MULTIPLE_AA
];/* The ID for the track's album art handle */
158 int cuesheet_hid
; /* The ID for the track's parsed cueesheet handle */
160 size_t filesize
; /* File total length */
162 bool taginfo_ready
; /* Is metadata read */
166 static volatile int track_ridx
= 0; /* Track being decoded (A/C-) */
167 static int track_widx
= 0; /* Track being buffered (A) */
168 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
170 static struct track_info
*prev_ti
= NULL
; /* Pointer to the previously played
173 /* Information used only for filling the buffer */
174 /* Playlist steps from playing track to next track to be buffered (A) */
175 static int last_peek_offset
= 0;
177 /* Scrobbler support */
178 static unsigned long prev_track_elapsed
= 0; /* Previous track elapsed time (C/A-)*/
180 /* Track change controls */
181 bool automatic_skip
= false; /* Who initiated in-progress skip? (C/A-) */
182 extern bool track_transition
; /* Are we in a track transition? */
183 static bool dir_skip
= false; /* Is a directory skip pending? (A) */
184 static bool new_playlist
= false; /* Are we starting a new playlist? (A) */
185 static int wps_offset
= 0; /* Pending track change offset, to keep WPS responsive (A) */
186 static bool skipped_during_pause
= false; /* Do we need to clear the PCM buffer when playback resumes (A) */
188 static bool start_play_g
= false; /* Used by audio_load_track to notify
189 audio_finish_load_track about start_play */
191 /* True when a track load is in progress, i.e. audio_load_track() has returned
192 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
193 * audio_load_track() to get called twice in a row, which would cause problems.
195 static bool track_load_started
= false;
197 #ifdef HAVE_DISK_STORAGE
198 static size_t buffer_margin
= 5; /* Buffer margin aka anti-skip buffer (A/C-) */
202 struct event_queue audio_queue SHAREDBSS_ATTR
;
203 struct event_queue codec_queue SHAREDBSS_ATTR
;
204 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR
;
206 extern struct codec_api ci
;
207 extern unsigned int codec_thread_id
;
209 /* Multiple threads */
210 /* Set the watermark to trigger buffer fill (A/C) */
211 static void set_filebuf_watermark(void);
214 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR
;
215 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
216 static const char audio_thread_name
[] = "audio";
218 static void audio_thread(void);
219 static void audio_initiate_track_change(long direction
);
220 static bool audio_have_tracks(void);
221 static void audio_reset_buffer(void);
222 static void audio_stop_playback(void);
225 /**************************************/
227 /* Between the codec and PCM track change, we need to keep updating the
228 "elapsed" value of the previous (to the codec, but current to the
229 user/PCM/WPS) track, so that the progressbar reaches the end.
230 During that transition, the WPS will display othertrack_id3. */
231 void audio_pcmbuf_position_callback(size_t size
)
233 /* This is called from an ISR, so be quick */
234 unsigned int time
= size
* 1000 / 4 / NATIVE_FREQUENCY
+
235 othertrack_id3
->elapsed
;
237 if (time
>= othertrack_id3
->length
)
239 /* we just played the end of the track, so stop this callback */
240 track_transition
= false;
241 othertrack_id3
->elapsed
= othertrack_id3
->length
;
244 othertrack_id3
->elapsed
= time
;
247 /* Post message from pcmbuf that the end of the previous track
248 * has just been played. */
249 void audio_post_track_change(bool pcmbuf
)
253 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
254 queue_post(&pcmbuf_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
258 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
259 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
263 /* Scan the pcmbuf queue and return true if a message pulled.
264 * Permissible Context(s): Thread
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);
281 /* --- Helper functions --- */
283 static struct mp3entry
*bufgetid3(int handle_id
)
288 struct mp3entry
*id3
;
289 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
291 if (ret
< 0 || ret
!= sizeof(struct mp3entry
))
297 static bool clear_track_info(struct track_info
*track
)
299 /* bufclose returns true if the handle is not found, or if it is closed
300 * successfully, so these checks are safe on non-existant handles */
304 if (track
->codec_hid
>= 0) {
305 if (bufclose(track
->codec_hid
))
306 track
->codec_hid
= -1;
311 if (track
->id3_hid
>= 0) {
312 if (bufclose(track
->id3_hid
))
318 if (track
->audio_hid
>= 0) {
319 if (bufclose(track
->audio_hid
))
320 track
->audio_hid
= -1;
330 if (track
->aa_hid
[i
] >= 0) {
331 if (bufclose(track
->aa_hid
[i
]))
332 track
->aa_hid
[i
] = -1;
340 if (track
->cuesheet_hid
>= 0) {
341 if (bufclose(track
->cuesheet_hid
))
342 track
->cuesheet_hid
= -1;
348 track
->taginfo_ready
= false;
353 /* --- External interfaces --- */
355 /* This sends a stop message and the audio thread will dump all it's
356 subsequenct messages */
357 void audio_hard_stop(void)
360 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
361 queue_send(&audio_queue
, Q_AUDIO_STOP
, 1);
362 #ifdef PLAYBACK_VOICE
367 bool audio_restore_playback(int type
)
371 case AUDIO_WANT_PLAYBACK
:
372 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
373 audio_reset_buffer();
375 case AUDIO_WANT_VOICE
:
376 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
377 audio_reset_buffer();
384 unsigned char *audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
386 unsigned char *buf
, *end
;
388 if (audio_is_initialized
)
392 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
394 /* Reset the buffering thread so that it doesn't try to use the data */
395 buffering_reset(filebuf
, filebuflen
);
397 if (buffer_size
== NULL
)
399 /* Special case for talk_init to use since it already knows it's
401 buffer_state
= AUDIOBUF_STATE_TRASHED
;
405 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
406 || !talk_voice_required())
408 logf("get buffer: talk, audio");
409 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
410 the talk buffer is not needed because voice isn't being used, or
411 could be AUDIOBUF_STATE_TRASHED already. If state is
412 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
413 without the caller knowing what's going on. Changing certain settings
414 may move it to a worse condition but the memory in use by something
415 else will remain undisturbed.
417 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
420 buffer_state
= AUDIOBUF_STATE_TRASHED
;
428 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
429 still AUDIOBUF_STATE_INITIALIZED */
430 /* Skip talk buffer and move pcm buffer to end to maximize available
431 contiguous memory - no audio running means voice will not need the
433 logf("get buffer: audio");
434 buf
= audiobuf
+ talk_get_bufsize();
435 end
= audiobufend
- pcmbuf_init(audiobufend
);
436 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
439 *buffer_size
= end
- buf
;
444 int audio_buffer_state(void)
449 #ifdef HAVE_RECORDING
450 unsigned char *audio_get_recording_buffer(size_t *buffer_size
)
452 /* Stop audio, voice and obtain all available buffer space */
456 unsigned char *end
= audiobufend
;
457 buffer_state
= AUDIOBUF_STATE_TRASHED
;
458 *buffer_size
= end
- audiobuf
;
460 return (unsigned char *)audiobuf
;
463 bool audio_load_encoder(int afmt
)
466 const char *enc_fn
= get_codec_filename(afmt
| CODEC_TYPE_ENCODER
);
470 audio_remove_encoder();
471 ci
.enc_codec_loaded
= 0; /* clear any previous error condition */
473 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
474 queue_post(&codec_queue
, Q_ENCODER_LOAD_DISK
, (intptr_t)enc_fn
);
476 while (ci
.enc_codec_loaded
== 0)
479 logf("codec loaded: %d", ci
.enc_codec_loaded
);
481 return ci
.enc_codec_loaded
> 0;
486 } /* audio_load_encoder */
488 void audio_remove_encoder(void)
491 /* force encoder codec unload (if currently loaded) */
492 if (ci
.enc_codec_loaded
<= 0)
495 ci
.stop_encoder
= true;
496 while (ci
.enc_codec_loaded
> 0)
499 } /* audio_remove_encoder */
501 #endif /* HAVE_RECORDING */
504 struct mp3entry
* audio_current_track(void)
506 const char *filename
;
507 struct playlist_track_info trackinfo
;
509 int offset
= ci
.new_track
+ wps_offset
;
510 struct mp3entry
*write_id3
;
512 cur_idx
= (track_ridx
+ offset
) & MAX_TRACK_MASK
;
514 if (cur_idx
== track_ridx
&& *thistrack_id3
->path
)
517 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
519 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
520 thistrack_id3
->cuesheet
= curr_cue
;
521 cue_spoof_id3(thistrack_id3
->cuesheet
, thistrack_id3
);
523 return thistrack_id3
;
525 else if (automatic_skip
&& offset
== -1 && *othertrack_id3
->path
)
527 /* We're in a track transition. The codec has moved on to the next track,
528 but the audio being played is still the same (now previous) track.
529 othertrack_id3.elapsed is being updated in an ISR by
530 codec_pcmbuf_position_callback */
531 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
533 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
534 othertrack_id3
->cuesheet
= curr_cue
;
535 cue_spoof_id3(othertrack_id3
->cuesheet
, othertrack_id3
);
537 return othertrack_id3
;
542 /* Codec may be using thistrack_id3, so it must not be overwritten.
543 If this is a manual skip, othertrack_id3 will become
544 thistrack_id3 in audio_check_new_track().
545 FIXME: If this is an automatic skip, it probably means multiple
546 short tracks fit in the PCM buffer. Overwriting othertrack_id3
547 can lead to an incorrect value later.
548 Note that othertrack_id3 may also be used for next track.
550 write_id3
= othertrack_id3
;
554 write_id3
= thistrack_id3
;
557 if (tracks
[cur_idx
].id3_hid
>= 0)
559 /* The current track's info has been buffered but not read yet, so get it */
560 if (bufread(tracks
[cur_idx
].id3_hid
, sizeof(struct mp3entry
), write_id3
)
561 == sizeof(struct mp3entry
))
565 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
566 we have and return that. */
568 memset(write_id3
, 0, sizeof(struct mp3entry
));
570 playlist_get_track_info(NULL
, playlist_next(0)+wps_offset
, &trackinfo
);
571 filename
= trackinfo
.filename
;
573 filename
= "No file!";
575 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
576 if (tagcache_fill_tags(write_id3
, filename
))
580 strlcpy(write_id3
->path
, filename
, sizeof(write_id3
->path
));
581 write_id3
->title
= strrchr(write_id3
->path
, '/');
582 if (!write_id3
->title
)
583 write_id3
->title
= &write_id3
->path
[0];
590 struct mp3entry
* audio_next_track(void)
593 int offset
= ci
.new_track
+ wps_offset
;
595 if (!audio_have_tracks())
598 if (wps_offset
== -1 && *thistrack_id3
->path
)
600 /* We're in a track transition. The next track for the WPS is the one
601 currently being decoded. */
602 return thistrack_id3
;
605 next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
607 if (tracks
[next_idx
].id3_hid
>= 0)
609 if (bufread(tracks
[next_idx
].id3_hid
, sizeof(struct mp3entry
), othertrack_id3
)
610 == sizeof(struct mp3entry
))
611 return othertrack_id3
;
616 if (next_idx
== track_widx
)
618 /* The next track hasn't been buffered yet, so we return the static
619 version of its metadata. */
620 return &unbuffered_id3
;
627 int playback_current_aa_hid(int slot
)
632 int offset
= ci
.new_track
+ wps_offset
;
634 cur_idx
= track_ridx
+ offset
;
635 cur_idx
&= MAX_TRACK_MASK
;
637 return tracks
[cur_idx
].aa_hid
[slot
];
640 int playback_claim_aa_slot(struct dim
*dim
)
643 /* first try to find a slot already having the size to reuse it
644 * since we don't want albumart of the same size buffered multiple times */
647 struct albumart_slot
*slot
= &albumart_slots
[i
];
648 if (slot
->dim
.width
== dim
->width
649 && slot
->dim
.height
== dim
->height
)
655 /* size is new, find a free slot */
658 if (!albumart_slots
[i
].used
)
660 albumart_slots
[i
].used
++;
661 albumart_slots
[i
].dim
= *dim
;
665 /* sorry, no free slot */
669 void playback_release_aa_slot(int slot
)
671 /* invalidate the albumart_slot */
672 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
673 if (aa_slot
->used
> 0)
678 void audio_play(long offset
)
682 #ifdef PLAYBACK_VOICE
683 /* Truncate any existing voice output so we don't have spelling
684 * etc. over the first part of the played track */
689 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
690 /* Don't return until playback has actually started */
691 queue_send(&audio_queue
, Q_AUDIO_PLAY
, offset
);
694 void audio_stop(void)
697 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
698 /* Don't return until playback has actually stopped */
699 queue_send(&audio_queue
, Q_AUDIO_STOP
, 0);
702 void audio_pause(void)
704 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
705 /* Don't return until playback has actually paused */
706 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, true);
709 void audio_resume(void)
711 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
712 /* Don't return until playback has actually resumed */
713 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, false);
716 void audio_skip(int direction
)
718 if (playlist_check(ci
.new_track
+ wps_offset
+ direction
))
720 if (global_settings
.beep
)
721 pcmbuf_beep(2000, 100, 2500*global_settings
.beep
);
723 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction
);
724 queue_post(&audio_queue
, Q_AUDIO_SKIP
, direction
);
725 /* Update wps while our message travels inside deep playback queues. */
726 wps_offset
+= direction
;
730 /* No more tracks. */
731 if (global_settings
.beep
)
732 pcmbuf_beep(1000, 100, 1500*global_settings
.beep
);
736 void audio_next(void)
741 void audio_prev(void)
746 void audio_next_dir(void)
748 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
749 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, 1);
752 void audio_prev_dir(void)
754 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
755 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, -1);
758 void audio_pre_ff_rewind(void)
760 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
761 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
764 void audio_ff_rewind(long newpos
)
766 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
767 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, newpos
);
770 void audio_flush_and_reload_tracks(void)
772 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
773 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
776 void audio_error_clear(void)
778 #ifdef AUDIO_HAVE_RECORDING
779 pcm_rec_error_clear();
783 int audio_status(void)
788 ret
|= AUDIO_STATUS_PLAY
;
791 ret
|= AUDIO_STATUS_PAUSE
;
793 #ifdef HAVE_RECORDING
794 /* Do this here for constitency with mpeg.c version */
795 /* FIXME: pcm_rec_status() is deprecated */
796 ret
|= pcm_rec_status();
802 int audio_get_file_pos(void)
807 #ifdef HAVE_DISK_STORAGE
808 void audio_set_buffer_margin(int setting
)
810 static const unsigned short lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
811 buffer_margin
= lookup
[setting
];
812 logf("buffer margin: %ld", (long)buffer_margin
);
813 set_filebuf_watermark();
817 #ifdef HAVE_CROSSFADE
818 /* Take necessary steps to enable or disable the crossfade setting */
819 void audio_set_crossfade(int enable
)
825 /* Tell it the next setting to use */
826 pcmbuf_request_crossfade_enable(enable
);
828 /* Return if size hasn't changed or this is too early to determine
829 which in the second case there's no way we could be playing
831 if (pcmbuf_is_same_size()) return;
834 was_playing
= playing
;
836 /* Playback has to be stopped before changing the buffer size */
839 /* Store the track resume position */
840 offset
= thistrack_id3
->offset
;
843 /* Blast it - audio buffer will have to be setup again next time
845 audio_get_buffer(true, &size
);
847 /* Restart playback if audio was running previously */
853 /* --- Routines called from multiple threads --- */
855 static void set_filebuf_watermark(void)
858 return; /* Audio buffers not yet set up */
860 #ifdef HAVE_DISK_STORAGE
862 int spinup
= ata_spinup_time();
864 seconds
= (spinup
/ HZ
) + 1;
868 seconds
+= buffer_margin
;
874 /* bitrate of last track in buffer dictates watermark */
875 struct mp3entry
* id3
= NULL
;
876 if (tracks
[track_widx
].taginfo_ready
)
877 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
879 id3
= bufgetid3(tracks
[track_widx
-1].id3_hid
);
881 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx
, track_widx
);
884 size_t bytes
= id3
->bitrate
* (1000/8) * seconds
;
885 buf_set_watermark(bytes
);
886 logf("fwmark: %d", bytes
);
889 /* --- Buffering callbacks --- */
891 static void buffering_low_buffer_callback(void *data
)
894 logf("low buffer callback");
896 if (filling
== STATE_FULL
|| filling
== STATE_END_OF_PLAYLIST
) {
898 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
899 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
903 static void buffering_handle_rebuffer_callback(void *data
)
906 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
907 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
910 static void buffering_handle_finished_callback(void *data
)
912 logf("handle %d finished buffering", *(int*)data
);
913 int hid
= (*(int*)data
);
915 if (hid
== tracks
[track_widx
].id3_hid
)
917 int offset
= ci
.new_track
+ wps_offset
;
918 int next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
919 /* The metadata handle for the last loaded track has been buffered.
920 We can ask the audio thread to load the rest of the track's data. */
921 LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
922 queue_post(&audio_queue
, Q_AUDIO_FINISH_LOAD
, 0);
923 if (tracks
[next_idx
].id3_hid
== hid
)
924 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
, NULL
);
928 /* This is most likely an audio handle, so we strip the useless
929 trailing tags that are left. */
932 if (hid
== tracks
[track_widx
-1].audio_hid
933 && filling
== STATE_END_OF_PLAYLIST
)
935 /* This was the last track in the playlist.
936 We now have all the data we need. */
937 logf("last track finished buffering");
938 filling
= STATE_FINISHED
;
944 /* --- Audio thread --- */
946 static bool audio_have_tracks(void)
948 return (audio_track_count() != 0);
951 static int audio_free_track_count(void)
953 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
954 return MAX_TRACK
- 1 - audio_track_count();
957 int audio_track_count(void)
959 /* Calculate difference from track_ridx to track_widx
960 * taking into account a possible wrap-around. */
961 return (MAX_TRACK
+ track_widx
- track_ridx
) & MAX_TRACK_MASK
;
964 long audio_filebufused(void)
966 return (long) buf_used();
969 /* Update track info after successful a codec track change */
970 static void audio_update_trackinfo(void)
972 /* Load the curent track's metadata into curtrack_id3 */
973 if (CUR_TI
->id3_hid
>= 0)
974 copy_mp3entry(thistrack_id3
, bufgetid3(CUR_TI
->id3_hid
));
976 /* Reset current position */
977 thistrack_id3
->elapsed
= 0;
978 thistrack_id3
->offset
= 0;
980 /* Update the codec API */
981 ci
.filesize
= CUR_TI
->filesize
;
982 ci
.id3
= thistrack_id3
;
984 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
987 /* Clear tracks between write and read, non inclusive */
988 static void audio_clear_track_entries(void)
990 int cur_idx
= track_widx
;
992 logf("Clearing tracks: r%d/w%d", track_ridx
, track_widx
);
994 /* Loop over all tracks from write-to-read */
997 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
999 if (cur_idx
== track_ridx
)
1002 clear_track_info(&tracks
[cur_idx
]);
1006 /* Clear all tracks */
1007 static bool audio_release_tracks(void)
1011 logf("releasing all tracks");
1013 for(i
= 0; i
< MAX_TRACK
; i
++)
1015 cur_idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1016 if (!clear_track_info(&tracks
[cur_idx
]))
1023 static bool audio_loadcodec(bool start_play
)
1026 char codec_path
[MAX_PATH
]; /* Full path to codec */
1027 const struct mp3entry
*id3
, *prev_id3
;
1029 if (tracks
[track_widx
].id3_hid
< 0) {
1033 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1037 const char *codec_fn
= get_codec_filename(id3
->codectype
);
1038 if (codec_fn
== NULL
)
1041 tracks
[track_widx
].codec_hid
= -1;
1045 /* Load the codec directly from disk and save some memory. */
1046 track_ridx
= track_widx
;
1047 ci
.filesize
= CUR_TI
->filesize
;
1048 ci
.id3
= thistrack_id3
;
1049 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1051 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1052 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
, (intptr_t)codec_fn
);
1057 /* If we already have another track than this one buffered */
1058 if (track_widx
!= track_ridx
)
1060 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
1062 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1063 prev_id3
= bufgetid3(tracks
[prev_track
].id3_hid
);
1065 /* If the previous codec is the same as this one, there is no need
1066 * to put another copy of it on the file buffer */
1067 if (id3
&& prev_id3
&&
1068 get_codec_base_type(id3
->codectype
) ==
1069 get_codec_base_type(prev_id3
->codectype
)
1070 && audio_codec_loaded
)
1072 logf("Reusing prev. codec");
1078 codec_get_full_path(codec_path
, codec_fn
);
1080 tracks
[track_widx
].codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1081 if (tracks
[track_widx
].codec_hid
< 0)
1084 logf("Loaded codec");
1089 /* Load metadata for the next track (with bufopen). The rest of the track
1090 loading will be handled by audio_finish_load_track once the metadata has been
1091 actually loaded by the buffering thread. */
1092 static bool audio_load_track(size_t offset
, bool start_play
)
1094 const char *trackname
;
1097 if (track_load_started
) {
1098 /* There is already a track load in progress, so track_widx hasn't been
1099 incremented yet. Loading another track would overwrite the one that
1100 hasn't finished loading. */
1101 logf("audio_load_track(): a track load is already in progress");
1105 start_play_g
= start_play
; /* will be read by audio_finish_load_track */
1107 /* Stop buffer filling if there is no free track entries.
1108 Don't fill up the last track entry (we wan't to store next track
1110 if (!audio_free_track_count())
1112 logf("No free tracks");
1117 tracks
[track_widx
].taginfo_ready
= false;
1119 logf("Buffering track: r%d/w%d", track_ridx
, track_widx
);
1120 /* Get track name from current playlist read position. */
1121 while ((trackname
= playlist_peek(last_peek_offset
)) != NULL
)
1123 /* Handle broken playlists. */
1124 fd
= open(trackname
, O_RDONLY
);
1127 logf("Open failed");
1128 /* Skip invalid entry from playlist. */
1129 playlist_skip_entry(NULL
, last_peek_offset
);
1137 logf("End-of-playlist");
1138 memset(&unbuffered_id3
, 0, sizeof(struct mp3entry
));
1139 filling
= STATE_END_OF_PLAYLIST
;
1141 if (thistrack_id3
->length
== 0 && thistrack_id3
->filesize
== 0)
1143 /* Stop playback if no valid track was found. */
1144 audio_stop_playback();
1150 tracks
[track_widx
].filesize
= filesize(fd
);
1152 if (offset
> tracks
[track_widx
].filesize
)
1155 /* Set default values */
1158 buf_set_watermark(filebuflen
/2);
1159 dsp_configure(ci
.dsp
, DSP_RESET
, 0);
1160 playlist_update_resume_info(audio_current_track());
1163 /* Get track metadata if we don't already have it. */
1164 if (tracks
[track_widx
].id3_hid
< 0)
1166 tracks
[track_widx
].id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
);
1168 if (tracks
[track_widx
].id3_hid
< 0)
1170 /* Buffer is full. */
1171 get_metadata(&unbuffered_id3
, fd
, trackname
);
1174 logf("buffer is full for now (get metadata)");
1175 filling
= STATE_FULL
;
1179 if (track_widx
== track_ridx
)
1181 /* TODO: Superfluos buffering call? */
1182 buf_request_buffer_handle(tracks
[track_widx
].id3_hid
);
1183 struct mp3entry
*id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1186 copy_mp3entry(thistrack_id3
, id3
);
1187 thistrack_id3
->offset
= offset
;
1190 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1195 playlist_update_resume_info(audio_current_track());
1200 track_load_started
= true; /* Remember that we've started loading a track */
1204 /* Second part of the track loading: We now have the metadata available, so we
1205 can load the codec, the album art and finally the audio data.
1206 This is called on the audio thread after the buffering thread calls the
1207 buffering_handle_finished_callback callback. */
1208 static void audio_finish_load_track(void)
1210 size_t file_offset
= 0;
1212 bool start_play
= start_play_g
;
1214 track_load_started
= false;
1216 if (tracks
[track_widx
].id3_hid
< 0) {
1217 logf("No metadata");
1221 struct mp3entry
*track_id3
;
1223 if (track_widx
== track_ridx
)
1224 track_id3
= thistrack_id3
;
1226 track_id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1228 if (track_id3
->length
== 0 && track_id3
->filesize
== 0)
1230 logf("audio_finish_load_track: invalid metadata");
1232 /* Invalid metadata */
1233 bufclose(tracks
[track_widx
].id3_hid
);
1234 tracks
[track_widx
].id3_hid
= -1;
1236 /* Skip invalid entry from playlist. */
1237 playlist_skip_entry(NULL
, last_peek_offset
--);
1239 /* load next track */
1240 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play
);
1241 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, start_play
);
1245 /* Try to load a cuesheet for the track */
1248 char cuepath
[MAX_PATH
];
1249 if (look_for_cuesheet_file(track_id3
->path
, cuepath
))
1252 tracks
[track_widx
].cuesheet_hid
=
1253 bufalloc(NULL
, sizeof(struct cuesheet
), TYPE_CUESHEET
);
1254 if (tracks
[track_widx
].cuesheet_hid
>= 0)
1256 bufgetdata(tracks
[track_widx
].cuesheet_hid
,
1257 sizeof(struct cuesheet
), &temp
);
1258 struct cuesheet
*cuesheet
= (struct cuesheet
*)temp
;
1259 if (!parse_cuesheet(cuepath
, cuesheet
))
1261 bufclose(tracks
[track_widx
].cuesheet_hid
);
1262 track_id3
->cuesheet
= NULL
;
1267 #ifdef HAVE_ALBUMART
1270 char aa_path
[MAX_PATH
];
1273 /* albumart_slots may change during a yield of bufopen,
1274 * but that's no problem */
1275 if (tracks
[track_widx
].aa_hid
[i
] >= 0 || !albumart_slots
[i
].used
)
1277 /* find_albumart will error out if the wps doesn't have AA */
1278 if (find_albumart(track_id3
, aa_path
, sizeof(aa_path
),
1279 &(albumart_slots
[i
].dim
)))
1281 int aa_hid
= bufopen(aa_path
, 0, TYPE_BITMAP
,
1282 &(albumart_slots
[i
].dim
));
1284 if(aa_hid
== ERR_BUFFER_FULL
)
1286 filling
= STATE_FULL
;
1287 logf("buffer is full for now (get album art)");
1288 return; /* No space for track's album art, not an error */
1290 else if (aa_hid
< 0)
1292 /* another error, ignore AlbumArt */
1293 logf("Album art loading failed");
1295 tracks
[track_widx
].aa_hid
[i
] = aa_hid
;
1302 /* Load the codec. */
1303 if (!audio_loadcodec(start_play
))
1305 if (tracks
[track_widx
].codec_hid
== ERR_BUFFER_FULL
)
1307 /* No space for codec on buffer, not an error */
1308 filling
= STATE_FULL
;
1312 /* This is an error condition, either no codec was found, or reading
1313 * the codec file failed part way through, either way, skip the track */
1314 /* FIXME: We should not use splashf from audio thread! */
1315 splashf(HZ
*2, "No codec for: %s", track_id3
->path
);
1316 /* Skip invalid entry from playlist. */
1317 playlist_skip_entry(NULL
, last_peek_offset
);
1321 track_id3
->elapsed
= 0;
1322 offset
= track_id3
->offset
;
1324 enum data_type type
= TYPE_PACKET_AUDIO
;
1326 switch (track_id3
->codectype
) {
1331 file_offset
= offset
;
1332 track_id3
->offset
= offset
;
1338 file_offset
= offset
;
1339 track_id3
->offset
= offset
;
1340 track_id3
->elapsed
= track_id3
->length
/ 2;
1344 case AFMT_OGG_VORBIS
:
1354 track_id3
->offset
= offset
;
1360 logf("Loading atomic %d",track_id3
->codectype
);
1361 type
= TYPE_ATOMIC_AUDIO
;
1365 logf("load track: %s", track_id3
->path
);
1367 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1368 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1369 else if (track_id3
->first_frame_offset
)
1370 file_offset
= track_id3
->first_frame_offset
;
1374 tracks
[track_widx
].audio_hid
= bufopen(track_id3
->path
, file_offset
, type
,
1377 /* No space left, not an error */
1378 if (tracks
[track_widx
].audio_hid
== ERR_BUFFER_FULL
)
1380 filling
= STATE_FULL
;
1381 logf("buffer is full for now (load audio)");
1384 else if (tracks
[track_widx
].audio_hid
< 0)
1386 /* another error, do not continue either */
1387 logf("Could not add audio data handle");
1391 /* All required data is now available for the codec. */
1392 tracks
[track_widx
].taginfo_ready
= true;
1396 ci
.curpos
=file_offset
;
1397 buf_request_buffer_handle(tracks
[track_widx
].audio_hid
);
1400 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1402 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, track_id3
);
1404 /* load next track */
1405 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1406 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1411 static void audio_fill_file_buffer(bool start_play
, size_t offset
)
1413 trigger_cpu_boost();
1415 /* No need to rebuffer if there are track skips pending,
1416 * however don't cancel buffering on skipping while filling. */
1417 if (ci
.new_track
!= 0 && filling
!= STATE_FILLING
)
1419 filling
= STATE_FILLING
;
1421 /* Must reset the buffer before use if trashed or voice only - voice
1422 file size shouldn't have changed so we can go straight from
1423 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1424 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1425 audio_reset_buffer();
1427 logf("Starting buffer fill");
1430 audio_clear_track_entries();
1432 /* Save the current resume position once. */
1433 playlist_update_resume_info(audio_current_track());
1435 audio_load_track(offset
, start_play
);
1438 static void audio_rebuffer(void)
1440 logf("Forcing rebuffer");
1442 clear_track_info(CUR_TI
);
1444 /* Reset track pointers */
1445 track_widx
= track_ridx
;
1446 audio_clear_track_entries();
1448 /* Reset a possibly interrupted track load */
1449 track_load_started
= false;
1451 /* Fill the buffer */
1452 last_peek_offset
= -1;
1455 if (!CUR_TI
->taginfo_ready
)
1456 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1458 audio_fill_file_buffer(false, 0);
1461 /* Called on request from the codec to get a new track. This is the codec part
1462 of the track transition. */
1463 static int audio_check_new_track(void)
1465 int track_count
= audio_track_count();
1466 int old_track_ridx
= track_ridx
;
1469 struct mp3entry
*temp
= thistrack_id3
;
1471 /* Now it's good time to send track finish events. */
1472 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
1473 /* swap the mp3entry pointers */
1474 thistrack_id3
= othertrack_id3
;
1475 othertrack_id3
= temp
;
1476 ci
.id3
= thistrack_id3
;
1477 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1482 /* regardless of the return value we need to rebuffer.
1483 if it fails the old playlist will resume, else the
1484 next dir will start playing */
1485 playlist_next_dir(ci
.new_track
);
1494 /* If the playlist isn't that big */
1497 while (!playlist_check(ci
.new_track
))
1499 if (ci
.new_track
>= 0)
1501 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1502 return Q_CODEC_REQUEST_FAILED
;
1508 /* Update the playlist */
1509 last_peek_offset
-= ci
.new_track
;
1511 if (playlist_next(ci
.new_track
) < 0)
1513 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1514 return Q_CODEC_REQUEST_FAILED
;
1520 new_playlist
= false;
1523 /* Save a pointer to the old track to allow later clearing */
1526 for (i
= 0; i
< ci
.new_track
; i
++)
1528 idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1529 struct mp3entry
*id3
= bufgetid3(tracks
[idx
].id3_hid
);
1530 ssize_t offset
= buf_handle_offset(tracks
[idx
].audio_hid
);
1531 if (!id3
|| offset
< 0 || (unsigned)offset
> id3
->first_frame_offset
)
1533 /* We don't have all the audio data for that track, so clear it,
1534 but keep the metadata. */
1535 if (tracks
[idx
].audio_hid
>= 0 && bufclose(tracks
[idx
].audio_hid
))
1537 tracks
[idx
].audio_hid
= -1;
1538 tracks
[idx
].filesize
= 0;
1543 /* Move to the new track */
1544 track_ridx
= (track_ridx
+ ci
.new_track
) & MAX_TRACK_MASK
;
1546 buf_set_base_handle(CUR_TI
->audio_hid
);
1550 wps_offset
= -ci
.new_track
;
1553 /* If it is not safe to even skip this many track entries */
1554 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
1561 forward
= ci
.new_track
> 0;
1564 /* If the target track is clearly not in memory */
1565 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
1571 /* When skipping backwards, it is possible that we've found a track that's
1572 * buffered, but which is around the track-wrap and therefore not the track
1573 * we are looking for */
1576 int cur_idx
= track_ridx
;
1577 bool taginfo_ready
= true;
1578 /* We've wrapped the buffer backwards if new > old */
1579 bool wrap
= track_ridx
> old_track_ridx
;
1583 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1585 /* if we've advanced past the wrap when cur_idx is zeroed */
1589 /* if we aren't still on the wrap and we've caught the old track */
1590 if (!(wrap
|| cur_idx
< old_track_ridx
))
1593 /* If we hit a track in between without valid tag info, bail */
1594 if (!tracks
[cur_idx
].taginfo_ready
)
1596 taginfo_ready
= false;
1607 audio_update_trackinfo();
1608 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
1609 return Q_CODEC_REQUEST_COMPLETE
;
1612 unsigned long audio_prev_elapsed(void)
1614 return prev_track_elapsed
;
1617 void audio_set_prev_elapsed(unsigned long setting
)
1619 prev_track_elapsed
= setting
;
1622 static void audio_stop_codec_flush(void)
1624 ci
.stop_codec
= true;
1627 while (audio_codec_loaded
)
1630 /* If the audio codec is not loaded any more, and the audio is still
1631 * playing, it is now and _only_ now safe to call this function from the
1633 if (pcm_is_playing())
1637 queue_clear(&pcmbuf_queue
);
1640 pcmbuf_pause(paused
);
1643 static void audio_stop_playback(void)
1647 /* If we were playing, save resume information */
1648 struct mp3entry
*id3
= NULL
;
1652 /* Set this early, the outside code yields and may allow the codec
1653 to try to wait for a reply on a buffer wait */
1654 ci
.stop_codec
= true;
1655 id3
= audio_current_track();
1658 /* Save the current playing spot, or NULL if the playlist has ended */
1659 playlist_update_resume_info(id3
);
1661 /* TODO: Create auto bookmark too? */
1663 prev_track_elapsed
= othertrack_id3
->elapsed
;
1665 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffering_low_buffer_callback
);
1668 audio_stop_codec_flush();
1671 track_load_started
= false;
1673 filling
= STATE_IDLE
;
1675 /* Mark all entries null. */
1676 audio_clear_track_entries();
1678 /* Close all tracks */
1679 audio_release_tracks();
1682 static void audio_play_start(size_t offset
)
1686 #if INPUT_SRC_CAPS != 0
1687 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1688 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
1691 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
1693 audio_stop_codec_flush();
1696 track_load_started
= false;
1702 sound_set_volume(global_settings
.volume
);
1703 track_widx
= track_ridx
= 0;
1705 /* Clear all track entries. */
1706 for (i
= 0; i
< MAX_TRACK
; i
++) {
1707 clear_track_info(&tracks
[i
]);
1710 last_peek_offset
= -1;
1712 /* Officially playing */
1713 queue_reply(&audio_queue
, 1);
1715 audio_fill_file_buffer(true, offset
);
1717 add_event(BUFFER_EVENT_BUFFER_LOW
, false, buffering_low_buffer_callback
);
1719 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1720 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1724 /* Invalidates all but currently playing track. */
1725 static void audio_invalidate_tracks(void)
1727 if (audio_have_tracks())
1729 last_peek_offset
= 0;
1730 track_widx
= track_ridx
;
1732 /* Mark all other entries null (also buffered wrong metadata). */
1733 audio_clear_track_entries();
1735 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1737 audio_fill_file_buffer(false, 0);
1741 static void audio_new_playlist(void)
1743 /* Prepare to start a new fill from the beginning of the playlist */
1744 last_peek_offset
= -1;
1745 if (audio_have_tracks())
1748 skipped_during_pause
= true;
1749 track_widx
= track_ridx
;
1750 audio_clear_track_entries();
1752 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1754 /* Mark the current track as invalid to prevent skipping back to it */
1755 CUR_TI
->taginfo_ready
= false;
1758 /* Signal the codec to initiate a track change forward */
1759 new_playlist
= true;
1762 /* Officially playing */
1763 queue_reply(&audio_queue
, 1);
1765 audio_fill_file_buffer(false, 0);
1768 /* Called on manual track skip */
1769 static void audio_initiate_track_change(long direction
)
1771 logf("audio_initiate_track_change(%ld)", direction
);
1773 ci
.new_track
+= direction
;
1774 wps_offset
-= direction
;
1776 skipped_during_pause
= true;
1779 /* Called on manual dir skip */
1780 static void audio_initiate_dir_change(long direction
)
1783 ci
.new_track
= direction
;
1785 skipped_during_pause
= true;
1788 /* Called when PCM track change is complete */
1789 static void audio_finalise_track_change(void)
1791 logf("audio_finalise_track_change");
1796 automatic_skip
= false;
1798 /* Invalidate prevtrack_id3 */
1799 memset(othertrack_id3
, 0, sizeof(struct mp3entry
));
1801 if (prev_ti
&& prev_ti
->audio_hid
< 0)
1803 /* No audio left so we clear all the track info. */
1804 clear_track_info(prev_ti
);
1807 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, thistrack_id3
);
1808 playlist_update_resume_info(audio_current_track());
1812 * Layout audio buffer as follows - iram buffer depends on target:
1813 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
1815 static void audio_reset_buffer(void)
1817 /* see audio_get_recording_buffer if this is modified */
1818 logf("audio_reset_buffer");
1820 /* If the setup of anything allocated before the file buffer is
1821 changed, do check the adjustments after the buffer_alloc call
1822 as it will likely be affected and need sliding over */
1824 /* Initially set up file buffer as all space available */
1825 malloc_buf
= audiobuf
+ talk_get_bufsize();
1826 /* Align the malloc buf to line size. Especially important to cf
1827 targets that do line reads/writes. */
1828 malloc_buf
= (unsigned char *)(((uintptr_t)malloc_buf
+ 15) & ~15);
1829 filebuf
= malloc_buf
; /* filebuf line align implied */
1830 filebuflen
= audiobufend
- filebuf
;
1834 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
1835 const size_t pcmbuf_size
= pcmbuf_init(filebuf
+ filebuflen
) +GUARD_BUFSIZE
;
1838 if(pcmbuf_size
> filebuflen
)
1839 panicf("Not enough memory for pcmbuf_init() : %d > %d",
1840 (int)pcmbuf_size
, (int)filebuflen
);
1843 filebuflen
-= pcmbuf_size
;
1845 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
1846 will already be line aligned */
1849 buffering_reset(filebuf
, filebuflen
);
1851 /* Clear any references to the file buffer */
1852 buffer_state
= AUDIOBUF_STATE_INITIALIZED
;
1854 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1855 /* Make sure everything adds up - yes, some info is a bit redundant but
1856 aids viewing and the sumation of certain variables should add up to
1857 the location of others. */
1860 const unsigned char *pcmbuf
= pcmbuf_get_meminfo(&pcmbufsize
);
1861 logf("mabuf: %08X", (unsigned)malloc_buf
);
1862 logf("fbuf: %08X", (unsigned)filebuf
);
1863 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
1864 logf("gbuf: %08X", (unsigned)(filebuf
+ filebuflen
));
1865 logf("gbufe: %08X", (unsigned)(filebuf
+ filebuflen
+ GUARD_BUFSIZE
));
1866 logf("pcmb: %08X", (unsigned)pcmbuf
);
1867 logf("pcmbe: %08X", (unsigned)(pcmbuf
+ pcmbufsize
));
1872 static void audio_thread(void)
1874 struct queue_event ev
;
1878 audio_thread_ready
= true;
1882 if (filling
!= STATE_FILLING
&& filling
!= STATE_IDLE
) {
1883 /* End of buffering, let's calculate the watermark and unboost */
1884 set_filebuf_watermark();
1888 if (!pcmbuf_queue_scan(&ev
))
1889 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
1893 case Q_AUDIO_FILL_BUFFER
:
1894 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev
.data
);
1895 audio_fill_file_buffer((bool)ev
.data
, 0);
1898 case Q_AUDIO_FINISH_LOAD
:
1899 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
1900 audio_finish_load_track();
1904 LOGFQUEUE("audio < Q_AUDIO_PLAY");
1905 if (playing
&& ev
.data
<= 0)
1906 audio_new_playlist();
1909 audio_stop_playback();
1910 audio_play_start((size_t)ev
.data
);
1915 LOGFQUEUE("audio < Q_AUDIO_STOP");
1917 audio_stop_playback();
1919 queue_clear(&audio_queue
);
1923 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
1924 if (!(bool) ev
.data
&& skipped_during_pause
1925 #ifdef HAVE_CROSSFADE
1926 && !pcmbuf_is_crossfade_active()
1929 pcmbuf_play_stop(); /* Flush old track on resume after skip */
1930 skipped_during_pause
= false;
1933 pcmbuf_pause((bool)ev
.data
);
1934 paused
= (bool)ev
.data
;
1938 LOGFQUEUE("audio < Q_AUDIO_SKIP");
1939 audio_initiate_track_change((long)ev
.data
);
1942 case Q_AUDIO_PRE_FF_REWIND
:
1943 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
1949 case Q_AUDIO_FF_REWIND
:
1950 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
1955 /* An automatic track skip is in progress. Finalize it,
1956 then go back to the previous track */
1957 audio_finalise_track_change();
1960 ci
.seek_time
= (long)ev
.data
+1;
1963 case Q_AUDIO_CHECK_NEW_TRACK
:
1964 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
1965 queue_reply(&audio_queue
, audio_check_new_track());
1968 case Q_AUDIO_DIR_SKIP
:
1969 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
1970 audio_initiate_dir_change(ev
.data
);
1974 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
1975 audio_invalidate_tracks();
1978 case Q_AUDIO_TRACK_CHANGED
:
1979 /* PCM track change done */
1980 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
1981 audio_finalise_track_change();
1984 case SYS_USB_CONNECTED
:
1985 LOGFQUEUE("audio < SYS_USB_CONNECTED");
1987 audio_stop_playback();
1988 #ifdef PLAYBACK_VOICE
1991 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1992 usb_wait_for_disconnect(&audio_queue
);
1994 /* Mark all entries null. */
1995 audio_clear_track_entries();
1997 /* release tracks to make sure all handles are closed */
1998 audio_release_tracks();
2003 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2007 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2013 /* Initialize the audio system - called from init() in main.c.
2014 * Last function because of all the references to internal symbols
2016 void audio_init(void)
2018 unsigned int audio_thread_id
;
2020 /* Can never do this twice */
2021 if (audio_is_initialized
)
2023 logf("audio: already initialized");
2027 logf("audio: initializing");
2029 /* Initialize queues before giving control elsewhere in case it likes
2030 to send messages. Thread creation will be delayed however so nothing
2031 starts running until ready if something yields such as talk_init. */
2032 queue_init(&audio_queue
, true);
2033 queue_init(&codec_queue
, false);
2034 queue_init(&pcmbuf_queue
, false);
2038 codec_init_codec_api();
2040 thistrack_id3
= &mp3entry_buf
[0];
2041 othertrack_id3
= &mp3entry_buf
[1];
2043 /* cuesheet support */
2044 if (global_settings
.cuesheet
)
2045 curr_cue
= (struct cuesheet
*)buffer_alloc(sizeof(struct cuesheet
));
2047 /* initialize the buffer */
2050 /* audio_reset_buffer must to know the size of voice buffer so init
2054 make_codec_thread();
2056 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
2057 sizeof(audio_stack
), CREATE_THREAD_FROZEN
,
2058 audio_thread_name
IF_PRIO(, PRIORITY_USER_INTERFACE
)
2061 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
2064 #ifdef PLAYBACK_VOICE
2065 voice_thread_init();
2068 #ifdef HAVE_CROSSFADE
2069 /* Set crossfade setting for next buffer init which should be about... */
2070 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
2073 /* initialize the buffering system */
2076 /* ...now! Set up the buffers */
2077 audio_reset_buffer();
2080 for(i
= 0; i
< MAX_TRACK
; i
++)
2082 tracks
[i
].audio_hid
= -1;
2083 tracks
[i
].id3_hid
= -1;
2084 tracks
[i
].codec_hid
= -1;
2085 tracks
[i
].cuesheet_hid
= -1;
2087 #ifdef HAVE_ALBUMART
2091 for (j
= 0; j
< MAX_TRACK
; j
++)
2093 tracks
[j
].aa_hid
[i
] = -1;
2098 add_event(BUFFER_EVENT_REBUFFER
, false, buffering_handle_rebuffer_callback
);
2099 add_event(BUFFER_EVENT_FINISHED
, false, buffering_handle_finished_callback
);
2101 /* Probably safe to say */
2102 audio_is_initialized
= true;
2104 sound_settings_apply();
2105 #ifdef HAVE_DISK_STORAGE
2106 audio_set_buffer_margin(global_settings
.buffer_margin
);
2109 /* it's safe to let the threads run now */
2110 #ifdef PLAYBACK_VOICE
2111 voice_thread_resume();
2113 thread_thaw(codec_thread_id
);
2114 thread_thaw(audio_thread_id
);
2118 bool audio_is_thread_ready(void)
2120 return audio_thread_ready
;
2123 size_t audio_get_filebuflen(void)
2130 return CUR_TI
->audio_hid
;
2133 int *get_codec_hid()
2135 return &tracks
[track_ridx
].codec_hid
;