1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2005 Miika Pekkarinen
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 /* TODO: Check for a possibly broken codepath on a rapid skip, stop event */
21 /* TODO: same in reverse ^^ */
22 /* TODO: Also play, stop ^^ */
23 /* TODO: Can use the track changed callback to detect end of track and seek
24 * in the previous track until this happens */
25 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
26 * play whilst audio is paused */
27 /* Design: we have prev_ti already, have a conditional for what type of seek
28 * to do on a seek request, if it is a previous track seek, skip previous,
29 * and in the request_next_track callback set the offset up the same way that
30 * starting from an offset works. */
31 /* This is also necesary to prevent the problem with buffer overwriting on
32 * automatic track changes */
53 #include "mp3_playback.h"
56 #include "main_menu.h"
62 #include "pcm_playback.h"
63 #include "pcm_record.h"
68 #ifdef HAVE_LCD_BITMAP
70 #include "peakmeter.h"
82 #include "recording.h"
85 #define PLAYBACK_VOICE
88 /* default point to start buffer refill */
89 #define AUDIO_DEFAULT_WATERMARK (1024*512)
90 /* amount of data to read in one read() call */
91 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
92 /* point at which the file buffer will fight for CPU time */
93 #define AUDIO_FILEBUF_CRITICAL (1024*128)
94 /* amount of guess-space to allow for codecs that must hunt and peck
95 * for their correct seeek target, 32k seems a good size */
96 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
98 /* macros to enable logf for queues */
100 #define PLAYBACK_LOGQUEUES /* Define this for logf output of all queuing */
103 #ifdef PLAYBACK_LOGQUEUES
104 #define LOGFQUEUE(s) logf("%s", s)
114 Q_AUDIO_PRE_FF_REWIND
,
116 Q_AUDIO_REBUFFER_SEEK
,
117 Q_AUDIO_CHECK_NEW_TRACK
,
119 Q_AUDIO_TRACK_CHANGED
,
121 Q_AUDIO_NEW_PLAYLIST
,
125 Q_CODEC_REQUEST_PENDING
,
126 Q_CODEC_REQUEST_COMPLETE
,
127 Q_CODEC_REQUEST_FAILED
,
135 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
141 /* As defined in plugins/lib/xxx2wav.h */
143 #define MALLOC_BUFSIZE (512*1024)
144 #define GUARD_BUFSIZE (32*1024)
146 #define MALLOC_BUFSIZE (100*1024)
147 #define GUARD_BUFSIZE (8*1024)
150 /* As defined in plugin.lds */
151 #if CONFIG_CPU == PP5020 || CONFIG_CPU == PP5002
152 #define CODEC_IRAM_ORIGIN 0x4000c000
153 #elif defined(IAUDIO_X5)
154 #define CODEC_IRAM_ORIGIN 0x10014000
156 #define CODEC_IRAM_ORIGIN 0x1000c000
158 #define CODEC_IRAM_SIZE 0xc000
160 #ifdef PLAYBACK_VOICE
162 static unsigned char sim_iram
[CODEC_IRAM_SIZE
];
163 #undef CODEC_IRAM_ORIGIN
164 #define CODEC_IRAM_ORIGIN sim_iram
169 extern bool audio_is_initialized
;
171 static bool audio_is_initialized
= false;
176 static struct mutex mutex_codecthread
;
177 static struct event_queue codec_callback_queue
;
179 static volatile bool audio_codec_loaded
;
180 static volatile bool playing
;
181 static volatile bool paused
;
183 /* Is file buffer currently being refilled? */
184 static volatile bool filling IDATA_ATTR
;
186 volatile int current_codec IDATA_ATTR
;
187 extern unsigned char codecbuf
[];
189 /* Ring buffer where tracks and codecs are loaded. */
190 static char *filebuf
;
192 /* Total size of the ring buffer. */
195 /* Ring buffer read and write indexes. */
196 static volatile size_t buf_ridx IDATA_ATTR
;
197 static volatile size_t buf_widx IDATA_ATTR
;
199 /* Ring buffer arithmetic */
200 #define RINGBUF_ADD(p,v) ((p+v)<filebuflen ? p+v : p+v-filebuflen)
201 #define RINGBUF_SUB(p,v) ((p>=v) ? p-v : p+filebuflen-v)
203 /* Bytes available in the buffer. */
204 #define FILEBUFUSED RINGBUF_SUB(buf_widx, buf_ridx)
206 /* Codec swapping pointers */
207 static unsigned char *iram_buf
[2];
208 static unsigned char *dram_buf
[2];
210 /* Step count to the next unbuffered track. */
211 static int last_peek_offset
;
213 /* Track information (count in file buffer, read/write indexes for
214 track ring structure. */
215 static int track_ridx
;
216 static int track_widx
;
217 static bool track_changed
; /* Audio and codec threads */
219 /* Partially loaded song's file handle to continue buffering later. */
220 static int current_fd
;
222 /* Information about how many bytes left on the buffer re-fill run. */
223 static size_t fill_bytesleft
;
225 /* Track info structure about songs in the file buffer. */
226 static struct track_info tracks
[MAX_TRACK
]; /* Audio thread */
228 /* Pointer to track info structure about current song playing. */
229 #define CUR_TI (&tracks[track_ridx])
231 /* Pointer to track info structure about previous played song. */
232 static struct track_info
*prev_ti
; /* Audio and codec threads */
234 /* Have we reached end of the current playlist. */
235 static bool playlist_end
= false; /* Audio thread */
237 /* Was the skip being executed manual or automatic? */
238 static bool automatic_skip
= false; /* Audio and codec threads */
239 static bool dir_skip
= false; /* Audio thread */
240 static bool new_playlist
= false; /* Audio thread */
241 static int wps_offset
= 0;
243 /* Callback function to call when current track has really changed. */
244 void (*track_changed_callback
)(struct mp3entry
*id3
);
245 void (*track_buffer_callback
)(struct mp3entry
*id3
, bool last_track
);
246 void (*track_unbuffer_callback
)(struct mp3entry
*id3
, bool last_track
);
249 static size_t conf_watermark
;
250 static size_t conf_filechunk
;
251 static size_t conf_preseek
;
252 static size_t buffer_margin
;
253 static bool v1first
= false;
255 /* Multiple threads */
256 static const char * get_codec_filename(int enc_spec
);
257 static void set_filebuf_watermark(int seconds
);
260 static struct event_queue audio_queue
;
261 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
262 static const char audio_thread_name
[] = "audio";
264 static void audio_thread(void);
265 static void audio_initiate_track_change(long direction
);
266 static bool audio_have_tracks(void);
267 static void audio_reset_buffer(void);
270 extern struct codec_api ci
;
271 static struct event_queue codec_queue
;
272 static long codec_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)]
274 static const char codec_thread_name
[] = "codec";
275 /* For modifying thread priority later. */
276 struct thread_entry
*codec_thread_p
;
279 #ifdef PLAYBACK_VOICE
280 extern struct codec_api ci_voice
;
282 static volatile bool voice_thread_start
;
283 static volatile bool voice_is_playing
;
284 static volatile bool voice_codec_loaded
;
285 static void (*voice_getmore
)(unsigned char** start
, int* size
);
286 static char *voicebuf
;
287 static size_t voice_remaining
;
288 static struct thread_entry
*voice_thread_p
= NULL
;
290 static struct event_queue voice_queue
;
291 static long voice_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)]
293 static const char voice_thread_name
[] = "voice codec";
295 void (*callback
)(unsigned char **start
, int *size
);
300 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
301 static void voice_boost_cpu(bool state
);
303 #define voice_boost_cpu(state) do { } while(0)
305 static void voice_thread(void);
307 #endif /* PLAYBACK_VOICE */
309 /* --- External interfaces --- */
311 void mp3_play_data(const unsigned char* start
, int size
,
312 void (*get_more
)(unsigned char** start
, int* size
))
314 #ifdef PLAYBACK_VOICE
315 static struct voice_info voice_clip
;
316 voice_clip
.callback
= get_more
;
317 voice_clip
.buf
= (char *)start
;
318 voice_clip
.size
= size
;
319 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
320 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
321 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
322 queue_post(&voice_queue
, Q_VOICE_PLAY
, &voice_clip
);
323 voice_thread_start
= true;
324 voice_boost_cpu(true);
332 void mp3_play_stop(void)
334 #ifdef PLAYBACK_VOICE
335 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
336 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
340 bool mp3_pause_done(void)
342 return pcm_is_paused();
345 void mpeg_id3_options(bool _v1first
)
350 void audio_load_encoder(int enc_id
)
352 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
353 const char *enc_fn
= get_codec_filename(enc_id
| CODEC_TYPE_ENCODER
);
357 audio_remove_encoder();
359 LOGFQUEUE("audio > codec Q_ENCODER_LOAD_DISK");
360 queue_post(&codec_queue
, Q_ENCODER_LOAD_DISK
, (void *)enc_fn
);
362 while (!ci
.enc_codec_loaded
)
367 } /* audio_load_encoder */
369 void audio_remove_encoder(void)
371 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
372 /* force encoder codec unload (if previously loaded) */
373 if (!ci
.enc_codec_loaded
)
376 ci
.stop_codec
= true;
377 while (ci
.enc_codec_loaded
)
380 } /* audio_remove_encoder */
382 struct mp3entry
* audio_current_track(void)
384 const char *filename
;
386 static struct mp3entry temp_id3
;
388 int offset
= ci
.new_track
+ wps_offset
;
390 cur_idx
= track_ridx
+ offset
;
391 cur_idx
&= MAX_TRACK_MASK
;
393 if (tracks
[cur_idx
].taginfo_ready
)
394 return &tracks
[cur_idx
].id3
;
396 memset(&temp_id3
, 0, sizeof(struct mp3entry
));
398 filename
= playlist_peek(offset
);
400 filename
= "No file!";
402 #ifdef HAVE_TC_RAMCACHE
403 if (tagcache_fill_tags(&temp_id3
, filename
))
407 p
= strrchr(filename
, '/');
413 strncpy(temp_id3
.path
, p
, sizeof(temp_id3
.path
)-1);
414 temp_id3
.title
= &temp_id3
.path
[0];
419 struct mp3entry
* audio_next_track(void)
421 int next_idx
= track_ridx
;
423 if (!audio_have_tracks())
427 next_idx
&= MAX_TRACK_MASK
;
429 if (!tracks
[next_idx
].taginfo_ready
)
432 return &tracks
[next_idx
].id3
;
435 bool audio_has_changed_track(void)
439 track_changed
= false;
446 void audio_play(long offset
)
449 if (playing
&& offset
<= 0)
451 LOGFQUEUE("audio > audio Q_AUDIO_NEW_PLAYLIST");
452 queue_post(&audio_queue
, Q_AUDIO_NEW_PLAYLIST
, 0);
456 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
457 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
458 LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
459 queue_post(&audio_queue
, Q_AUDIO_PLAY
, (void *)offset
);
465 void audio_stop(void)
467 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
468 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
473 void audio_pause(void)
475 LOGFQUEUE("audio > audio Q_AUDIO_PAUSE");
476 queue_post(&audio_queue
, Q_AUDIO_PAUSE
, (void *)true);
479 void audio_resume(void)
481 LOGFQUEUE("audio > audio Q_AUDIO_PAUSE resume");
482 queue_post(&audio_queue
, Q_AUDIO_PAUSE
, (void *)false);
485 void audio_next(void)
487 if (playlist_check(ci
.new_track
+ wps_offset
+ 1))
489 if (global_settings
.beep
)
490 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
492 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
493 queue_post(&audio_queue
, Q_AUDIO_SKIP
, (void *)1);
494 /* Keep wps fast while our message travels inside deep playback queues. */
496 track_changed
= true;
500 /* No more tracks. */
501 if (global_settings
.beep
)
502 pcmbuf_beep(1000, 100, 1000*global_settings
.beep
);
506 void audio_prev(void)
508 if (playlist_check(ci
.new_track
+ wps_offset
- 1))
510 if (global_settings
.beep
)
511 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
513 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
514 queue_post(&audio_queue
, Q_AUDIO_SKIP
, (void *)-1);
515 /* Keep wps fast while our message travels inside deep playback queues. */
517 track_changed
= true;
521 /* No more tracks. */
522 if (global_settings
.beep
)
523 pcmbuf_beep(1000, 100, 1000*global_settings
.beep
);
527 void audio_next_dir(void)
529 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
530 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, (void *)1);
533 void audio_prev_dir(void)
535 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
536 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, (void *)-1);
539 void audio_pre_ff_rewind(void)
541 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
542 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
545 void audio_ff_rewind(long newpos
)
547 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
548 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, (int *)newpos
);
551 void audio_flush_and_reload_tracks(void)
553 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
554 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
557 void audio_error_clear(void)
561 int audio_status(void)
566 ret
|= AUDIO_STATUS_PLAY
;
569 ret
|= AUDIO_STATUS_PAUSE
;
571 #ifdef HAVE_RECORDING
572 /* Do this here for constitency with mpeg.c version */
573 ret
|= pcm_rec_status();
579 bool audio_query_poweroff(void)
581 return !(playing
&& paused
);
584 int audio_get_file_pos(void)
589 void audio_set_buffer_margin(int setting
)
591 static const int lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
592 buffer_margin
= lookup
[setting
];
593 logf("buffer margin: %ds", buffer_margin
);
594 set_filebuf_watermark(buffer_margin
);
597 /* Set crossfade & PCM buffer length. */
598 void audio_set_crossfade(int enable
)
601 bool was_playing
= (playing
&& audio_is_initialized
);
608 return; /* Audio buffers not yet set up */
612 seconds
= global_settings
.crossfade_fade_out_delay
613 + global_settings
.crossfade_fade_out_duration
;
615 /* Buffer has to be at least 2s long. */
617 logf("buf len: %d", seconds
);
618 size
= seconds
* (NATIVE_FREQUENCY
*4);
621 size
= NATIVE_FREQUENCY
*2;
623 if (pcmbuf_get_bufsize() == size
)
628 /* Store the track resume position */
629 offset
= CUR_TI
->id3
.offset
;
631 /* Playback has to be stopped before changing the buffer size. */
632 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK
));
633 LOGFQUEUE("audio > audio Q_AUDIO_STOP");
634 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
635 while (audio_codec_loaded
)
641 /* Re-initialize audio system. */
643 pcmbuf_crossfade_enable(enable
);
644 audio_reset_buffer();
645 logf("abuf:%dB", pcmbuf_get_bufsize());
646 logf("fbuf:%dB", filebuflen
);
650 /* Restart playback. */
653 LOGFQUEUE("audio > audio Q_AUDIO_PLAY");
654 queue_post(&audio_queue
, Q_AUDIO_PLAY
, (void *)offset
);
656 /* Wait for the playback to start again (and display the splash
657 screen during that period. */
663 void audio_preinit(void)
665 logf("playback system pre-init");
668 current_codec
= CODEC_IDX_AUDIO
;
671 audio_codec_loaded
= false;
672 #ifdef PLAYBACK_VOICE
673 voice_is_playing
= false;
674 voice_thread_start
= false;
675 voice_codec_loaded
= false;
677 track_changed
= false;
679 track_buffer_callback
= NULL
;
680 track_unbuffer_callback
= NULL
;
681 track_changed_callback
= NULL
;
682 /* Just to prevent CUR_TI never be anything random. */
685 mutex_init(&mutex_codecthread
);
687 queue_init(&audio_queue
, true);
688 queue_init(&codec_queue
, true);
689 /* create a private queue */
690 queue_init(&codec_callback_queue
, false);
692 create_thread(audio_thread
, audio_stack
, sizeof(audio_stack
),
693 audio_thread_name
IF_PRIO(, PRIORITY_BUFFERING
));
696 void audio_init(void)
698 LOGFQUEUE("audio > audio Q_AUDIO_POSTINIT");
699 queue_post(&audio_queue
, Q_AUDIO_POSTINIT
, 0);
702 void voice_init(void)
704 #ifdef PLAYBACK_VOICE
706 return; /* Audio buffers not yet set up */
711 if (!talk_voice_required())
714 logf("Starting voice codec");
715 queue_init(&voice_queue
, true);
716 voice_thread_p
= create_thread(voice_thread
, voice_stack
,
717 sizeof(voice_stack
), voice_thread_name
718 IF_PRIO(, PRIORITY_PLAYBACK
));
720 while (!voice_codec_loaded
)
725 void voice_stop(void)
727 #ifdef PLAYBACK_VOICE
728 /* Messages should not be posted to voice codec queue unless it is the
729 current codec or deadlocks happen.
731 if (current_codec
!= CODEC_IDX_VOICE
)
734 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
735 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
736 while (voice_is_playing
)
745 /* --- Routines called from multiple threads --- */
747 #ifdef PLAYBACK_VOICE
748 static void swap_codec(void)
750 int my_codec
= current_codec
;
752 logf("swapping out codec:%d", my_codec
);
754 /* Save our current IRAM and DRAM */
755 memcpy(iram_buf
[my_codec
], (unsigned char *)CODEC_IRAM_ORIGIN
,
757 memcpy(dram_buf
[my_codec
], codecbuf
, CODEC_SIZE
);
759 /* Release my semaphore */
760 mutex_unlock(&mutex_codecthread
);
762 /* Loop until the other codec has locked and run */
764 /* Release my semaphore and force a task switch. */
766 } while (my_codec
== current_codec
);
768 /* Wait for other codec to unlock */
769 mutex_lock(&mutex_codecthread
);
772 current_codec
= my_codec
;
774 /* Reload our IRAM and DRAM */
775 memcpy((unsigned char *)CODEC_IRAM_ORIGIN
, iram_buf
[my_codec
],
778 memcpy(codecbuf
, dram_buf
[my_codec
], CODEC_SIZE
);
780 logf("resuming codec:%d", my_codec
);
784 static void set_filebuf_watermark(int seconds
)
788 if (current_codec
== CODEC_IDX_VOICE
)
792 return; /* Audio buffers not yet set up */
794 bytes
= MAX(CUR_TI
->id3
.bitrate
* seconds
* (1000/8), conf_watermark
);
795 bytes
= MIN(bytes
, filebuflen
/ 2);
796 conf_watermark
= bytes
;
799 static const char * get_codec_filename(int enc_spec
)
802 int type
= enc_spec
& CODEC_TYPE_MASK
;
803 int afmt
= enc_spec
& CODEC_AFMT_MASK
;
805 if ((unsigned)afmt
>= AFMT_NUM_CODECS
)
806 type
= AFMT_UNKNOWN
| (type
& CODEC_TYPE_MASK
);
808 fname
= (type
== CODEC_TYPE_DECODER
) ?
809 audio_formats
[afmt
].codec_fn
: audio_formats
[afmt
].codec_enc_fn
;
812 (type
== CODEC_TYPE_ENCODER
) ? "Encoder" : "Decoder",
813 afmt
, fname
? fname
: "<unknown>");
816 } /* get_codec_filename */
819 /* --- Voice thread --- */
821 #ifdef PLAYBACK_VOICE
823 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
824 static void voice_boost_cpu(bool state
)
826 static bool voice_cpu_boosted
= false;
828 if (state
!= voice_cpu_boosted
)
830 voice_cpu_boosted
= state
;
831 cpu_boost_id(state
, CPUBOOSTID_PLAYBACK_VOICE
);
836 static bool voice_pcmbuf_insert_split_callback(
837 const void *ch1
, const void *ch2
, size_t length
)
847 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED
)
848 length
*= 2; /* Length is per channel */
852 long est_output_size
= dsp_output_size(length
);
854 while ((dest
= pcmbuf_request_voice_buffer(est_output_size
,
855 &output_size
, playing
)) == NULL
)
857 if (playing
&& audio_codec_loaded
)
863 /* Get the real input_size for output_size bytes, guarding
864 * against resampling buffer overflows. */
865 input_size
= dsp_input_size(output_size
);
869 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
870 output_size
, length
, input_size
);
871 /* If this happens, there are samples of codec data that don't
872 * become a number of pcm samples, and something is broken */
876 /* Input size has grown, no error, just don't write more than length */
877 if ((size_t)input_size
> length
)
880 output_size
= dsp_process(dest
, src
, input_size
);
884 pcmbuf_mix_voice(output_size
);
885 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) && audio_codec_loaded
)
889 pcmbuf_write_complete(output_size
);
891 length
-= input_size
;
895 } /* voice_pcmbuf_insert_split_callback */
897 static bool voice_pcmbuf_insert_callback(const char *buf
, size_t length
)
899 /* TODO: The audiobuffer API should probably be updated, and be based on
900 * pcmbuf_insert_split(). */
901 long real_length
= length
;
903 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED
)
904 length
/= 2; /* Length is per channel */
906 /* Second channel is only used for non-interleaved stereo. */
907 return voice_pcmbuf_insert_split_callback(buf
, buf
+ (real_length
/ 2),
911 static void* voice_get_memory_callback(size_t *size
)
917 static void voice_set_elapsed_callback(unsigned int value
)
922 static void voice_set_offset_callback(size_t value
)
927 static size_t voice_filebuf_callback(void *ptr
, size_t size
)
935 static void* voice_request_buffer_callback(size_t *realsize
, size_t reqsize
)
939 if (ci_voice
.new_track
)
947 if (voice_is_playing
|| playing
)
948 queue_wait_w_tmo(&voice_queue
, &ev
, 0);
950 queue_wait(&voice_queue
, &ev
);
951 if (!voice_is_playing
)
953 if (ev
.id
== SYS_TIMEOUT
)
954 ev
.id
= Q_AUDIO_PLAY
;
959 LOGFQUEUE("voice < Q_AUDIO_PLAY");
962 if (audio_codec_loaded
)
968 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
969 case Q_ENCODER_RECORD
:
970 LOGFQUEUE("voice < Q_ENCODER_RECORD");
976 LOGFQUEUE("voice < Q_VOICE_STOP");
977 if (voice_is_playing
)
979 /* Clear the current buffer */
980 voice_is_playing
= false;
981 voice_getmore
= NULL
;
984 voice_boost_cpu(false);
986 /* Force the codec to think it's changing tracks */
987 ci_voice
.new_track
= 1;
994 case SYS_USB_CONNECTED
:
995 LOGFQUEUE("voice < SYS_USB_CONNECTED");
996 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
997 if (audio_codec_loaded
)
999 usb_wait_for_disconnect(&voice_queue
);
1003 LOGFQUEUE("voice < Q_VOICE_PLAY");
1004 if (!voice_is_playing
)
1006 /* Slight hack - flush PCM buffer if only being used for voice */
1007 if (!playing
&& pcm_is_playing())
1010 /* Set up new voice data */
1011 struct voice_info
*voice_data
;
1012 voice_is_playing
= true;
1013 voice_boost_cpu(true);
1014 voice_data
= ev
.data
;
1015 voice_remaining
= voice_data
->size
;
1016 voicebuf
= voice_data
->buf
;
1017 voice_getmore
= voice_data
->callback
;
1019 goto voice_play_clip
;
1022 LOGFQUEUE("voice < SYS_TIMEOUT");
1023 goto voice_play_clip
;
1026 LOGFQUEUE("voice < default");
1032 if (voice_remaining
== 0 || voicebuf
== NULL
)
1035 voice_getmore((unsigned char **)&voicebuf
, (int *)&voice_remaining
);
1037 /* If this clip is done */
1038 if (voice_remaining
== 0)
1040 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1041 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
1042 /* Force pcm playback. */
1043 if (!pcm_is_playing())
1044 pcmbuf_play_start();
1048 *realsize
= MIN(voice_remaining
, reqsize
);
1054 } /* voice_request_buffer_callback */
1056 static void voice_advance_buffer_callback(size_t amount
)
1058 amount
= MIN(amount
, voice_remaining
);
1060 voice_remaining
-= amount
;
1063 static void voice_advance_buffer_loc_callback(void *ptr
)
1065 size_t amount
= (size_t)ptr
- (size_t)voicebuf
;
1067 voice_advance_buffer_callback(amount
);
1070 static off_t
voice_mp3_get_filepos_callback(int newtime
)
1077 static void voice_do_nothing(void)
1082 static bool voice_seek_buffer_callback(size_t newpos
)
1089 static bool voice_request_next_track_callback(void)
1091 ci_voice
.new_track
= 0;
1095 static void voice_thread(void)
1099 logf("Loading voice codec");
1100 voice_codec_loaded
= true;
1101 mutex_lock(&mutex_codecthread
);
1102 current_codec
= CODEC_IDX_VOICE
;
1103 dsp_configure(DSP_RESET
, 0);
1104 voice_remaining
= 0;
1105 voice_getmore
= NULL
;
1107 codec_load_file(get_codec_filename(AFMT_MPA_L3
), &ci_voice
);
1109 logf("Voice codec finished");
1110 voice_codec_loaded
= false;
1111 mutex_unlock(&mutex_codecthread
);
1113 } /* voice_thread */
1115 #endif /* PLAYBACK_VOICE */
1117 /* --- Codec thread --- */
1119 static bool codec_pcmbuf_insert_split_callback(
1120 const void *ch1
, const void *ch2
, size_t length
)
1130 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED
)
1131 length
*= 2; /* Length is per channel */
1135 long est_output_size
= dsp_output_size(length
);
1136 /* Prevent audio from a previous track from playing */
1137 if (ci
.new_track
|| ci
.stop_codec
)
1140 while ((dest
= pcmbuf_request_buffer(est_output_size
,
1141 &output_size
)) == NULL
)
1144 if (ci
.seek_time
|| ci
.new_track
|| ci
.stop_codec
)
1148 /* Get the real input_size for output_size bytes, guarding
1149 * against resampling buffer overflows. */
1150 input_size
= dsp_input_size(output_size
);
1152 if (input_size
<= 0)
1154 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld<=0\n",
1155 output_size
, length
, input_size
);
1156 /* If this happens, there are samples of codec data that don't
1157 * become a number of pcm samples, and something is broken */
1161 /* Input size has grown, no error, just don't write more than length */
1162 if ((size_t)input_size
> length
)
1163 input_size
= length
;
1165 output_size
= dsp_process(dest
, src
, input_size
);
1167 pcmbuf_write_complete(output_size
);
1169 #ifdef PLAYBACK_VOICE
1170 if ((voice_is_playing
|| voice_thread_start
)
1171 && pcm_is_playing() && voice_codec_loaded
&&
1172 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1174 voice_thread_start
= false;
1179 length
-= input_size
;
1183 } /* codec_pcmbuf_insert_split_callback */
1185 static bool codec_pcmbuf_insert_callback(const char *buf
, size_t length
)
1187 /* TODO: The audiobuffer API should probably be updated, and be based on
1188 * pcmbuf_insert_split(). */
1189 long real_length
= length
;
1191 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED
)
1192 length
/= 2; /* Length is per channel */
1194 /* Second channel is only used for non-interleaved stereo. */
1195 return codec_pcmbuf_insert_split_callback(buf
, buf
+ (real_length
/ 2),
1199 static void* codec_get_memory_callback(size_t *size
)
1201 *size
= MALLOC_BUFSIZE
;
1202 return &audiobuf
[talk_get_bufsize()];
1205 static void codec_pcmbuf_position_callback(size_t size
) ICODE_ATTR
;
1206 static void codec_pcmbuf_position_callback(size_t size
)
1208 unsigned int time
= size
* 1000 / 4 / NATIVE_FREQUENCY
+
1209 prev_ti
->id3
.elapsed
;
1211 if (time
>= prev_ti
->id3
.length
)
1213 pcmbuf_set_position_callback(NULL
);
1214 prev_ti
->id3
.elapsed
= prev_ti
->id3
.length
;
1217 prev_ti
->id3
.elapsed
= time
;
1220 static void codec_set_elapsed_callback(unsigned int value
)
1222 unsigned int latency
;
1226 #ifdef AB_REPEAT_ENABLE
1227 ab_position_report(value
);
1230 latency
= pcmbuf_get_latency();
1231 if (value
< latency
)
1232 CUR_TI
->id3
.elapsed
= 0;
1233 else if (value
- latency
> CUR_TI
->id3
.elapsed
||
1234 value
- latency
< CUR_TI
->id3
.elapsed
- 2)
1236 CUR_TI
->id3
.elapsed
= value
- latency
;
1240 static void codec_set_offset_callback(size_t value
)
1242 unsigned int latency
;
1247 latency
= pcmbuf_get_latency() * CUR_TI
->id3
.bitrate
/ 8;
1248 if (value
< latency
)
1249 CUR_TI
->id3
.offset
= 0;
1251 CUR_TI
->id3
.offset
= value
- latency
;
1254 static void codec_advance_buffer_counters(size_t amount
)
1256 buf_ridx
= RINGBUF_ADD(buf_ridx
, amount
);
1258 ci
.curpos
+= amount
;
1259 CUR_TI
->available
-= amount
;
1261 /* Start buffer filling as necessary. */
1262 if (!pcmbuf_is_lowdata() && !filling
)
1264 if (conf_watermark
&& FILEBUFUSED
<= conf_watermark
&& playing
)
1266 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1267 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1272 /* copy up-to size bytes into ptr and return the actual size copied */
1273 static size_t codec_filebuf_callback(void *ptr
, size_t size
)
1275 char *buf
= (char *)ptr
;
1279 if (ci
.stop_codec
|| !playing
)
1282 /* The ammount to copy is the lesser of the requested amount and the
1283 * amount left of the current track (both on disk and already loaded) */
1284 copy_n
= MIN(size
, CUR_TI
->available
+ CUR_TI
->filerem
);
1286 /* Nothing requested OR nothing left */
1290 /* Let the disk buffer catch fill until enough data is available */
1291 while (copy_n
> CUR_TI
->available
)
1295 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1296 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1300 if (ci
.stop_codec
|| ci
.new_track
)
1304 /* Copy as much as possible without wrapping */
1305 part_n
= MIN(copy_n
, filebuflen
- buf_ridx
);
1306 memcpy(buf
, &filebuf
[buf_ridx
], part_n
);
1307 /* Copy the rest in the case of a wrap */
1308 if (part_n
< copy_n
) {
1309 memcpy(&buf
[part_n
], &filebuf
[0], copy_n
- part_n
);
1312 /* Update read and other position pointers */
1313 codec_advance_buffer_counters(copy_n
);
1315 /* Return the actual amount of data copied to the buffer */
1317 } /* codec_filebuf_callback */
1319 static void* codec_request_buffer_callback(size_t *realsize
, size_t reqsize
)
1321 size_t short_n
, copy_n
, buf_rem
;
1329 copy_n
= MIN(reqsize
, CUR_TI
->available
+ CUR_TI
->filerem
);
1336 while (copy_n
> CUR_TI
->available
)
1340 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1341 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1345 if (ci
.stop_codec
|| ci
.new_track
)
1352 /* How much is left at the end of the file buffer before wrap? */
1353 buf_rem
= filebuflen
- buf_ridx
;
1355 /* If we can't satisfy the request without wrapping */
1356 if (buf_rem
< copy_n
)
1358 /* How short are we? */
1359 short_n
= copy_n
- buf_rem
;
1361 /* If we can fudge it with the guardbuf */
1362 if (short_n
< GUARD_BUFSIZE
)
1363 memcpy(&filebuf
[filebuflen
], &filebuf
[0], short_n
);
1370 return (char *)&filebuf
[buf_ridx
];
1371 } /* codec_request_buffer_callback */
1373 static int get_codec_base_type(int type
)
1385 static void codec_advance_buffer_callback(size_t amount
)
1387 if (amount
> CUR_TI
->available
+ CUR_TI
->filerem
)
1388 amount
= CUR_TI
->available
+ CUR_TI
->filerem
;
1390 while (amount
> CUR_TI
->available
&& filling
)
1393 if (amount
> CUR_TI
->available
)
1397 LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK");
1398 queue_post(&audio_queue
,
1399 Q_AUDIO_REBUFFER_SEEK
, (void *)(ci
.curpos
+ amount
));
1401 queue_wait(&codec_callback_queue
, &ev
);
1404 case Q_CODEC_REQUEST_FAILED
:
1405 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1406 ci
.stop_codec
= true;
1409 case Q_CODEC_REQUEST_COMPLETE
:
1410 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1414 LOGFQUEUE("codec < default");
1415 ci
.stop_codec
= true;
1420 codec_advance_buffer_counters(amount
);
1422 codec_set_offset_callback(ci
.curpos
);
1425 static void codec_advance_buffer_loc_callback(void *ptr
)
1427 size_t amount
= (size_t)ptr
- (size_t)&filebuf
[buf_ridx
];
1429 codec_advance_buffer_callback(amount
);
1432 /* Copied from mpeg.c. Should be moved somewhere else. */
1433 static int codec_get_file_pos(void)
1436 struct mp3entry
*id3
= audio_current_track();
1442 /* Use the TOC to find the new position */
1443 unsigned int percent
, remainder
;
1444 int curtoc
, nexttoc
, plen
;
1446 percent
= (id3
->elapsed
*100)/id3
->length
;
1450 curtoc
= id3
->toc
[percent
];
1453 nexttoc
= id3
->toc
[percent
+1];
1457 pos
= (id3
->filesize
/256)*curtoc
;
1459 /* Use the remainder to get a more accurate position */
1460 remainder
= (id3
->elapsed
*100)%id3
->length
;
1461 remainder
= (remainder
*100)/id3
->length
;
1462 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
1463 pos
+= (plen
/100)*remainder
;
1467 /* No TOC exists, estimate the new position */
1468 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
1469 (id3
->elapsed
/ 1000);
1472 else if (id3
->bitrate
)
1473 pos
= id3
->elapsed
* (id3
->bitrate
/ 8);
1477 /* Don't seek right to the end of the file so that we can
1478 transition properly to the next song */
1479 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
1480 pos
= id3
->filesize
- id3
->id3v1len
- 1;
1481 /* skip past id3v2 tag and other leading garbage */
1482 else if (pos
< (int)id3
->first_frame_offset
)
1483 pos
= id3
->first_frame_offset
;
1488 static off_t
codec_mp3_get_filepos_callback(int newtime
)
1492 CUR_TI
->id3
.elapsed
= newtime
;
1493 newpos
= codec_get_file_pos();
1498 static void codec_seek_complete_callback(void)
1500 logf("seek_complete");
1501 if (pcm_is_paused())
1503 /* If this is not a seamless seek, clear the buffer */
1506 /* If playback was not 'deliberately' paused, unpause now */
1508 pcmbuf_pause(false);
1513 static bool codec_seek_buffer_callback(size_t newpos
)
1517 logf("codec_seek_buffer_callback");
1519 if (newpos
>= CUR_TI
->filesize
)
1520 newpos
= CUR_TI
->filesize
- 1;
1522 difference
= newpos
- ci
.curpos
;
1523 if (difference
>= 0)
1525 /* Seeking forward */
1526 logf("seek: +%d", difference
);
1527 codec_advance_buffer_callback(difference
);
1531 /* Seeking backward */
1532 difference
= -difference
;
1533 if (ci
.curpos
- difference
< 0)
1534 difference
= ci
.curpos
;
1536 /* We need to reload the song. */
1537 if (newpos
< CUR_TI
->start_pos
)
1541 LOGFQUEUE("codec > audio Q_AUDIO_REBUFFER_SEEK");
1542 queue_post(&audio_queue
, Q_AUDIO_REBUFFER_SEEK
, (void *)newpos
);
1544 queue_wait(&codec_callback_queue
, &ev
);
1547 case Q_CODEC_REQUEST_COMPLETE
:
1548 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1551 case Q_CODEC_REQUEST_FAILED
:
1552 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1553 ci
.stop_codec
= true;
1557 LOGFQUEUE("codec < default");
1562 /* Seeking inside buffer space. */
1563 logf("seek: -%d", difference
);
1564 CUR_TI
->available
+= difference
;
1565 buf_ridx
= RINGBUF_SUB(buf_ridx
, (unsigned)difference
);
1566 ci
.curpos
-= difference
;
1571 static void codec_configure_callback(int setting
, void *value
)
1574 case CODEC_SET_FILEBUF_WATERMARK
:
1575 conf_watermark
= (unsigned long)value
;
1576 set_filebuf_watermark(buffer_margin
);
1579 case CODEC_SET_FILEBUF_CHUNKSIZE
:
1580 conf_filechunk
= (unsigned long)value
;
1583 case CODEC_SET_FILEBUF_PRESEEK
:
1584 conf_preseek
= (unsigned long)value
;
1588 if (!dsp_configure(setting
, value
)) { logf("Illegal key:%d", setting
); }
1592 static void codec_track_changed(void)
1594 automatic_skip
= false;
1595 track_changed
= true;
1596 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1597 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1600 static void codec_pcmbuf_track_changed_callback(void)
1602 pcmbuf_set_position_callback(NULL
);
1603 codec_track_changed();
1606 static void codec_discard_codec_callback(void)
1608 if (CUR_TI
->has_codec
)
1610 CUR_TI
->has_codec
= false;
1611 buf_ridx
= RINGBUF_ADD(buf_ridx
, CUR_TI
->codecsize
);
1615 /* Check if a buffer desync has happened, log it and stop playback. */
1616 if (buf_ridx
!= CUR_TI
->buf_idx
)
1618 int offset
= CUR_TI
->buf_idx
- buf_ridx
;
1619 size_t new_used
= FILEBUFUSED
- offset
;
1621 logf("Buf off :%d=%d-%d", offset
, CUR_TI
->buf_idx
, buf_ridx
);
1622 logf("Used off:%d",FILEBUFUSED
- new_used
);
1624 /* This is a fatal internal error and it's not safe to
1625 * continue playback. */
1626 ci
.stop_codec
= true;
1627 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
1632 static void codec_track_skip_done(bool was_manual
)
1634 /* Manual track change (always crossfade or flush audio). */
1637 pcmbuf_crossfade_init(true);
1638 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1639 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1641 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1642 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1643 && global_settings
.crossfade
!= 2)
1645 pcmbuf_crossfade_init(false);
1646 codec_track_changed();
1648 /* Gapless playback. */
1651 pcmbuf_set_position_callback(codec_pcmbuf_position_callback
);
1652 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback
);
1656 static bool codec_load_next_track(void)
1661 codec_seek_complete_callback();
1663 #ifdef AB_REPEAT_ENABLE
1664 ab_end_of_track_report();
1667 logf("Request new track");
1669 if (ci
.new_track
== 0)
1672 automatic_skip
= true;
1675 cpu_boost_id(true, CPUBOOSTID_PLAYBACK_CODEC
);
1676 LOGFQUEUE("codec > audio Q_AUDIO_CHECK_NEW_TRACK");
1677 queue_post(&audio_queue
, Q_AUDIO_CHECK_NEW_TRACK
, 0);
1680 queue_wait(&codec_callback_queue
, &ev
);
1681 if (ev
.id
== Q_CODEC_REQUEST_PENDING
)
1683 if (!automatic_skip
)
1689 cpu_boost_id(false, CPUBOOSTID_PLAYBACK_CODEC
);
1692 case Q_CODEC_REQUEST_COMPLETE
:
1693 LOGFQUEUE("codec < Q_CODEC_REQUEST_COMPLETE");
1694 codec_track_skip_done(!automatic_skip
);
1697 case Q_CODEC_REQUEST_FAILED
:
1698 LOGFQUEUE("codec < Q_CODEC_REQUEST_FAILED");
1700 ci
.stop_codec
= true;
1704 LOGFQUEUE("codec < default");
1705 ci
.stop_codec
= true;
1710 static bool codec_request_next_track_callback(void)
1714 if (ci
.stop_codec
|| !playing
)
1717 prev_codectype
= get_codec_base_type(CUR_TI
->id3
.codectype
);
1719 if (!codec_load_next_track())
1722 /* Check if the next codec is the same file. */
1723 if (prev_codectype
== get_codec_base_type(CUR_TI
->id3
.codectype
))
1725 logf("New track loaded");
1726 codec_discard_codec_callback();
1731 logf("New codec:%d/%d", CUR_TI
->id3
.codectype
, prev_codectype
);
1736 static void codec_thread(void)
1744 queue_wait(&codec_queue
, &ev
);
1747 case Q_CODEC_LOAD_DISK
:
1748 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1749 audio_codec_loaded
= true;
1750 #ifdef PLAYBACK_VOICE
1751 /* Don't sent messages to voice codec if it's not current */
1752 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1754 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1755 queue_post(&voice_queue
, Q_AUDIO_PLAY
, 0);
1758 mutex_lock(&mutex_codecthread
);
1759 current_codec
= CODEC_IDX_AUDIO
;
1760 ci
.stop_codec
= false;
1761 status
= codec_load_file((const char *)ev
.data
, &ci
);
1762 mutex_unlock(&mutex_codecthread
);
1766 LOGFQUEUE("codec < Q_CODEC_LOAD");
1767 if (!CUR_TI
->has_codec
) {
1768 logf("Codec slot is empty!");
1769 /* Wait for the pcm buffer to go empty */
1770 while (pcm_is_playing())
1772 /* This must be set to prevent an infinite loop */
1773 ci
.stop_codec
= true;
1774 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1775 queue_post(&codec_queue
, Q_AUDIO_PLAY
, 0);
1779 audio_codec_loaded
= true;
1780 #ifdef PLAYBACK_VOICE
1781 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1783 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1784 queue_post(&voice_queue
, Q_AUDIO_PLAY
, 0);
1787 mutex_lock(&mutex_codecthread
);
1788 current_codec
= CODEC_IDX_AUDIO
;
1789 ci
.stop_codec
= false;
1790 wrap
= (size_t)&filebuf
[filebuflen
] - (size_t)CUR_TI
->codecbuf
;
1791 status
= codec_load_ram(CUR_TI
->codecbuf
, CUR_TI
->codecsize
,
1792 &filebuf
[0], wrap
, &ci
);
1793 mutex_unlock(&mutex_codecthread
);
1796 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
1797 case Q_ENCODER_LOAD_DISK
:
1798 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1799 audio_codec_loaded
= false; /* Not audio codec! */
1800 #ifdef PLAYBACK_VOICE
1801 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1803 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1804 queue_post(&voice_queue
, Q_ENCODER_RECORD
, NULL
);
1807 mutex_lock(&mutex_codecthread
);
1808 current_codec
= CODEC_IDX_AUDIO
;
1809 ci
.stop_codec
= false;
1810 status
= codec_load_file((const char *)ev
.data
, &ci
);
1811 mutex_unlock(&mutex_codecthread
);
1816 case SYS_USB_CONNECTED
:
1817 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1818 queue_clear(&codec_queue
);
1819 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1820 usb_wait_for_disconnect(&codec_queue
);
1825 LOGFQUEUE("codec < default");
1828 if (audio_codec_loaded
)
1836 audio_codec_loaded
= false;
1840 case Q_CODEC_LOAD_DISK
:
1842 LOGFQUEUE("codec < Q_CODEC_LOAD");
1845 if (ci
.new_track
|| status
!= CODEC_OK
)
1849 logf("Codec failure");
1850 gui_syncsplash(HZ
*2, true, "Codec failure");
1853 if (!codec_load_next_track())
1855 // queue_post(&codec_queue, Q_AUDIO_STOP, 0);
1856 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1857 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
1863 logf("Codec finished");
1866 /* Wait for the audio to stop playing before
1867 * triggering the WPS exit */
1868 while(pcm_is_playing())
1870 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1871 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
1876 if (CUR_TI
->has_codec
)
1878 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
1879 queue_post(&codec_queue
, Q_CODEC_LOAD
, 0);
1883 const char *codec_fn
= get_codec_filename(CUR_TI
->id3
.codectype
);
1884 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1885 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
,
1892 LOGFQUEUE("codec < default");
1899 /* --- Audio thread --- */
1901 static bool audio_filebuf_is_lowdata(void)
1903 return FILEBUFUSED
< AUDIO_FILEBUF_CRITICAL
;
1906 static bool audio_have_tracks(void)
1908 return track_ridx
!= track_widx
|| CUR_TI
->filesize
;
1911 static bool audio_have_free_tracks(void)
1913 if (track_widx
< track_ridx
)
1914 return track_widx
+ 1 < track_ridx
;
1915 else if (track_ridx
== 0)
1916 return track_widx
< MAX_TRACK
- 1;
1921 int audio_track_count(void)
1923 if (audio_have_tracks())
1925 int relative_track_widx
= track_widx
;
1927 if (track_ridx
> track_widx
)
1928 relative_track_widx
+= MAX_TRACK
;
1930 return relative_track_widx
- track_ridx
+ 1;
1936 long audio_filebufused(void)
1938 return (long) FILEBUFUSED
;
1941 /* Count the data BETWEEN the selected tracks */
1942 static size_t audio_buffer_count_tracks(int from_track
, int to_track
)
1945 bool need_wrap
= to_track
< from_track
;
1949 if (++from_track
>= MAX_TRACK
)
1951 from_track
-= MAX_TRACK
;
1955 if (from_track
>= to_track
&& !need_wrap
)
1958 amount
+= tracks
[from_track
].codecsize
+ tracks
[from_track
].filesize
;
1963 static bool audio_buffer_wind_forward(int new_track_ridx
, int old_track_ridx
)
1967 /* Start with the remainder of the previously playing track */
1968 amount
= tracks
[old_track_ridx
].filesize
- ci
.curpos
;
1969 /* Then collect all data from tracks in between them */
1970 amount
+= audio_buffer_count_tracks(old_track_ridx
, new_track_ridx
);
1972 if (amount
> FILEBUFUSED
)
1975 logf("bwf:%ldB",amount
);
1977 /* Wind the buffer to the beginning of the target track or its codec */
1978 buf_ridx
= RINGBUF_ADD(buf_ridx
, amount
);
1983 static bool audio_buffer_wind_backward(int new_track_ridx
, int old_track_ridx
)
1985 /* Available buffer data */
1987 /* Start with the previously playing track's data and our data */
1991 buf_back
= RINGBUF_SUB(buf_ridx
, buf_widx
);
1993 /* If we're not just resetting the current track */
1994 if (new_track_ridx
!= old_track_ridx
)
1996 /* Need to wind to before the old track's codec and our filesize */
1997 amount
+= tracks
[old_track_ridx
].codecsize
;
1998 amount
+= tracks
[new_track_ridx
].filesize
;
2000 /* Rewind the old track to its beginning */
2001 tracks
[old_track_ridx
].available
=
2002 tracks
[old_track_ridx
].filesize
- tracks
[old_track_ridx
].filerem
;
2005 /* If the codec was ever buffered */
2006 if (tracks
[new_track_ridx
].codecsize
)
2008 /* Add the codec to the needed size */
2009 amount
+= tracks
[new_track_ridx
].codecsize
;
2010 tracks
[new_track_ridx
].has_codec
= true;
2013 /* Then collect all data from tracks between new and old */
2014 amount
+= audio_buffer_count_tracks(new_track_ridx
, old_track_ridx
);
2016 /* Do we have space to make this skip? */
2017 if (amount
> buf_back
)
2020 logf("bwb:%ldB",amount
);
2022 /* Rewind the buffer to the beginning of the target track or its codec */
2023 buf_ridx
= RINGBUF_SUB(buf_ridx
, amount
);
2025 /* Reset to the beginning of the new track */
2026 tracks
[new_track_ridx
].available
= tracks
[new_track_ridx
].filesize
;
2031 static void audio_update_trackinfo(void)
2033 ci
.filesize
= CUR_TI
->filesize
;
2034 CUR_TI
->id3
.elapsed
= 0;
2035 CUR_TI
->id3
.offset
= 0;
2036 ci
.id3
= &CUR_TI
->id3
;
2038 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
2041 /* Yield to codecs for as long as possible if they are in need of data
2042 * return true if the caller should break to let the audio thread process
2044 static bool audio_yield_codecs(void)
2048 if (!queue_empty(&audio_queue
))
2051 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
2052 && !ci
.stop_codec
&& playing
&& !audio_filebuf_is_lowdata())
2055 if (!queue_empty(&audio_queue
))
2062 /* Note that this function might yield(). */
2063 static void audio_clear_track_entries(
2064 bool clear_buffered
, bool clear_unbuffered
,
2067 int cur_idx
= track_widx
;
2070 logf("Clearing tracks:%d/%d, %d", track_ridx
, track_widx
, clear_unbuffered
);
2072 /* Loop over all tracks from write-to-read */
2076 cur_idx
&= MAX_TRACK_MASK
;
2078 if (cur_idx
== track_ridx
)
2081 /* If the track is buffered, conditionally clear/notify,
2082 * otherwise clear the track if that option is selected */
2083 if (tracks
[cur_idx
].event_sent
)
2089 /* If there is an unbuffer callback, call it, otherwise,
2090 * just clear the track */
2091 if (track_unbuffer_callback
)
2094 audio_yield_codecs();
2095 track_unbuffer_callback(&tracks
[last_idx
].id3
, false);
2098 memset(&tracks
[last_idx
], 0, sizeof(struct track_info
));
2103 else if (clear_unbuffered
)
2104 memset(&tracks
[cur_idx
], 0, sizeof(struct track_info
));
2107 /* We clear the previous instance of a buffered track throughout
2108 * the above loop to facilitate 'last' detection. Clear/notify
2109 * the last track here */
2112 if (track_unbuffer_callback
)
2113 track_unbuffer_callback(&tracks
[last_idx
].id3
, true);
2114 memset(&tracks
[last_idx
], 0, sizeof(struct track_info
));
2118 /* FIXME: This code should be made more generic and move to metadata.c */
2119 static void audio_strip_id3v1_tag(void)
2122 static const unsigned char tag
[] = "TAG";
2126 tag_idx
= RINGBUF_SUB(buf_widx
, 128);
2128 if (FILEBUFUSED
> 128 && tag_idx
> buf_ridx
)
2131 for(i
= 0;i
< 3;i
++)
2133 if(filebuf
[cur_idx
] != tag
[i
])
2136 cur_idx
= RINGBUF_ADD(cur_idx
, 1);
2139 /* Skip id3v1 tag */
2140 logf("Skipping ID3v1 tag");
2142 tracks
[track_widx
].available
-= 128;
2143 tracks
[track_widx
].filesize
-= 128;
2147 static void audio_read_file(bool quick
)
2152 /* If we're called and no file is open, this is an error */
2155 logf("Bad fd in arf");
2156 /* Stop this buffer cycle immediately */
2158 /* Give some hope of miraculous recovery by forcing a track reload */
2159 tracks
[track_widx
].filesize
= 0;
2163 cpu_boost_id(true, CPUBOOSTID_PLAYBACK_AUDIO
);
2164 while (tracks
[track_widx
].filerem
> 0)
2168 if (fill_bytesleft
== 0)
2171 /* copy_n is the largest chunk that is safe to read */
2172 copy_n
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
2173 copy_n
= MIN(copy_n
, fill_bytesleft
);
2175 /* rc is the actual amount read */
2176 rc
= read(current_fd
, &filebuf
[buf_widx
], copy_n
);
2180 /* Reached the end of the file */
2181 tracks
[track_widx
].filerem
= 0;
2185 overlap
= buf_widx
+ rc
- CUR_TI
->buf_idx
;
2186 buf_widx
= RINGBUF_ADD(buf_widx
, rc
);
2188 if (overlap
> 0 && (unsigned) overlap
>= filebuflen
)
2189 overlap
-= filebuflen
;
2191 if (overlap
> 0 && overlap
<= rc
&& CUR_TI
->available
!= 0) {
2192 CUR_TI
->buf_idx
= buf_widx
;
2193 CUR_TI
->start_pos
+= overlap
;
2196 tracks
[track_widx
].available
+= rc
;
2197 tracks
[track_widx
].filerem
-= rc
;
2199 if (fill_bytesleft
> (unsigned)rc
)
2200 fill_bytesleft
-= rc
;
2204 /* Let the codec process until it is out of the danger zone, or there
2205 * is an event to handle. In the latter case, break this fill cycle
2207 if (quick
|| audio_yield_codecs())
2211 if (tracks
[track_widx
].filerem
== 0)
2213 logf("Finished buf:%dB", tracks
[track_widx
].filesize
);
2216 audio_strip_id3v1_tag();
2219 track_widx
&= MAX_TRACK_MASK
;
2221 tracks
[track_widx
].filesize
= 0;
2225 logf("Partially buf:%dB",
2226 tracks
[track_widx
].filesize
- tracks
[track_widx
].filerem
);
2228 cpu_boost_id(false, CPUBOOSTID_PLAYBACK_AUDIO
);
2231 static bool audio_loadcodec(bool start_play
)
2238 char codec_path
[MAX_PATH
]; /* Full path to codec */
2240 const char * codec_fn
= get_codec_filename(tracks
[track_widx
].id3
.codectype
);
2241 if (codec_fn
== NULL
)
2244 tracks
[track_widx
].has_codec
= false;
2245 tracks
[track_widx
].codecsize
= 0;
2249 /* Load the codec directly from disk and save some memory. */
2250 track_ridx
= track_widx
;
2251 ci
.filesize
= CUR_TI
->filesize
;
2252 ci
.id3
= &CUR_TI
->id3
;
2253 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
2255 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2256 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
, (void *)codec_fn
);
2261 /* If we already have another track than this one buffered */
2262 if (track_widx
!= track_ridx
)
2264 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
2266 /* If the previous codec is the same as this one, there is no need
2267 * to put another copy of it on the file buffer */
2268 if (get_codec_base_type(tracks
[track_widx
].id3
.codectype
) ==
2269 get_codec_base_type(tracks
[prev_track
].id3
.codectype
)
2270 && audio_codec_loaded
)
2272 logf("Reusing prev. codec");
2278 codec_get_full_path(codec_path
, codec_fn
);
2280 fd
= open(codec_path
, O_RDONLY
);
2283 logf("Codec doesn't exist!");
2287 size
= filesize(fd
);
2289 /* Never load a partial codec */
2290 if (fill_bytesleft
< size
)
2292 logf("Not enough space");
2298 while (tracks
[track_widx
].codecsize
< size
)
2300 copy_n
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
2301 rc
= read(fd
, &filebuf
[buf_widx
], copy_n
);
2308 if (fill_bytesleft
> (unsigned)rc
)
2309 fill_bytesleft
-= rc
;
2313 buf_widx
= RINGBUF_ADD(buf_widx
, rc
);
2315 tracks
[track_widx
].codecsize
+= rc
;
2318 tracks
[track_widx
].has_codec
= true;
2321 logf("Done: %dB", size
);
2326 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2327 static void audio_set_elapsed(struct mp3entry
* id3
)
2330 if ( id3
->has_toc
) {
2331 /* calculate elapsed time using TOC */
2333 unsigned int remainder
, plen
, relpos
, nextpos
;
2335 /* find wich percent we're at */
2336 for (i
=0; i
<100; i
++ )
2337 if ( id3
->offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
2344 relpos
= id3
->toc
[i
];
2347 nextpos
= id3
->toc
[i
+1];
2351 remainder
= id3
->offset
- (relpos
* (id3
->filesize
/ 256));
2353 /* set time for this percent (divide before multiply to prevent
2354 overflow on long files. loss of precision is negligible on
2356 id3
->elapsed
= i
* (id3
->length
/ 100);
2358 /* calculate remainder time */
2359 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
2360 id3
->elapsed
+= (((remainder
* 100) / plen
) *
2361 (id3
->length
/ 10000));
2364 /* no TOC exists. set a rough estimate using average bitrate */
2365 int tpk
= id3
->length
/ (id3
->filesize
/ 1024);
2366 id3
->elapsed
= id3
->offset
/ 1024 * tpk
;
2371 /* constant bitrate, use exact calculation */
2372 if (id3
->bitrate
!= 0)
2373 id3
->elapsed
= id3
->offset
/ (id3
->bitrate
/ 8);
2377 static bool audio_load_track(int offset
, bool start_play
, bool rebuffer
)
2383 /* Stop buffer filling if there is no free track entries.
2384 Don't fill up the last track entry (we wan't to store next track
2386 if (!audio_have_free_tracks())
2388 logf("No free tracks");
2392 if (current_fd
>= 0)
2394 logf("Nonzero fd in alt");
2401 logf("Buffering track:%d/%d", track_widx
, track_ridx
);
2402 /* Get track name from current playlist read position. */
2403 while ((trackname
= playlist_peek(last_peek_offset
)) != NULL
)
2405 /* Handle broken playlists. */
2406 current_fd
= open(trackname
, O_RDONLY
);
2409 logf("Open failed");
2410 /* Skip invalid entry from playlist. */
2411 playlist_skip_entry(NULL
, last_peek_offset
);
2419 logf("End-of-playlist");
2420 playlist_end
= true;
2424 /* Initialize track entry. */
2425 size
= filesize(current_fd
);
2426 tracks
[track_widx
].filerem
= size
;
2427 tracks
[track_widx
].filesize
= size
;
2428 tracks
[track_widx
].available
= 0;
2430 /* Set default values */
2433 int last_codec
= current_codec
;
2435 current_codec
= CODEC_IDX_AUDIO
;
2436 conf_watermark
= AUDIO_DEFAULT_WATERMARK
;
2437 conf_filechunk
= AUDIO_DEFAULT_FILECHUNK
;
2438 conf_preseek
= AUDIO_REBUFFER_GUESS_SIZE
;
2439 dsp_configure(DSP_RESET
, 0);
2440 current_codec
= last_codec
;
2443 /* Get track metadata if we don't already have it. */
2444 if (!tracks
[track_widx
].taginfo_ready
)
2446 if (get_metadata(&tracks
[track_widx
],current_fd
,trackname
,v1first
))
2450 track_changed
= true;
2451 playlist_update_resume_info(audio_current_track());
2456 logf("mde:%s!",trackname
);
2458 /* Set filesize to zero to indicate no file was loaded. */
2459 tracks
[track_widx
].filesize
= 0;
2460 tracks
[track_widx
].filerem
= 0;
2464 /* Skip invalid entry from playlist. */
2465 playlist_skip_entry(NULL
, last_peek_offset
);
2466 tracks
[track_widx
].taginfo_ready
= false;
2472 /* Load the codec. */
2473 tracks
[track_widx
].codecbuf
= &filebuf
[buf_widx
];
2474 if (!audio_loadcodec(start_play
))
2476 if (tracks
[track_widx
].codecsize
)
2478 /* Must undo the buffer write of the partial codec */
2479 logf("Partial codec loaded");
2480 fill_bytesleft
+= tracks
[track_widx
].codecsize
;
2481 buf_widx
= RINGBUF_SUB(buf_widx
, tracks
[track_widx
].codecsize
);
2482 tracks
[track_widx
].codecsize
= 0;
2485 /* Set filesize to zero to indicate no file was loaded. */
2486 tracks
[track_widx
].filesize
= 0;
2487 tracks
[track_widx
].filerem
= 0;
2491 /* Try skipping to next track if there is space. */
2492 if (fill_bytesleft
> 0)
2494 /* This is an error condition unless the fill_bytesleft is 0 */
2495 snprintf(msgbuf
, sizeof(msgbuf
)-1, "No codec for: %s", trackname
);
2496 /* We should not use gui_syncplash from audio thread! */
2497 gui_syncsplash(HZ
*2, true, msgbuf
);
2498 /* Skip invalid entry from playlist. */
2499 playlist_skip_entry(NULL
, last_peek_offset
);
2500 tracks
[track_widx
].taginfo_ready
= false;
2507 tracks
[track_widx
].start_pos
= 0;
2508 set_filebuf_watermark(buffer_margin
);
2509 tracks
[track_widx
].id3
.elapsed
= 0;
2513 switch (tracks
[track_widx
].id3
.codectype
) {
2517 lseek(current_fd
, offset
, SEEK_SET
);
2518 tracks
[track_widx
].id3
.offset
= offset
;
2519 audio_set_elapsed(&tracks
[track_widx
].id3
);
2520 tracks
[track_widx
].filerem
= size
- offset
;
2522 tracks
[track_widx
].start_pos
= offset
;
2526 lseek(current_fd
, offset
, SEEK_SET
);
2527 tracks
[track_widx
].id3
.offset
= offset
;
2528 tracks
[track_widx
].id3
.elapsed
=
2529 tracks
[track_widx
].id3
.length
/ 2;
2530 tracks
[track_widx
].filerem
= size
- offset
;
2532 tracks
[track_widx
].start_pos
= offset
;
2535 case AFMT_OGG_VORBIS
:
2540 tracks
[track_widx
].id3
.offset
= offset
;
2546 logf("alt:%s", trackname
);
2547 tracks
[track_widx
].buf_idx
= buf_widx
;
2549 audio_read_file(rebuffer
);
2554 static bool audio_read_next_metadata(void)
2561 next_idx
= track_widx
;
2562 if (tracks
[next_idx
].taginfo_ready
)
2565 next_idx
&= MAX_TRACK_MASK
;
2567 if (tracks
[next_idx
].taginfo_ready
)
2571 trackname
= playlist_peek(last_peek_offset
+ 1);
2575 fd
= open(trackname
, O_RDONLY
);
2579 status
= get_metadata(&tracks
[next_idx
],fd
,trackname
,v1first
);
2580 /* Preload the glyphs in the tags */
2583 if (tracks
[next_idx
].id3
.title
)
2584 lcd_getstringsize(tracks
[next_idx
].id3
.title
, NULL
, NULL
);
2585 if (tracks
[next_idx
].id3
.artist
)
2586 lcd_getstringsize(tracks
[next_idx
].id3
.artist
, NULL
, NULL
);
2587 if (tracks
[next_idx
].id3
.album
)
2588 lcd_getstringsize(tracks
[next_idx
].id3
.album
, NULL
, NULL
);
2595 /* Send callback events to notify about new tracks. */
2596 static void audio_generate_postbuffer_events(void)
2601 logf("Postbuffer:%d/%d",track_ridx
,track_widx
);
2603 if (audio_have_tracks())
2605 cur_idx
= track_ridx
;
2608 if (!tracks
[cur_idx
].event_sent
)
2610 if (last_idx
>= 0 && !tracks
[last_idx
].event_sent
)
2612 /* Mark the event 'sent' even if we don't really send one */
2613 tracks
[last_idx
].event_sent
= true;
2614 if (track_buffer_callback
)
2615 track_buffer_callback(&tracks
[last_idx
].id3
, false);
2619 if (cur_idx
== track_widx
)
2622 cur_idx
&= MAX_TRACK_MASK
;
2625 if (last_idx
>= 0 && !tracks
[last_idx
].event_sent
)
2627 tracks
[last_idx
].event_sent
= true;
2628 if (track_buffer_callback
)
2629 track_buffer_callback(&tracks
[last_idx
].id3
, true);
2632 /* Force WPS reload. */
2633 track_changed
= true;
2637 static bool audio_initialize_buffer_fill(bool clear_tracks
)
2639 /* Don't initialize if we're already initialized */
2643 /* Don't start buffer fill if buffer is already full. */
2644 if (FILEBUFUSED
> conf_watermark
&& !filling
)
2647 logf("Starting buffer fill");
2649 fill_bytesleft
= filebuflen
- FILEBUFUSED
;
2650 /* TODO: This doesn't look right, and might explain some problems with
2651 * seeking in large files (to offsets larger than filebuflen).
2652 * And what about buffer wraps?
2654 * This really doesn't look right, so don't use it.
2656 // if (buf_ridx > CUR_TI->buf_idx)
2657 // CUR_TI->start_pos = buf_ridx - CUR_TI->buf_idx;
2659 /* Set the filling flag true before calling audio_clear_tracks as that
2660 * function can yield and we start looping. */
2664 audio_clear_track_entries(true, false, true);
2666 /* Save the current resume position once. */
2667 playlist_update_resume_info(audio_current_track());
2672 static void audio_fill_file_buffer(
2673 bool start_play
, bool rebuffer
, size_t offset
)
2675 bool had_next_track
= audio_next_track() != NULL
;
2677 if (!audio_initialize_buffer_fill(!start_play
))
2680 /* If we have a partially buffered track, continue loading,
2681 * otherwise load a new track */
2682 if (tracks
[track_widx
].filesize
> 0)
2683 audio_read_file(false);
2684 else if (!audio_load_track(offset
, start_play
, rebuffer
))
2687 if (!had_next_track
&& audio_next_track())
2688 track_changed
= true;
2690 /* If we're done buffering */
2691 if (fill_bytesleft
== 0)
2693 audio_read_next_metadata();
2695 audio_generate_postbuffer_events();
2705 static void audio_rebuffer(void)
2707 logf("Forcing rebuffer");
2709 /* Notify the codec that this will take a while */
2710 /* Currently this can cause some problems (logf in reverse order):
2711 * Codec load error:-1
2713 * Codec: Unsupported
2716 * Clearing tracks:7/7, 1
2718 * Check new track buffer
2720 * Clearing tracks:5/5, 0
2721 * Starting buffer fill
2722 * Clearing tracks:5/5, 1
2723 * Re-buffering song w/seek
2726 // queue_post(&codec_callback_queue, Q_CODEC_REQUEST_PENDING, 0);
2728 /* Stop in progress fill, and clear open file descriptor */
2729 if (current_fd
>= 0)
2736 /* Reset buffer and track pointers */
2737 CUR_TI
->buf_idx
= buf_ridx
= buf_widx
= 0;
2738 track_widx
= track_ridx
;
2739 audio_clear_track_entries(true, true, false);
2740 CUR_TI
->available
= 0;
2742 /* Fill the buffer */
2743 last_peek_offset
= -1;
2744 CUR_TI
->filesize
= 0;
2745 CUR_TI
->start_pos
= 0;
2748 if (!CUR_TI
->taginfo_ready
)
2749 memset(&CUR_TI
->id3
, 0, sizeof(struct mp3entry
));
2751 audio_fill_file_buffer(false, true, 0);
2754 static void audio_check_new_track(void)
2756 int track_count
= audio_track_count();
2757 int old_track_ridx
= track_ridx
;
2763 if (playlist_next_dir(ci
.new_track
))
2766 CUR_TI
->taginfo_ready
= false;
2772 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2773 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_FAILED
, 0);
2781 /* If the playlist isn't that big */
2782 if (!playlist_check(ci
.new_track
))
2784 if (ci
.new_track
>= 0)
2786 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2787 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_FAILED
, 0);
2790 /* Find the beginning backward if the user over-skips it */
2791 while (!playlist_check(++ci
.new_track
))
2792 if (ci
.new_track
>= 0)
2794 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2795 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_FAILED
, 0);
2799 /* Update the playlist */
2800 last_peek_offset
-= ci
.new_track
;
2802 if (playlist_next(ci
.new_track
) < 0)
2804 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2805 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_FAILED
, 0);
2812 new_playlist
= false;
2815 /* Save the old track */
2818 /* Move to the new track */
2819 track_ridx
+= ci
.new_track
;
2820 track_ridx
&= MAX_TRACK_MASK
;
2823 playlist_end
= false;
2825 track_changed
= !automatic_skip
;
2827 /* If it is not safe to even skip this many track entries */
2828 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
2831 CUR_TI
->taginfo_ready
= false;
2836 forward
= ci
.new_track
> 0;
2839 /* If the target track is clearly not in memory */
2840 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
2846 /* The track may be in memory, see if it really is */
2849 if (!audio_buffer_wind_forward(track_ridx
, old_track_ridx
))
2854 int cur_idx
= track_ridx
;
2855 bool taginfo_ready
= true;
2856 bool wrap
= track_ridx
> old_track_ridx
;
2861 cur_idx
&= MAX_TRACK_MASK
;
2862 if (!(wrap
|| cur_idx
< old_track_ridx
))
2865 /* If we hit a track in between without valid tag info, bail */
2866 if (!tracks
[cur_idx
].taginfo_ready
)
2868 taginfo_ready
= false;
2872 tracks
[cur_idx
].available
= tracks
[cur_idx
].filesize
;
2873 if (tracks
[cur_idx
].codecsize
)
2874 tracks
[cur_idx
].has_codec
= true;
2878 if (!audio_buffer_wind_backward(track_ridx
, old_track_ridx
))
2883 CUR_TI
->taginfo_ready
= false;
2889 audio_update_trackinfo();
2890 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE");
2891 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_COMPLETE
, 0);
2894 static void audio_rebuffer_and_seek(size_t newpos
)
2899 trackname
= playlist_peek(0);
2900 /* (Re-)open current track's file handle. */
2902 fd
= open(trackname
, O_RDONLY
);
2905 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_FAILED");
2906 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_FAILED
, 0);
2910 if (current_fd
>= 0)
2914 playlist_end
= false;
2918 /* Clear codec buffer. */
2919 track_widx
= track_ridx
;
2920 tracks
[track_widx
].buf_idx
= buf_widx
= buf_ridx
= 0;
2922 last_peek_offset
= 0;
2924 audio_initialize_buffer_fill(true);
2927 if (newpos
> conf_preseek
) {
2928 buf_ridx
= RINGBUF_ADD(buf_ridx
, conf_preseek
);
2929 CUR_TI
->start_pos
= newpos
- conf_preseek
;
2933 buf_ridx
= RINGBUF_ADD(buf_ridx
, newpos
);
2934 CUR_TI
->start_pos
= 0;
2937 CUR_TI
->filerem
= CUR_TI
->filesize
- CUR_TI
->start_pos
;
2938 CUR_TI
->available
= 0;
2940 lseek(current_fd
, CUR_TI
->start_pos
, SEEK_SET
);
2942 LOGFQUEUE("audio > codec Q_CODEC_REQUEST_COMPLETE");
2943 queue_post(&codec_callback_queue
, Q_CODEC_REQUEST_COMPLETE
, 0);
2946 void audio_set_track_buffer_event(void (*handler
)(struct mp3entry
*id3
,
2949 track_buffer_callback
= handler
;
2952 void audio_set_track_unbuffer_event(void (*handler
)(struct mp3entry
*id3
,
2955 track_unbuffer_callback
= handler
;
2958 void audio_set_track_changed_event(void (*handler
)(struct mp3entry
*id3
))
2960 track_changed_callback
= handler
;
2963 static void audio_stop_codec_flush(void)
2965 ci
.stop_codec
= true;
2967 while (audio_codec_loaded
)
2969 /* If the audio codec is not loaded any more, and the audio is still
2970 * playing, it is now and _only_ now safe to call this function from the
2972 if (pcm_is_playing())
2974 pcmbuf_pause(paused
);
2977 static void audio_stop_playback(void)
2979 /* If we were playing, save resume information */
2982 /* Save the current playing spot, or NULL if the playlist has ended */
2983 playlist_update_resume_info(
2984 (playlist_end
&& ci
.stop_codec
)?NULL
:audio_current_track());
2990 audio_stop_codec_flush();
2992 if (current_fd
>= 0)
2998 /* Mark all entries null. */
2999 audio_clear_track_entries(true, false, false);
3000 memset(tracks
, 0, sizeof(struct track_info
) * MAX_TRACK
);
3003 static void audio_play_start(size_t offset
)
3005 #if defined(HAVE_RECORDING) || defined(CONFIG_TUNER)
3006 rec_set_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
3009 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
3010 audio_stop_codec_flush();
3012 track_changed
= true;
3013 playlist_end
= false;
3020 if (current_fd
>= 0)
3026 sound_set_volume(global_settings
.volume
);
3027 track_widx
= track_ridx
= 0;
3028 buf_ridx
= buf_widx
= 0;
3030 /* Mark all entries null. */
3031 memset(tracks
, 0, sizeof(struct track_info
) * MAX_TRACK
);
3033 last_peek_offset
= -1;
3035 audio_fill_file_buffer(true, false, offset
);
3039 /* Invalidates all but currently playing track. */
3040 void audio_invalidate_tracks(void)
3042 if (audio_have_tracks()) {
3043 last_peek_offset
= 0;
3045 playlist_end
= false;
3046 track_widx
= track_ridx
;
3047 audio_clear_track_entries(true, true, true);
3049 /* If the current track is fully buffered, advance the write pointer */
3050 if (tracks
[track_widx
].filerem
== 0)
3051 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
3053 /* Mark all other entries null (also buffered wrong metadata). */
3054 buf_widx
= RINGBUF_ADD(buf_ridx
, CUR_TI
->available
);
3056 audio_read_next_metadata();
3060 static void audio_new_playlist(void)
3062 /* Prepare to start a new fill from the beginning of the playlist */
3063 last_peek_offset
= -1;
3064 if (audio_have_tracks()) {
3065 playlist_end
= false;
3066 track_widx
= track_ridx
;
3067 audio_clear_track_entries(true, true, true);
3070 track_widx
&= MAX_TRACK_MASK
;
3072 /* Stop reading the current track */
3073 CUR_TI
->filerem
= 0;
3077 /* Mark the current track as invalid to prevent skipping back to it */
3078 CUR_TI
->taginfo_ready
= false;
3080 /* Invalidate the buffer other than the playing track */
3081 buf_widx
= RINGBUF_ADD(buf_ridx
, CUR_TI
->available
);
3084 /* Signal the codec to initiate a track change forward */
3085 new_playlist
= true;
3087 audio_fill_file_buffer(false, true, 0);
3090 static void audio_initiate_track_change(long direction
)
3092 playlist_end
= false;
3093 ci
.new_track
+= direction
;
3094 wps_offset
-= direction
;
3097 static void audio_initiate_dir_change(long direction
)
3099 playlist_end
= false;
3101 ci
.new_track
= direction
;
3104 static void audio_reset_buffer(void)
3108 /* Set up file buffer as all space available */
3109 filebuf
= (char *)&audiobuf
[talk_get_bufsize()+MALLOC_BUFSIZE
];
3110 filebuflen
= audiobufend
- (unsigned char *) filebuf
- GUARD_BUFSIZE
-
3111 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_MIX_CHUNK
* 2);
3113 /* Allow for codec(s) at end of file buffer */
3114 if (talk_voice_required())
3116 /* Allow 2 codecs at end of file buffer */
3117 filebuflen
-= 2 * (CODEC_IRAM_SIZE
+ CODEC_SIZE
);
3119 iram_buf
[0] = &filebuf
[filebuflen
];
3120 iram_buf
[1] = &filebuf
[filebuflen
+CODEC_IRAM_SIZE
];
3121 dram_buf
[0] = (unsigned char *)&filebuf
[filebuflen
+CODEC_IRAM_SIZE
*2];
3122 dram_buf
[1] = (unsigned char *)&filebuf
[filebuflen
+CODEC_IRAM_SIZE
*2+CODEC_SIZE
];
3126 /* Allow for 1 codec at end of file buffer */
3127 filebuflen
-= CODEC_IRAM_SIZE
+ CODEC_SIZE
;
3129 iram_buf
[0] = &filebuf
[filebuflen
];
3131 dram_buf
[0] = (unsigned char *)&filebuf
[filebuflen
+CODEC_IRAM_SIZE
];
3135 /* Ensure that file buffer is aligned */
3136 offset
= (-(size_t)filebuf
) & 3;
3138 filebuflen
-= offset
;
3143 #ifdef ROCKBOX_HAS_LOGF
3144 static void audio_test_track_changed_event(struct mp3entry
*id3
)
3148 logf("tce:%s", id3
->path
);
3152 static void audio_playback_init(void)
3154 #ifdef PLAYBACK_VOICE
3155 static bool voicetagtrue
= true;
3156 static struct mp3entry id3_voice
;
3160 logf("playback api init");
3163 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
3164 /* Set the input multiplexer to Line In */
3168 #ifdef ROCKBOX_HAS_LOGF
3169 audio_set_track_changed_event(audio_test_track_changed_event
);
3172 /* Initialize codec api. */
3173 ci
.read_filebuf
= codec_filebuf_callback
;
3174 ci
.pcmbuf_insert
= codec_pcmbuf_insert_callback
;
3175 ci
.pcmbuf_insert_split
= codec_pcmbuf_insert_split_callback
;
3176 ci
.get_codec_memory
= codec_get_memory_callback
;
3177 ci
.request_buffer
= codec_request_buffer_callback
;
3178 ci
.advance_buffer
= codec_advance_buffer_callback
;
3179 ci
.advance_buffer_loc
= codec_advance_buffer_loc_callback
;
3180 ci
.request_next_track
= codec_request_next_track_callback
;
3181 ci
.mp3_get_filepos
= codec_mp3_get_filepos_callback
;
3182 ci
.seek_buffer
= codec_seek_buffer_callback
;
3183 ci
.seek_complete
= codec_seek_complete_callback
;
3184 ci
.set_elapsed
= codec_set_elapsed_callback
;
3185 ci
.set_offset
= codec_set_offset_callback
;
3186 ci
.configure
= codec_configure_callback
;
3187 ci
.discard_codec
= codec_discard_codec_callback
;
3189 /* Initialize voice codec api. */
3190 #ifdef PLAYBACK_VOICE
3191 memcpy(&ci_voice
, &ci
, sizeof(struct codec_api
));
3192 memset(&id3_voice
, 0, sizeof(struct mp3entry
));
3193 ci_voice
.read_filebuf
= voice_filebuf_callback
;
3194 ci_voice
.pcmbuf_insert
= voice_pcmbuf_insert_callback
;
3195 ci_voice
.pcmbuf_insert_split
= voice_pcmbuf_insert_split_callback
;
3196 ci_voice
.get_codec_memory
= voice_get_memory_callback
;
3197 ci_voice
.request_buffer
= voice_request_buffer_callback
;
3198 ci_voice
.advance_buffer
= voice_advance_buffer_callback
;
3199 ci_voice
.advance_buffer_loc
= voice_advance_buffer_loc_callback
;
3200 ci_voice
.request_next_track
= voice_request_next_track_callback
;
3201 ci_voice
.mp3_get_filepos
= voice_mp3_get_filepos_callback
;
3202 ci_voice
.seek_buffer
= voice_seek_buffer_callback
;
3203 ci_voice
.seek_complete
= voice_do_nothing
;
3204 ci_voice
.set_elapsed
= voice_set_elapsed_callback
;
3205 ci_voice
.set_offset
= voice_set_offset_callback
;
3206 ci_voice
.discard_codec
= voice_do_nothing
;
3207 ci_voice
.taginfo_ready
= &voicetagtrue
;
3208 ci_voice
.id3
= &id3_voice
;
3209 id3_voice
.frequency
= 11200;
3210 id3_voice
.length
= 1000000L;
3213 codec_thread_p
= create_thread(codec_thread
, codec_stack
,
3214 sizeof(codec_stack
),
3215 codec_thread_name
IF_PRIO(, PRIORITY_PLAYBACK
));
3219 queue_wait(&audio_queue
, &ev
);
3220 if (ev
.id
== Q_AUDIO_POSTINIT
)
3224 if (ev
.id
== SYS_USB_CONNECTED
)
3226 logf("USB: Audio preinit");
3227 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3228 usb_wait_for_disconnect(&audio_queue
);
3233 filebuf
= (char *)&audiobuf
[MALLOC_BUFSIZE
]; /* Will be reset by reset_buffer */
3235 audio_set_crossfade(global_settings
.crossfade
);
3237 audio_is_initialized
= true;
3239 sound_settings_apply();
3242 static void audio_thread(void)
3246 /* At first initialize audio system in background. */
3247 audio_playback_init();
3253 queue_wait_w_tmo(&audio_queue
, &ev
, 0);
3254 if (ev
.id
== SYS_TIMEOUT
)
3255 ev
.id
= Q_AUDIO_FILL_BUFFER
;
3258 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
3261 case Q_AUDIO_FILL_BUFFER
:
3262 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3264 if (!playing
|| playlist_end
|| ci
.stop_codec
)
3266 audio_fill_file_buffer(false, false, 0);
3270 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3271 audio_clear_track_entries(true, false, true);
3272 audio_play_start((size_t)ev
.data
);
3276 LOGFQUEUE("audio < Q_AUDIO_STOP");
3277 audio_stop_playback();
3281 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3282 pcmbuf_pause((bool)ev
.data
);
3283 paused
= (bool)ev
.data
;
3287 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3288 audio_initiate_track_change((long)ev
.data
);
3291 case Q_AUDIO_PRE_FF_REWIND
:
3292 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3298 case Q_AUDIO_FF_REWIND
:
3299 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3302 ci
.seek_time
= (long)ev
.data
+1;
3305 case Q_AUDIO_REBUFFER_SEEK
:
3306 LOGFQUEUE("audio < Q_AUDIO_REBUFFER_SEEK");
3307 audio_rebuffer_and_seek((size_t)ev
.data
);
3310 case Q_AUDIO_CHECK_NEW_TRACK
:
3311 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3312 audio_check_new_track();
3315 case Q_AUDIO_DIR_SKIP
:
3316 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3317 playlist_end
= false;
3318 audio_initiate_dir_change((long)ev
.data
);
3321 case Q_AUDIO_NEW_PLAYLIST
:
3322 LOGFQUEUE("audio < Q_AUDIO_NEW_PLAYLIST");
3323 audio_new_playlist();
3327 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3328 audio_invalidate_tracks();
3331 case Q_AUDIO_TRACK_CHANGED
:
3332 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3333 if (track_changed_callback
)
3334 track_changed_callback(&CUR_TI
->id3
);
3335 track_changed
= true;
3336 playlist_update_resume_info(audio_current_track());
3340 case SYS_USB_CONNECTED
:
3341 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3342 audio_stop_playback();
3343 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3344 usb_wait_for_disconnect(&audio_queue
);
3349 LOGFQUEUE("audio < SYS_TIMEOUT");
3353 LOGFQUEUE("audio < default");