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 DEBUGF("\n"); DEBUGF
81 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
82 #define LOGFQUEUE_SYS_TIMEOUT logf
84 #define LOGFQUEUE_SYS_TIMEOUT(...)
88 /* Define one constant that includes recording related functionality */
89 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
90 #define AUDIO_HAVE_RECORDING
100 Q_AUDIO_PRE_FF_REWIND
,
102 Q_AUDIO_CHECK_NEW_TRACK
,
104 Q_AUDIO_TRACK_CHANGED
,
109 Q_CODEC_REQUEST_COMPLETE
,
110 Q_CODEC_REQUEST_FAILED
,
115 #ifdef AUDIO_HAVE_RECORDING
123 static enum filling_state
{
124 STATE_IDLE
, /* audio is stopped: nothing to do */
125 STATE_FILLING
, /* adding tracks to the buffer */
126 STATE_FULL
, /* can't add any more tracks */
127 STATE_END_OF_PLAYLIST
, /* all remaining tracks have been added */
128 STATE_FINISHED
, /* all remaining tracks are fully buffered */
131 /* As defined in plugins/lib/xxx2wav.h */
132 #define GUARD_BUFSIZE (32*1024)
134 bool audio_is_initialized
= false;
135 static bool audio_thread_ready SHAREDBSS_ATTR
= false;
137 /* Variables are commented with the threads that use them: *
138 * A=audio, C=codec, V=voice. A suffix of - indicates that *
139 * the variable is read but not updated on that thread. */
140 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
142 /* Main state control */
143 static volatile bool playing SHAREDBSS_ATTR
= false;/* Is audio playing? (A) */
144 static volatile bool paused SHAREDBSS_ATTR
= false; /* Is audio paused? (A/C-) */
145 extern volatile bool audio_codec_loaded
; /* Codec loaded? (C/A-) */
146 static volatile bool fading SHAREDBSS_ATTR
= false; /* Is audio fading in/out? (A) */
148 /* Ring buffer where compressed audio and codecs are loaded */
149 static unsigned char *filebuf
= NULL
; /* Start of buffer (A/C-) */
150 static unsigned char *malloc_buf
= NULL
; /* Start of malloc buffer (A/C-) */
151 static size_t filebuflen
= 0; /* Size of buffer (A/C-) */
152 /* FIXME: make buf_ridx (C/A-) */
154 /* Possible arrangements of the buffer */
155 enum audio_buffer_state
157 AUDIOBUF_STATE_TRASHED
= -1, /* trashed; must be reset */
158 AUDIOBUF_STATE_INITIALIZED
= 0, /* voice+audio OR audio-only */
159 AUDIOBUF_STATE_VOICED_ONLY
= 1, /* voice-only */
161 static int buffer_state
= AUDIOBUF_STATE_TRASHED
; /* Buffer state */
163 /* These are used to store the current and next (or prev if the current is the last)
164 * mp3entry's in a round-robin system. This guarentees that the pointer returned
165 * by audio_current/next_track will be valid for the full duration of the
166 * currently playing track */
167 static struct mp3entry mp3entry_buf
[2];
168 struct mp3entry
*thistrack_id3
, /* the currently playing track */
169 *othertrack_id3
; /* prev track during track-change-transition, or end of playlist,
170 * next track otherwise */
171 static struct mp3entry unbuffered_id3
; /* the id3 for the first unbuffered track */
173 /* for cuesheet support */
174 static struct cuesheet
*curr_cue
= NULL
;
177 #define MAX_MULTIPLE_AA 2
180 static struct albumart_slot
{
181 struct dim dim
; /* holds width, height of the albumart */
182 int used
; /* counter, increments if something uses it */
183 } albumart_slots
[MAX_MULTIPLE_AA
];
185 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
189 #define MAX_TRACK 128
190 #define MAX_TRACK_MASK (MAX_TRACK-1)
192 /* Track info structure about songs in the file buffer (A/C-) */
193 static struct track_info
{
194 int audio_hid
; /* The ID for the track's buffer handle */
195 int id3_hid
; /* The ID for the track's metadata handle */
196 int codec_hid
; /* The ID for the track's codec handle */
198 int aa_hid
[MAX_MULTIPLE_AA
];/* The ID for the track's album art handle */
200 int cuesheet_hid
; /* The ID for the track's parsed cueesheet handle */
202 size_t filesize
; /* File total length */
204 bool taginfo_ready
; /* Is metadata read */
208 static volatile int track_ridx
= 0; /* Track being decoded (A/C-) */
209 static int track_widx
= 0; /* Track being buffered (A) */
210 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
212 static struct track_info
*prev_ti
= NULL
; /* Pointer to the previously played
215 /* Information used only for filling the buffer */
216 /* Playlist steps from playing track to next track to be buffered (A) */
217 static int last_peek_offset
= 0;
219 /* Scrobbler support */
220 static unsigned long prev_track_elapsed
= 0; /* Previous track elapsed time (C/A-)*/
222 /* Track change controls */
223 bool automatic_skip
= false; /* Who initiated in-progress skip? (C/A-) */
224 extern bool track_transition
; /* Are we in a track transition? */
225 static bool dir_skip
= false; /* Is a directory skip pending? (A) */
226 static bool new_playlist
= false; /* Are we starting a new playlist? (A) */
227 static int wps_offset
= 0; /* Pending track change offset, to keep WPS responsive (A) */
228 static bool skipped_during_pause
= false; /* Do we need to clear the PCM buffer when playback resumes (A) */
230 static bool start_play_g
= false; /* Used by audio_load_track to notify
231 audio_finish_load_track about start_play */
233 /* True when a track load is in progress, i.e. audio_load_track() has returned
234 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
235 * audio_load_track() to get called twice in a row, which would cause problems.
237 static bool track_load_started
= false;
239 #ifdef HAVE_DISK_STORAGE
240 static size_t buffer_margin
= 5; /* Buffer margin aka anti-skip buffer (A/C-) */
244 struct event_queue audio_queue SHAREDBSS_ATTR
;
245 struct event_queue codec_queue SHAREDBSS_ATTR
;
246 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR
;
248 extern struct codec_api ci
;
249 extern unsigned int codec_thread_id
;
251 /* Multiple threads */
252 /* Set the watermark to trigger buffer fill (A/C) */
253 static void set_filebuf_watermark(void);
256 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR
;
257 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
258 static const char audio_thread_name
[] = "audio";
260 static void audio_thread(void);
261 static void audio_initiate_track_change(long direction
);
262 static bool audio_have_tracks(void);
263 static void audio_reset_buffer(void);
264 static void audio_stop_playback(void);
267 /**************************************/
270 /** Pcmbuf callbacks */
272 /* Between the codec and PCM track change, we need to keep updating the
273 * "elapsed" value of the previous (to the codec, but current to the
274 * user/PCM/WPS) track, so that the progressbar reaches the end.
275 * During that transition, the WPS will display othertrack_id3. */
276 void audio_pcmbuf_position_callback(unsigned int time
)
278 time
+= othertrack_id3
->elapsed
;
280 if (time
>= othertrack_id3
->length
)
282 /* we just played the end of the track, so stop this callback */
283 track_transition
= false;
284 othertrack_id3
->elapsed
= othertrack_id3
->length
;
287 othertrack_id3
->elapsed
= time
;
290 /* Post message from pcmbuf that the end of the previous track
291 * has just been played. */
292 void audio_post_track_change(bool pcmbuf
)
296 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
297 queue_post(&pcmbuf_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
301 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
302 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
306 /* Scan the pcmbuf queue and return true if a message pulled */
307 static bool pcmbuf_queue_scan(struct queue_event
*ev
)
309 if (!queue_empty(&pcmbuf_queue
))
311 /* Transfer message to audio queue */
313 /* Pull message - never, ever any blocking call! */
314 queue_wait_w_tmo(&pcmbuf_queue
, ev
, 0);
323 /** Helper functions */
325 static struct mp3entry
*bufgetid3(int handle_id
)
330 struct mp3entry
*id3
;
331 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
333 if (ret
< 0 || ret
!= sizeof(struct mp3entry
))
339 static bool clear_track_info(struct track_info
*track
)
341 /* bufclose returns true if the handle is not found, or if it is closed
342 * successfully, so these checks are safe on non-existant handles */
346 if (track
->codec_hid
>= 0) {
347 if (bufclose(track
->codec_hid
))
348 track
->codec_hid
= -1;
353 if (track
->id3_hid
>= 0) {
354 if (bufclose(track
->id3_hid
))
360 if (track
->audio_hid
>= 0) {
361 if (bufclose(track
->audio_hid
))
362 track
->audio_hid
= -1;
372 if (track
->aa_hid
[i
] >= 0) {
373 if (bufclose(track
->aa_hid
[i
]))
374 track
->aa_hid
[i
] = -1;
382 if (track
->cuesheet_hid
>= 0) {
383 if (bufclose(track
->cuesheet_hid
))
384 track
->cuesheet_hid
= -1;
390 track
->taginfo_ready
= false;
395 /* --- External interfaces --- */
397 /* This sends a stop message and the audio thread will dump all it's
398 subsequenct messages */
399 void audio_hard_stop(void)
402 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
403 queue_send(&audio_queue
, Q_AUDIO_STOP
, 1);
404 #ifdef PLAYBACK_VOICE
409 bool audio_restore_playback(int type
)
413 case AUDIO_WANT_PLAYBACK
:
414 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
415 audio_reset_buffer();
417 case AUDIO_WANT_VOICE
:
418 if (buffer_state
== AUDIOBUF_STATE_TRASHED
)
419 audio_reset_buffer();
426 unsigned char *audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
428 unsigned char *buf
, *end
;
430 if (audio_is_initialized
)
434 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
436 /* Reset the buffering thread so that it doesn't try to use the data */
437 buffering_reset(filebuf
, filebuflen
);
439 if (buffer_size
== NULL
)
441 /* Special case for talk_init to use since it already knows it's
443 buffer_state
= AUDIOBUF_STATE_TRASHED
;
447 if (talk_buf
|| buffer_state
== AUDIOBUF_STATE_TRASHED
448 || !talk_voice_required())
450 logf("get buffer: talk, audio");
451 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
452 the talk buffer is not needed because voice isn't being used, or
453 could be AUDIOBUF_STATE_TRASHED already. If state is
454 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
455 without the caller knowing what's going on. Changing certain settings
456 may move it to a worse condition but the memory in use by something
457 else will remain undisturbed.
459 if (buffer_state
!= AUDIOBUF_STATE_TRASHED
)
462 buffer_state
= AUDIOBUF_STATE_TRASHED
;
470 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
471 still AUDIOBUF_STATE_INITIALIZED */
472 /* Skip talk buffer and move pcm buffer to end to maximize available
473 contiguous memory - no audio running means voice will not need the
475 logf("get buffer: audio");
476 buf
= audiobuf
+ talk_get_bufsize();
477 end
= audiobufend
- pcmbuf_init(audiobufend
);
478 buffer_state
= AUDIOBUF_STATE_VOICED_ONLY
;
481 *buffer_size
= end
- buf
;
486 bool audio_buffer_state_trashed(void)
488 return buffer_state
== AUDIOBUF_STATE_TRASHED
;
491 #ifdef HAVE_RECORDING
492 unsigned char *audio_get_recording_buffer(size_t *buffer_size
)
494 /* Stop audio, voice and obtain all available buffer space */
498 unsigned char *end
= audiobufend
;
499 buffer_state
= AUDIOBUF_STATE_TRASHED
;
500 *buffer_size
= end
- audiobuf
;
502 return (unsigned char *)audiobuf
;
505 bool audio_load_encoder(int afmt
)
508 const char *enc_fn
= get_codec_filename(afmt
| CODEC_TYPE_ENCODER
);
512 audio_remove_encoder();
513 ci
.enc_codec_loaded
= 0; /* clear any previous error condition */
515 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
516 queue_post(&codec_queue
, Q_ENCODER_LOAD_DISK
, (intptr_t)enc_fn
);
518 while (ci
.enc_codec_loaded
== 0)
521 logf("codec loaded: %d", ci
.enc_codec_loaded
);
523 return ci
.enc_codec_loaded
> 0;
528 } /* audio_load_encoder */
530 void audio_remove_encoder(void)
533 /* force encoder codec unload (if currently loaded) */
534 if (ci
.enc_codec_loaded
<= 0)
537 ci
.stop_encoder
= true;
538 while (ci
.enc_codec_loaded
> 0)
541 } /* audio_remove_encoder */
543 #endif /* HAVE_RECORDING */
546 struct mp3entry
* audio_current_track(void)
548 const char *filename
;
549 struct playlist_track_info trackinfo
;
551 int offset
= ci
.new_track
+ wps_offset
;
552 struct mp3entry
*write_id3
;
554 cur_idx
= (track_ridx
+ offset
) & MAX_TRACK_MASK
;
556 if (cur_idx
== track_ridx
&& *thistrack_id3
->path
)
559 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
561 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
562 thistrack_id3
->cuesheet
= curr_cue
;
563 cue_spoof_id3(thistrack_id3
->cuesheet
, thistrack_id3
);
565 return thistrack_id3
;
567 else if (automatic_skip
&& offset
== -1 && *othertrack_id3
->path
)
569 /* We're in a track transition. The codec has moved on to the next track,
570 but the audio being played is still the same (now previous) track.
571 othertrack_id3.elapsed is being updated in an ISR by
572 codec_pcmbuf_position_callback */
573 if (tracks
[cur_idx
].cuesheet_hid
>= 0 && !thistrack_id3
->cuesheet
)
575 bufread(tracks
[cur_idx
].cuesheet_hid
, sizeof(struct cuesheet
), curr_cue
);
576 othertrack_id3
->cuesheet
= curr_cue
;
577 cue_spoof_id3(othertrack_id3
->cuesheet
, othertrack_id3
);
579 return othertrack_id3
;
584 /* Codec may be using thistrack_id3, so it must not be overwritten.
585 If this is a manual skip, othertrack_id3 will become
586 thistrack_id3 in audio_check_new_track().
587 FIXME: If this is an automatic skip, it probably means multiple
588 short tracks fit in the PCM buffer. Overwriting othertrack_id3
589 can lead to an incorrect value later.
590 Note that othertrack_id3 may also be used for next track.
592 write_id3
= othertrack_id3
;
596 write_id3
= thistrack_id3
;
599 if (tracks
[cur_idx
].id3_hid
>= 0)
601 /* The current track's info has been buffered but not read yet, so get it */
602 if (bufread(tracks
[cur_idx
].id3_hid
, sizeof(struct mp3entry
), write_id3
)
603 == sizeof(struct mp3entry
))
607 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
608 we have and return that. */
610 memset(write_id3
, 0, sizeof(struct mp3entry
));
612 playlist_get_track_info(NULL
, playlist_next(0)+wps_offset
, &trackinfo
);
613 filename
= trackinfo
.filename
;
615 filename
= "No file!";
617 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
618 if (tagcache_fill_tags(write_id3
, filename
))
622 strlcpy(write_id3
->path
, filename
, sizeof(write_id3
->path
));
623 write_id3
->title
= strrchr(write_id3
->path
, '/');
624 if (!write_id3
->title
)
625 write_id3
->title
= &write_id3
->path
[0];
632 struct mp3entry
* audio_next_track(void)
635 int offset
= ci
.new_track
+ wps_offset
;
637 if (!audio_have_tracks())
640 if (wps_offset
== -1 && *thistrack_id3
->path
)
642 /* We're in a track transition. The next track for the WPS is the one
643 currently being decoded. */
644 return thistrack_id3
;
647 next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
649 if (tracks
[next_idx
].id3_hid
>= 0)
651 if (bufread(tracks
[next_idx
].id3_hid
, sizeof(struct mp3entry
), othertrack_id3
)
652 == sizeof(struct mp3entry
))
653 return othertrack_id3
;
658 if (next_idx
== track_widx
)
660 /* The next track hasn't been buffered yet, so we return the static
661 version of its metadata. */
662 return &unbuffered_id3
;
668 /* gets a pointer to the id3 data, Not thread safe!, DON'T yield()/sleep() */
669 bool audio_peek_track(struct mp3entry
** id3
, int offset
)
672 int new_offset
= ci
.new_track
+ wps_offset
+ offset
;
674 if (!audio_have_tracks())
676 next_idx
= (track_ridx
+ new_offset
) & MAX_TRACK_MASK
;
678 if (tracks
[next_idx
].id3_hid
>= 0)
680 return bufgetdata(tracks
[next_idx
].id3_hid
, 0, (void**)id3
)
681 == sizeof(struct mp3entry
);
687 int playback_current_aa_hid(int slot
)
692 int offset
= ci
.new_track
+ wps_offset
;
694 cur_idx
= track_ridx
+ offset
;
695 cur_idx
&= MAX_TRACK_MASK
;
697 return tracks
[cur_idx
].aa_hid
[slot
];
700 int playback_claim_aa_slot(struct dim
*dim
)
703 /* first try to find a slot already having the size to reuse it
704 * since we don't want albumart of the same size buffered multiple times */
707 struct albumart_slot
*slot
= &albumart_slots
[i
];
708 if (slot
->dim
.width
== dim
->width
709 && slot
->dim
.height
== dim
->height
)
715 /* size is new, find a free slot */
718 if (!albumart_slots
[i
].used
)
720 albumart_slots
[i
].used
++;
721 albumart_slots
[i
].dim
= *dim
;
725 /* sorry, no free slot */
729 void playback_release_aa_slot(int slot
)
731 /* invalidate the albumart_slot */
732 struct albumart_slot
*aa_slot
= &albumart_slots
[slot
];
733 if (aa_slot
->used
> 0)
738 void audio_play(long offset
)
742 #ifdef PLAYBACK_VOICE
743 /* Truncate any existing voice output so we don't have spelling
744 * etc. over the first part of the played track */
749 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
750 /* Don't return until playback has actually started */
751 queue_send(&audio_queue
, Q_AUDIO_PLAY
, offset
);
754 void audio_stop(void)
759 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
760 /* Don't return until playback has actually stopped */
761 queue_send(&audio_queue
, Q_AUDIO_STOP
, 0);
764 void playback_fade_on_pause(bool fade_in
, void (*update_func
)(void))
770 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE_W_FADE");
771 /* Don't return until playback has actually stopped */
772 queue_post(&audio_queue
, Q_AUDIO_PAUSE_W_FADE
, (intptr_t)fade_in
);
776 static void handle_fade(bool fade_out
)
778 int fp_global_vol
= global_settings
.volume
<< 8;
779 int fp_min_vol
= sound_min(SOUND_VOLUME
) << 8;
780 int fp_step
= (fp_global_vol
- fp_min_vol
) / 30;
783 int fp_volume
= fp_min_vol
;
785 /* zero out the sound */
786 sound_set_volume(fp_min_vol
>> 8);
788 if (skipped_during_pause
&& !pcmbuf_is_crossfade_active())
789 pcmbuf_play_stop(); /* Flush old track on resume after skip */
790 skipped_during_pause
= false;
793 while (fp_volume
< fp_global_vol
- fp_step
) {
794 fp_volume
+= fp_step
;
795 sound_set_volume(fp_volume
>> 8);
798 sound_set_volume(global_settings
.volume
);
802 int fp_volume
= fp_global_vol
;
804 while (fp_volume
> fp_min_vol
+ fp_step
) {
805 fp_volume
-= fp_step
;
806 sound_set_volume(fp_volume
>> 8);
809 #if CONFIG_CODEC != SWCODEC
811 /* let audio thread run and wait for the mas to run out of data */
812 while (!mp3_pause_done())
817 /* reset volume to what it was before the fade */
818 sound_set_volume(global_settings
.volume
);
823 void audio_pause(void)
827 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
828 /* Don't return until playback has actually paused */
829 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, true);
832 void audio_resume(void)
836 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
837 /* Don't return until playback has actually resumed */
838 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, false);
841 void audio_skip(int direction
)
843 if (playlist_check(ci
.new_track
+ wps_offset
+ direction
))
845 if (global_settings
.beep
)
846 pcmbuf_beep(2000, 100, 2500*global_settings
.beep
);
848 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction
);
849 queue_post(&audio_queue
, Q_AUDIO_SKIP
, direction
);
850 /* Update wps while our message travels inside deep playback queues. */
851 wps_offset
+= direction
;
855 /* No more tracks. */
856 if (global_settings
.beep
)
857 pcmbuf_beep(1000, 100, 1500*global_settings
.beep
);
861 void audio_next(void)
866 void audio_prev(void)
871 void audio_next_dir(void)
873 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
874 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, 1);
877 void audio_prev_dir(void)
879 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
880 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, -1);
883 void audio_pre_ff_rewind(void)
885 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
886 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
889 void audio_ff_rewind(long newpos
)
891 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
892 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, newpos
);
895 void audio_flush_and_reload_tracks(void)
897 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
898 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
901 void audio_error_clear(void)
903 #ifdef AUDIO_HAVE_RECORDING
904 pcm_rec_error_clear();
908 int audio_status(void)
913 ret
|= AUDIO_STATUS_PLAY
;
916 ret
|= AUDIO_STATUS_PAUSE
;
919 ret
|= AUDIO_STATUS_FADING
;
921 #ifdef HAVE_RECORDING
922 /* Do this here for constitency with mpeg.c version */
923 /* FIXME: pcm_rec_status() is deprecated */
924 ret
|= pcm_rec_status();
930 int audio_get_file_pos(void)
935 #ifdef HAVE_DISK_STORAGE
936 void audio_set_buffer_margin(int setting
)
938 static const unsigned short lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
939 buffer_margin
= lookup
[setting
];
940 logf("buffer margin: %ld", (long)buffer_margin
);
941 set_filebuf_watermark();
945 #ifdef HAVE_CROSSFADE
946 /* Take necessary steps to enable or disable the crossfade setting */
947 void audio_set_crossfade(int enable
)
953 /* Tell it the next setting to use */
954 pcmbuf_request_crossfade_enable(enable
);
956 /* Return if size hasn't changed or this is too early to determine
957 which in the second case there's no way we could be playing
959 if (pcmbuf_is_same_size()) return;
962 was_playing
= playing
;
964 /* Playback has to be stopped before changing the buffer size */
967 /* Store the track resume position */
968 offset
= thistrack_id3
->offset
;
971 /* Blast it - audio buffer will have to be setup again next time
973 audio_get_buffer(true, &size
);
975 /* Restart playback if audio was running previously */
981 /* --- Routines called from multiple threads --- */
983 static void set_filebuf_watermark(void)
986 return; /* Audio buffers not yet set up */
988 #ifdef HAVE_DISK_STORAGE
990 int spinup
= ata_spinup_time();
992 seconds
= (spinup
/ HZ
) + 1;
996 seconds
+= buffer_margin
;
1002 /* bitrate of last track in buffer dictates watermark */
1003 struct mp3entry
* id3
= NULL
;
1004 if (tracks
[track_widx
].taginfo_ready
)
1005 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1007 id3
= bufgetid3(tracks
[track_widx
-1].id3_hid
);
1009 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx
, track_widx
);
1012 size_t bytes
= id3
->bitrate
* (1000/8) * seconds
;
1013 buf_set_watermark(bytes
);
1014 logf("fwmark: %d", bytes
);
1017 /* --- Buffering callbacks --- */
1019 static void buffering_low_buffer_callback(void *data
)
1022 logf("low buffer callback");
1024 if (filling
== STATE_FULL
|| filling
== STATE_END_OF_PLAYLIST
) {
1025 /* force a refill */
1026 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1027 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1031 static void buffering_handle_rebuffer_callback(void *data
)
1034 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
1035 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
1038 static void buffering_handle_finished_callback(void *data
)
1040 logf("handle %d finished buffering", *(int*)data
);
1041 int hid
= (*(int*)data
);
1043 if (hid
== tracks
[track_widx
].id3_hid
)
1045 int offset
= ci
.new_track
+ wps_offset
;
1046 int next_idx
= (track_ridx
+ offset
+ 1) & MAX_TRACK_MASK
;
1047 /* The metadata handle for the last loaded track has been buffered.
1048 We can ask the audio thread to load the rest of the track's data. */
1049 LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
1050 queue_post(&audio_queue
, Q_AUDIO_FINISH_LOAD
, 0);
1051 if (tracks
[next_idx
].id3_hid
== hid
)
1052 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE
, NULL
);
1056 /* This is most likely an audio handle, so we strip the useless
1057 trailing tags that are left. */
1060 if (hid
== tracks
[track_widx
-1].audio_hid
1061 && filling
== STATE_END_OF_PLAYLIST
)
1063 /* This was the last track in the playlist.
1064 We now have all the data we need. */
1065 logf("last track finished buffering");
1066 filling
= STATE_FINISHED
;
1072 /* --- Audio thread --- */
1074 static bool audio_have_tracks(void)
1076 return (audio_track_count() != 0);
1079 static int audio_free_track_count(void)
1081 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
1082 return MAX_TRACK
- 1 - audio_track_count();
1085 int audio_track_count(void)
1087 /* Calculate difference from track_ridx to track_widx
1088 * taking into account a possible wrap-around. */
1089 return (MAX_TRACK
+ track_widx
- track_ridx
) & MAX_TRACK_MASK
;
1092 long audio_filebufused(void)
1094 return (long) buf_used();
1097 /* Update track info after successful a codec track change */
1098 static void audio_update_trackinfo(void)
1100 /* Load the curent track's metadata into curtrack_id3 */
1101 if (CUR_TI
->id3_hid
>= 0)
1102 copy_mp3entry(thistrack_id3
, bufgetid3(CUR_TI
->id3_hid
));
1104 /* Reset current position */
1105 thistrack_id3
->elapsed
= 0;
1106 thistrack_id3
->offset
= 0;
1108 /* Update the codec API */
1109 ci
.filesize
= CUR_TI
->filesize
;
1110 ci
.id3
= thistrack_id3
;
1112 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1115 /* Clear tracks between write and read, non inclusive */
1116 static void audio_clear_track_entries(void)
1118 int cur_idx
= track_widx
;
1120 logf("Clearing tracks: r%d/w%d", track_ridx
, track_widx
);
1122 /* Loop over all tracks from write-to-read */
1125 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1127 if (cur_idx
== track_ridx
)
1130 clear_track_info(&tracks
[cur_idx
]);
1134 /* Clear all tracks */
1135 static bool audio_release_tracks(void)
1139 logf("releasing all tracks");
1141 for(i
= 0; i
< MAX_TRACK
; i
++)
1143 cur_idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1144 if (!clear_track_info(&tracks
[cur_idx
]))
1151 static bool audio_loadcodec(bool start_play
)
1154 char codec_path
[MAX_PATH
]; /* Full path to codec */
1155 const struct mp3entry
*id3
, *prev_id3
;
1157 if (tracks
[track_widx
].id3_hid
< 0) {
1161 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1165 const char *codec_fn
= get_codec_filename(id3
->codectype
);
1166 if (codec_fn
== NULL
)
1169 tracks
[track_widx
].codec_hid
= -1;
1173 /* Load the codec directly from disk and save some memory. */
1174 track_ridx
= track_widx
;
1175 ci
.filesize
= CUR_TI
->filesize
;
1176 ci
.id3
= thistrack_id3
;
1177 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
1179 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1180 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
, (intptr_t)codec_fn
);
1185 /* If we already have another track than this one buffered */
1186 if (track_widx
!= track_ridx
)
1188 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
1190 id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1191 prev_id3
= bufgetid3(tracks
[prev_track
].id3_hid
);
1193 /* If the previous codec is the same as this one, there is no need
1194 * to put another copy of it on the file buffer */
1195 if (id3
&& prev_id3
&&
1196 get_codec_base_type(id3
->codectype
) ==
1197 get_codec_base_type(prev_id3
->codectype
)
1198 && audio_codec_loaded
)
1200 logf("Reusing prev. codec");
1206 codec_get_full_path(codec_path
, codec_fn
);
1208 tracks
[track_widx
].codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
, NULL
);
1209 if (tracks
[track_widx
].codec_hid
< 0)
1212 logf("Loaded codec");
1217 /* Load metadata for the next track (with bufopen). The rest of the track
1218 loading will be handled by audio_finish_load_track once the metadata has been
1219 actually loaded by the buffering thread. */
1220 static bool audio_load_track(size_t offset
, bool start_play
)
1222 const char *trackname
;
1225 if (track_load_started
) {
1226 /* There is already a track load in progress, so track_widx hasn't been
1227 incremented yet. Loading another track would overwrite the one that
1228 hasn't finished loading. */
1229 logf("audio_load_track(): a track load is already in progress");
1233 start_play_g
= start_play
; /* will be read by audio_finish_load_track */
1235 /* Stop buffer filling if there is no free track entries.
1236 Don't fill up the last track entry (we wan't to store next track
1238 if (!audio_free_track_count())
1240 logf("No free tracks");
1245 tracks
[track_widx
].taginfo_ready
= false;
1247 logf("Buffering track: r%d/w%d", track_ridx
, track_widx
);
1248 /* Get track name from current playlist read position. */
1249 while ((trackname
= playlist_peek(last_peek_offset
)) != NULL
)
1251 /* Handle broken playlists. */
1252 fd
= open(trackname
, O_RDONLY
);
1255 logf("Open failed");
1256 /* Skip invalid entry from playlist. */
1257 playlist_skip_entry(NULL
, last_peek_offset
);
1265 logf("End-of-playlist");
1266 memset(&unbuffered_id3
, 0, sizeof(struct mp3entry
));
1267 filling
= STATE_END_OF_PLAYLIST
;
1269 if (thistrack_id3
->length
== 0 && thistrack_id3
->filesize
== 0)
1271 /* Stop playback if no valid track was found. */
1272 audio_stop_playback();
1278 tracks
[track_widx
].filesize
= filesize(fd
);
1280 if (offset
> tracks
[track_widx
].filesize
)
1283 /* Set default values */
1286 buf_set_watermark(filebuflen
/2);
1287 dsp_configure(ci
.dsp
, DSP_RESET
, 0);
1288 playlist_update_resume_info(audio_current_track());
1291 /* Get track metadata if we don't already have it. */
1292 if (tracks
[track_widx
].id3_hid
< 0)
1294 tracks
[track_widx
].id3_hid
= bufopen(trackname
, 0, TYPE_ID3
, NULL
);
1296 if (tracks
[track_widx
].id3_hid
< 0)
1298 /* Buffer is full. */
1299 get_metadata(&unbuffered_id3
, fd
, trackname
);
1302 logf("buffer is full for now (get metadata)");
1303 filling
= STATE_FULL
;
1307 if (track_widx
== track_ridx
)
1309 /* TODO: Superfluos buffering call? */
1310 buf_request_buffer_handle(tracks
[track_widx
].id3_hid
);
1311 struct mp3entry
*id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1314 copy_mp3entry(thistrack_id3
, id3
);
1315 thistrack_id3
->offset
= offset
;
1318 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1323 playlist_update_resume_info(audio_current_track());
1328 track_load_started
= true; /* Remember that we've started loading a track */
1332 /* Second part of the track loading: We now have the metadata available, so we
1333 can load the codec, the album art and finally the audio data.
1334 This is called on the audio thread after the buffering thread calls the
1335 buffering_handle_finished_callback callback. */
1336 static void audio_finish_load_track(void)
1338 size_t file_offset
= 0;
1340 bool start_play
= start_play_g
;
1342 track_load_started
= false;
1344 if (tracks
[track_widx
].id3_hid
< 0) {
1345 logf("No metadata");
1349 struct mp3entry
*track_id3
;
1351 if (track_widx
== track_ridx
)
1352 track_id3
= thistrack_id3
;
1354 track_id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
1356 if (track_id3
->length
== 0 && track_id3
->filesize
== 0)
1358 logf("audio_finish_load_track: invalid metadata");
1360 /* Invalid metadata */
1361 bufclose(tracks
[track_widx
].id3_hid
);
1362 tracks
[track_widx
].id3_hid
= -1;
1364 /* Skip invalid entry from playlist. */
1365 playlist_skip_entry(NULL
, last_peek_offset
--);
1367 /* load next track */
1368 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play
);
1369 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, start_play
);
1373 /* Try to load a cuesheet for the track */
1376 char cuepath
[MAX_PATH
];
1377 if (look_for_cuesheet_file(track_id3
->path
, cuepath
))
1380 tracks
[track_widx
].cuesheet_hid
=
1381 bufalloc(NULL
, sizeof(struct cuesheet
), TYPE_CUESHEET
);
1382 if (tracks
[track_widx
].cuesheet_hid
>= 0)
1384 bufgetdata(tracks
[track_widx
].cuesheet_hid
,
1385 sizeof(struct cuesheet
), &temp
);
1386 struct cuesheet
*cuesheet
= (struct cuesheet
*)temp
;
1387 if (!parse_cuesheet(cuepath
, cuesheet
))
1389 bufclose(tracks
[track_widx
].cuesheet_hid
);
1390 track_id3
->cuesheet
= NULL
;
1395 #ifdef HAVE_ALBUMART
1398 char aa_path
[MAX_PATH
];
1401 /* albumart_slots may change during a yield of bufopen,
1402 * but that's no problem */
1403 if (tracks
[track_widx
].aa_hid
[i
] >= 0 || !albumart_slots
[i
].used
)
1405 /* find_albumart will error out if the wps doesn't have AA */
1406 if (find_albumart(track_id3
, aa_path
, sizeof(aa_path
),
1407 &(albumart_slots
[i
].dim
)))
1409 int aa_hid
= bufopen(aa_path
, 0, TYPE_BITMAP
,
1410 &(albumart_slots
[i
].dim
));
1412 if(aa_hid
== ERR_BUFFER_FULL
)
1414 filling
= STATE_FULL
;
1415 logf("buffer is full for now (get album art)");
1416 return; /* No space for track's album art, not an error */
1418 else if (aa_hid
< 0)
1420 /* another error, ignore AlbumArt */
1421 logf("Album art loading failed");
1423 tracks
[track_widx
].aa_hid
[i
] = aa_hid
;
1430 /* Load the codec. */
1431 if (!audio_loadcodec(start_play
))
1433 if (tracks
[track_widx
].codec_hid
== ERR_BUFFER_FULL
)
1435 /* No space for codec on buffer, not an error */
1436 filling
= STATE_FULL
;
1440 /* This is an error condition, either no codec was found, or reading
1441 * the codec file failed part way through, either way, skip the track */
1442 /* FIXME: We should not use splashf from audio thread! */
1443 splashf(HZ
*2, "No codec for: %s", track_id3
->path
);
1444 /* Skip invalid entry from playlist. */
1445 playlist_skip_entry(NULL
, last_peek_offset
);
1449 track_id3
->elapsed
= 0;
1450 offset
= track_id3
->offset
;
1451 size_t resume_rewind
= (global_settings
.resume_rewind
*
1452 track_id3
->bitrate
* 1000) / 8;
1454 if (offset
< resume_rewind
)
1460 offset
-= resume_rewind
;
1463 enum data_type type
= TYPE_PACKET_AUDIO
;
1465 switch (track_id3
->codectype
) {
1470 file_offset
= offset
;
1476 file_offset
= offset
;
1477 track_id3
->elapsed
= track_id3
->length
/ 2;
1484 logf("Loading atomic %d",track_id3
->codectype
);
1485 type
= TYPE_ATOMIC_AUDIO
;
1489 /* no special treatment needed */
1493 track_id3
->offset
= offset
;
1495 logf("load track: %s", track_id3
->path
);
1497 if (file_offset
> AUDIO_REBUFFER_GUESS_SIZE
)
1498 file_offset
-= AUDIO_REBUFFER_GUESS_SIZE
;
1499 else if (track_id3
->first_frame_offset
)
1500 file_offset
= track_id3
->first_frame_offset
;
1504 tracks
[track_widx
].audio_hid
= bufopen(track_id3
->path
, file_offset
, type
,
1507 /* No space left, not an error */
1508 if (tracks
[track_widx
].audio_hid
== ERR_BUFFER_FULL
)
1510 filling
= STATE_FULL
;
1511 logf("buffer is full for now (load audio)");
1514 else if (tracks
[track_widx
].audio_hid
< 0)
1516 /* another error, do not continue either */
1517 logf("Could not add audio data handle");
1521 /* All required data is now available for the codec. */
1522 tracks
[track_widx
].taginfo_ready
= true;
1526 ci
.curpos
=file_offset
;
1527 buf_request_buffer_handle(tracks
[track_widx
].audio_hid
);
1530 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1532 send_event(PLAYBACK_EVENT_TRACK_BUFFER
, track_id3
);
1534 /* load next track */
1535 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1536 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1541 static void audio_fill_file_buffer(bool start_play
, size_t offset
)
1543 trigger_cpu_boost();
1545 /* No need to rebuffer if there are track skips pending,
1546 * however don't cancel buffering on skipping while filling. */
1547 if (ci
.new_track
!= 0 && filling
!= STATE_FILLING
)
1549 filling
= STATE_FILLING
;
1551 /* Must reset the buffer before use if trashed or voice only - voice
1552 file size shouldn't have changed so we can go straight from
1553 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1554 if (buffer_state
!= AUDIOBUF_STATE_INITIALIZED
)
1555 audio_reset_buffer();
1557 logf("Starting buffer fill");
1560 audio_clear_track_entries();
1562 /* Save the current resume position once. */
1563 playlist_update_resume_info(audio_current_track());
1565 audio_load_track(offset
, start_play
);
1568 static void audio_rebuffer(void)
1570 logf("Forcing rebuffer");
1572 clear_track_info(CUR_TI
);
1574 /* Reset track pointers */
1575 track_widx
= track_ridx
;
1576 audio_clear_track_entries();
1578 /* Reset a possibly interrupted track load */
1579 track_load_started
= false;
1581 /* Fill the buffer */
1582 last_peek_offset
= -1;
1585 if (!CUR_TI
->taginfo_ready
)
1586 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1588 audio_fill_file_buffer(false, 0);
1591 /* Called on request from the codec to get a new track. This is the codec part
1592 of the track transition. */
1593 static int audio_check_new_track(void)
1595 int track_count
= audio_track_count();
1596 int old_track_ridx
= track_ridx
;
1599 struct mp3entry
*temp
= thistrack_id3
;
1601 /* Now it's good time to send track finish events. */
1602 send_event(PLAYBACK_EVENT_TRACK_FINISH
, thistrack_id3
);
1603 /* swap the mp3entry pointers */
1604 thistrack_id3
= othertrack_id3
;
1605 othertrack_id3
= temp
;
1606 ci
.id3
= thistrack_id3
;
1607 memset(thistrack_id3
, 0, sizeof(struct mp3entry
));
1612 /* regardless of the return value we need to rebuffer.
1613 if it fails the old playlist will resume, else the
1614 next dir will start playing */
1615 playlist_next_dir(ci
.new_track
);
1624 /* If the playlist isn't that big */
1627 while (!playlist_check(ci
.new_track
))
1629 if (ci
.new_track
>= 0)
1631 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1632 return Q_CODEC_REQUEST_FAILED
;
1638 /* Update the playlist */
1639 last_peek_offset
-= ci
.new_track
;
1641 if (playlist_next(ci
.new_track
) < 0)
1643 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1644 return Q_CODEC_REQUEST_FAILED
;
1650 new_playlist
= false;
1653 /* Save a pointer to the old track to allow later clearing */
1656 for (i
= 0; i
< ci
.new_track
; i
++)
1658 idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
1659 struct mp3entry
*id3
= bufgetid3(tracks
[idx
].id3_hid
);
1660 ssize_t offset
= buf_handle_offset(tracks
[idx
].audio_hid
);
1661 if (!id3
|| offset
< 0 || (unsigned)offset
> id3
->first_frame_offset
)
1663 /* We don't have all the audio data for that track, so clear it,
1664 but keep the metadata. */
1665 if (tracks
[idx
].audio_hid
>= 0 && bufclose(tracks
[idx
].audio_hid
))
1667 tracks
[idx
].audio_hid
= -1;
1668 tracks
[idx
].filesize
= 0;
1673 /* Move to the new track */
1674 track_ridx
= (track_ridx
+ ci
.new_track
) & MAX_TRACK_MASK
;
1675 buf_set_base_handle(CUR_TI
->audio_hid
);
1680 wps_offset
= -ci
.new_track
;
1683 /* If it is not safe to even skip this many track entries */
1684 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
1691 forward
= ci
.new_track
> 0;
1694 /* If the target track is clearly not in memory */
1695 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
1701 /* When skipping backwards, it is possible that we've found a track that's
1702 * buffered, but which is around the track-wrap and therefore not the track
1703 * we are looking for */
1706 int cur_idx
= track_ridx
;
1707 bool taginfo_ready
= true;
1708 /* We've wrapped the buffer backwards if new > old */
1709 bool wrap
= track_ridx
> old_track_ridx
;
1713 cur_idx
= (cur_idx
+ 1) & MAX_TRACK_MASK
;
1715 /* if we've advanced past the wrap when cur_idx is zeroed */
1719 /* if we aren't still on the wrap and we've caught the old track */
1720 if (!(wrap
|| cur_idx
< old_track_ridx
))
1723 /* If we hit a track in between without valid tag info, bail */
1724 if (!tracks
[cur_idx
].taginfo_ready
)
1726 taginfo_ready
= false;
1737 audio_update_trackinfo();
1738 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
1739 return Q_CODEC_REQUEST_COMPLETE
;
1742 unsigned long audio_prev_elapsed(void)
1744 return prev_track_elapsed
;
1747 void audio_set_prev_elapsed(unsigned long setting
)
1749 prev_track_elapsed
= setting
;
1752 static void audio_stop_codec_flush(void)
1754 ci
.stop_codec
= true;
1757 while (audio_codec_loaded
)
1760 /* If the audio codec is not loaded any more, and the audio is still
1761 * playing, it is now and _only_ now safe to call this function from the
1763 if (pcm_is_playing())
1767 queue_clear(&pcmbuf_queue
);
1770 pcmbuf_pause(paused
);
1773 static void audio_stop_playback(void)
1777 /* If we were playing, save resume information */
1778 struct mp3entry
*id3
= NULL
;
1782 /* Set this early, the outside code yields and may allow the codec
1783 to try to wait for a reply on a buffer wait */
1784 ci
.stop_codec
= true;
1785 id3
= audio_current_track();
1788 /* Save the current playing spot, or NULL if the playlist has ended */
1789 playlist_update_resume_info(id3
);
1791 /* TODO: Create auto bookmark too? */
1793 prev_track_elapsed
= othertrack_id3
->elapsed
;
1795 remove_event(BUFFER_EVENT_BUFFER_LOW
, buffering_low_buffer_callback
);
1798 audio_stop_codec_flush();
1801 track_load_started
= false;
1803 filling
= STATE_IDLE
;
1805 /* Mark all entries null. */
1806 audio_clear_track_entries();
1808 /* Close all tracks */
1809 audio_release_tracks();
1812 static void audio_play_start(size_t offset
)
1816 #if INPUT_SRC_CAPS != 0
1817 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1818 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
1821 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
1823 audio_stop_codec_flush();
1826 track_load_started
= false;
1832 sound_set_volume(global_settings
.volume
);
1833 track_widx
= track_ridx
= 0;
1834 buf_set_base_handle(-1);
1836 /* Clear all track entries. */
1837 for (i
= 0; i
< MAX_TRACK
; i
++) {
1838 clear_track_info(&tracks
[i
]);
1841 last_peek_offset
= -1;
1843 /* Officially playing */
1844 queue_reply(&audio_queue
, 1);
1846 audio_fill_file_buffer(true, offset
);
1848 add_event(BUFFER_EVENT_BUFFER_LOW
, false, buffering_low_buffer_callback
);
1850 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1851 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1855 /* Invalidates all but currently playing track. */
1856 static void audio_invalidate_tracks(void)
1858 if (audio_have_tracks())
1860 last_peek_offset
= 0;
1861 track_widx
= track_ridx
;
1863 /* Mark all other entries null (also buffered wrong metadata). */
1864 audio_clear_track_entries();
1866 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1868 audio_fill_file_buffer(false, 0);
1869 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, thistrack_id3
);
1873 static void audio_new_playlist(void)
1875 /* Prepare to start a new fill from the beginning of the playlist */
1876 last_peek_offset
= -1;
1877 if (audio_have_tracks())
1880 skipped_during_pause
= true;
1881 track_widx
= track_ridx
;
1882 audio_clear_track_entries();
1884 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
1886 /* Mark the current track as invalid to prevent skipping back to it */
1887 CUR_TI
->taginfo_ready
= false;
1890 /* Signal the codec to initiate a track change forward */
1891 new_playlist
= true;
1894 /* Officially playing */
1895 queue_reply(&audio_queue
, 1);
1897 audio_fill_file_buffer(false, 0);
1900 /* Called on manual track skip */
1901 static void audio_initiate_track_change(long direction
)
1903 logf("audio_initiate_track_change(%ld)", direction
);
1905 ci
.new_track
+= direction
;
1906 wps_offset
-= direction
;
1908 skipped_during_pause
= true;
1911 /* Called on manual dir skip */
1912 static void audio_initiate_dir_change(long direction
)
1915 ci
.new_track
= direction
;
1917 skipped_during_pause
= true;
1920 /* Called when PCM track change is complete */
1921 static void audio_finalise_track_change(void)
1923 logf("audio_finalise_track_change");
1928 automatic_skip
= false;
1930 /* Invalidate prevtrack_id3 */
1931 memset(othertrack_id3
, 0, sizeof(struct mp3entry
));
1933 if (prev_ti
&& prev_ti
->audio_hid
< 0)
1935 /* No audio left so we clear all the track info. */
1936 clear_track_info(prev_ti
);
1939 send_event(PLAYBACK_EVENT_TRACK_CHANGE
, thistrack_id3
);
1940 playlist_update_resume_info(audio_current_track());
1944 * Layout audio buffer as follows - iram buffer depends on target:
1945 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
1947 static void audio_reset_buffer(void)
1949 /* see audio_get_recording_buffer if this is modified */
1950 logf("audio_reset_buffer");
1952 /* If the setup of anything allocated before the file buffer is
1953 changed, do check the adjustments after the buffer_alloc call
1954 as it will likely be affected and need sliding over */
1956 /* Initially set up file buffer as all space available */
1957 malloc_buf
= audiobuf
+ talk_get_bufsize();
1958 /* Align the malloc buf to line size. Especially important to cf
1959 targets that do line reads/writes. */
1960 malloc_buf
= (unsigned char *)(((uintptr_t)malloc_buf
+ 15) & ~15);
1961 filebuf
= malloc_buf
; /* filebuf line align implied */
1962 filebuflen
= audiobufend
- filebuf
;
1966 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
1967 const size_t pcmbuf_size
= pcmbuf_init(filebuf
+ filebuflen
) +GUARD_BUFSIZE
;
1970 if(pcmbuf_size
> filebuflen
)
1971 panicf("Not enough memory for pcmbuf_init() : %d > %d",
1972 (int)pcmbuf_size
, (int)filebuflen
);
1975 filebuflen
-= pcmbuf_size
;
1977 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
1978 will already be line aligned */
1981 buffering_reset(filebuf
, filebuflen
);
1983 /* Clear any references to the file buffer */
1984 buffer_state
= AUDIOBUF_STATE_INITIALIZED
;
1986 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1987 /* Make sure everything adds up - yes, some info is a bit redundant but
1988 aids viewing and the sumation of certain variables should add up to
1989 the location of others. */
1992 const unsigned char *pcmbuf
= pcmbuf_get_meminfo(&pcmbufsize
);
1993 logf("mabuf: %08X", (unsigned)malloc_buf
);
1994 logf("fbuf: %08X", (unsigned)filebuf
);
1995 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
1996 logf("gbuf: %08X", (unsigned)(filebuf
+ filebuflen
));
1997 logf("gbufe: %08X", (unsigned)(filebuf
+ filebuflen
+ GUARD_BUFSIZE
));
1998 logf("pcmb: %08X", (unsigned)pcmbuf
);
1999 logf("pcmbe: %08X", (unsigned)(pcmbuf
+ pcmbufsize
));
2004 static void audio_thread(void)
2006 struct queue_event ev
;
2010 audio_thread_ready
= true;
2014 if (filling
!= STATE_FILLING
&& filling
!= STATE_IDLE
) {
2015 /* End of buffering, let's calculate the watermark and unboost */
2016 set_filebuf_watermark();
2020 if (!pcmbuf_queue_scan(&ev
))
2021 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
2025 case Q_AUDIO_FILL_BUFFER
:
2026 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev
.data
);
2027 audio_fill_file_buffer((bool)ev
.data
, 0);
2030 case Q_AUDIO_FINISH_LOAD
:
2031 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2032 audio_finish_load_track();
2033 buf_set_base_handle(CUR_TI
->audio_hid
);
2037 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2038 if (playing
&& ev
.data
<= 0)
2039 audio_new_playlist();
2042 audio_stop_playback();
2043 audio_play_start((size_t)ev
.data
);
2048 LOGFQUEUE("audio < Q_AUDIO_STOP");
2050 audio_stop_playback();
2052 queue_clear(&audio_queue
);
2054 case Q_AUDIO_PAUSE_W_FADE
:
2056 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2057 if (global_settings
.fade_on_stop
)
2060 handle_fade(ev
.data
);
2062 if (!fading
|| (fading
&& !ev
.data
))
2063 { /* fade will do this for us */
2064 if (!(bool) ev
.data
&& skipped_during_pause
2065 #ifdef HAVE_CROSSFADE
2066 && !pcmbuf_is_crossfade_active()
2069 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2070 skipped_during_pause
= false;
2074 if (!fading
|| (fading
&& !ev
.data
))
2075 pcmbuf_pause((bool)ev
.data
); /* done in fading */
2076 paused
= (bool)ev
.data
;
2081 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2082 audio_initiate_track_change((long)ev
.data
);
2085 case Q_AUDIO_PRE_FF_REWIND
:
2086 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2092 case Q_AUDIO_FF_REWIND
:
2093 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2098 /* An automatic track skip is in progress. Finalize it,
2099 then go back to the previous track */
2100 audio_finalise_track_change();
2103 ci
.seek_time
= (long)ev
.data
+1;
2106 case Q_AUDIO_CHECK_NEW_TRACK
:
2107 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2108 queue_reply(&audio_queue
, audio_check_new_track());
2111 case Q_AUDIO_DIR_SKIP
:
2112 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2113 audio_initiate_dir_change(ev
.data
);
2117 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2118 audio_invalidate_tracks();
2121 case Q_AUDIO_TRACK_CHANGED
:
2122 /* PCM track change done */
2123 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2124 audio_finalise_track_change();
2127 case SYS_USB_CONNECTED
:
2128 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2130 audio_stop_playback();
2131 #ifdef PLAYBACK_VOICE
2134 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2135 usb_wait_for_disconnect(&audio_queue
);
2137 /* Mark all entries null. */
2138 audio_clear_track_entries();
2140 /* release tracks to make sure all handles are closed */
2141 audio_release_tracks();
2146 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2150 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2156 /* Initialize the audio system - called from init() in main.c.
2157 * Last function because of all the references to internal symbols
2159 void audio_init(void)
2161 unsigned int audio_thread_id
;
2163 /* Can never do this twice */
2164 if (audio_is_initialized
)
2166 logf("audio: already initialized");
2170 logf("audio: initializing");
2172 /* Initialize queues before giving control elsewhere in case it likes
2173 to send messages. Thread creation will be delayed however so nothing
2174 starts running until ready if something yields such as talk_init. */
2175 queue_init(&audio_queue
, true);
2176 queue_init(&codec_queue
, false);
2177 queue_init(&pcmbuf_queue
, false);
2181 codec_init_codec_api();
2183 thistrack_id3
= &mp3entry_buf
[0];
2184 othertrack_id3
= &mp3entry_buf
[1];
2186 /* cuesheet support */
2187 if (global_settings
.cuesheet
)
2188 curr_cue
= (struct cuesheet
*)buffer_alloc(sizeof(struct cuesheet
));
2190 /* initialize the buffer */
2193 /* audio_reset_buffer must to know the size of voice buffer so init
2197 make_codec_thread();
2199 audio_thread_id
= create_thread(audio_thread
, audio_stack
,
2200 sizeof(audio_stack
), CREATE_THREAD_FROZEN
,
2201 audio_thread_name
IF_PRIO(, PRIORITY_USER_INTERFACE
)
2204 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
,
2207 #ifdef PLAYBACK_VOICE
2208 voice_thread_init();
2211 #ifdef HAVE_CROSSFADE
2212 /* Set crossfade setting for next buffer init which should be about... */
2213 pcmbuf_request_crossfade_enable(global_settings
.crossfade
);
2216 /* initialize the buffering system */
2219 /* ...now! Set up the buffers */
2220 audio_reset_buffer();
2223 for(i
= 0; i
< MAX_TRACK
; i
++)
2225 tracks
[i
].audio_hid
= -1;
2226 tracks
[i
].id3_hid
= -1;
2227 tracks
[i
].codec_hid
= -1;
2228 tracks
[i
].cuesheet_hid
= -1;
2230 #ifdef HAVE_ALBUMART
2234 for (j
= 0; j
< MAX_TRACK
; j
++)
2236 tracks
[j
].aa_hid
[i
] = -1;
2241 add_event(BUFFER_EVENT_REBUFFER
, false, buffering_handle_rebuffer_callback
);
2242 add_event(BUFFER_EVENT_FINISHED
, false, buffering_handle_finished_callback
);
2244 /* Probably safe to say */
2245 audio_is_initialized
= true;
2247 sound_settings_apply();
2248 #ifdef HAVE_DISK_STORAGE
2249 audio_set_buffer_margin(global_settings
.buffer_margin
);
2252 /* it's safe to let the threads run now */
2253 #ifdef PLAYBACK_VOICE
2254 voice_thread_resume();
2256 thread_thaw(codec_thread_id
);
2257 thread_thaw(audio_thread_id
);
2261 bool audio_is_thread_ready(void)
2263 return audio_thread_ready
;
2266 size_t audio_get_filebuflen(void)
2273 return CUR_TI
->audio_hid
;
2276 int *get_codec_hid()
2278 return &tracks
[track_ridx
].codec_hid
;