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: Can use the track changed callback to detect end of track and seek
21 * in the previous track until this happens */
22 /* Design: we have prev_ti already, have a conditional for what type of seek
23 * to do on a seek request, if it is a previous track seek, skip previous,
24 * and in the request_next_track callback set the offset up the same way that
25 * starting from an offset works. */
26 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
27 * play whilst audio is paused */
49 #include "buffering.h"
50 #include "mp3_playback.h"
65 #ifdef HAVE_LCD_BITMAP
67 #include "peakmeter.h"
77 #include "ata_idle_notify.h"
80 #include "recording.h"
85 #include "menus/eq_menu.h"
88 #define PLAYBACK_VOICE
91 /* Define LOGF_ENABLE to enable logf output in this file */
92 /*#define LOGF_ENABLE*/
95 /* macros to enable logf for queues
96 logging on SYS_TIMEOUT can be disabled */
98 /* Define this for logf output of all queuing except SYS_TIMEOUT */
99 #define PLAYBACK_LOGQUEUES
100 /* Define this to logf SYS_TIMEOUT messages */
101 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
104 #ifdef PLAYBACK_LOGQUEUES
105 #define LOGFQUEUE logf
107 #define LOGFQUEUE(...)
110 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
111 #define LOGFQUEUE_SYS_TIMEOUT logf
113 #define LOGFQUEUE_SYS_TIMEOUT(...)
117 /* Define one constant that includes recording related functionality */
118 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
119 #define AUDIO_HAVE_RECORDING
127 Q_AUDIO_PRE_FF_REWIND
,
129 /* Q_AUDIO_REBUFFER_SEEK, */
130 Q_AUDIO_CHECK_NEW_TRACK
,
132 Q_AUDIO_TRACK_CHANGED
,
137 Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA
,
139 Q_CODEC_REQUEST_COMPLETE
,
140 Q_CODEC_REQUEST_FAILED
,
148 #ifdef AUDIO_HAVE_RECORDING
154 /* As defined in plugins/lib/xxx2wav.h */
156 #define MALLOC_BUFSIZE (512*1024)
157 #define GUARD_BUFSIZE (32*1024)
159 #define MALLOC_BUFSIZE (100*1024)
160 #define GUARD_BUFSIZE (8*1024)
163 /* As defined in plugin.lds */
165 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
166 #define CODEC_IRAM_SIZE ((size_t)0xc000)
167 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
168 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
169 #define CODEC_IRAM_SIZE ((size_t)0x10000)
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
175 #ifndef IBSS_ATTR_VOICE_STACK
176 #define IBSS_ATTR_VOICE_STACK IBSS_ATTR
179 bool audio_is_initialized
= false;
181 /* Variables are commented with the threads that use them: *
182 * A=audio, C=codec, V=voice. A suffix of - indicates that *
183 * the variable is read but not updated on that thread. */
184 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
186 /* Main state control */
187 static volatile bool audio_codec_loaded NOCACHEBSS_ATTR
= false; /* Codec loaded? (C/A-) */
188 static volatile bool playing NOCACHEBSS_ATTR
= false; /* Is audio playing? (A) */
189 static volatile bool paused NOCACHEBSS_ATTR
= false; /* Is audio paused? (A/C-) */
190 static volatile bool filling IDATA_ATTR
= false; /* Is file buffer refilling? (A/C-) */
192 /* Ring buffer where compressed audio and codecs are loaded */
193 static unsigned char *filebuf
= NULL
; /* Start of buffer (A/C-) */
194 static unsigned char *malloc_buf
= NULL
; /* Start of malloc buffer (A/C-) */
195 /* FIXME: make filebuflen static */
196 size_t filebuflen
= 0; /* Size of buffer (A/C-) */
197 /* FIXME: make buf_ridx (C/A-) */
199 /* Possible arrangements of the buffer */
200 #define BUFFER_STATE_TRASHED -1 /* trashed; must be reset */
201 #define BUFFER_STATE_INITIALIZED 0 /* voice+audio OR audio-only */
202 #define BUFFER_STATE_VOICED_ONLY 1 /* voice-only */
203 static int buffer_state
= BUFFER_STATE_TRASHED
; /* Buffer state */
205 static struct mp3entry curtrack_id3
;
206 static struct mp3entry nexttrack_id3
;
208 /* Track info structure about songs in the file buffer (A/C-) */
210 int audio_hid
; /* The ID for the track's buffer handle */
211 int id3_hid
; /* The ID for the track's metadata handle */
212 int codec_hid
; /* The ID for the track's codec handle */
214 size_t codecsize
; /* Codec length in bytes */
215 size_t filesize
; /* File total length */
217 bool taginfo_ready
; /* Is metadata read */
219 bool event_sent
; /* Was this track's buffered event sent */
222 static struct track_info tracks
[MAX_TRACK
];
223 static volatile int track_ridx
= 0; /* Track being decoded (A/C-) */
224 static int track_widx
= 0; /* Track being buffered (A) */
226 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
228 /* Set by the audio thread when the current track information has updated
229 * and the WPS may need to update its cached information */
230 static bool track_changed
= false;
232 /* Information used only for filling the buffer */
233 /* Playlist steps from playing track to next track to be buffered (A) */
234 static int last_peek_offset
= 0;
236 /* Scrobbler support */
237 static unsigned long prev_track_elapsed
= 0; /* Previous track elapsed time (C/A-)*/
239 /* Track change controls */
240 static bool automatic_skip
= false; /* Who initiated in-progress skip? (C/A-) */
241 static bool playlist_end
= false; /* Has the current playlist ended? (A) */
242 static bool dir_skip
= false; /* Is a directory skip pending? (A) */
243 static bool new_playlist
= false; /* Are we starting a new playlist? (A) */
244 static int wps_offset
= 0; /* Pending track change offset, to keep WPS responsive (A) */
245 static bool skipped_during_pause
= false; /* Do we need to clear the PCM buffer when playback resumes (A) */
247 /* Callbacks which applications or plugins may set */
248 /* When the playing track has changed from the user's perspective */
249 void (*track_changed_callback
)(struct mp3entry
*id3
) = NULL
;
250 /* When a track has been buffered */
251 void (*track_buffer_callback
)(struct mp3entry
*id3
, bool last_track
) = NULL
;
252 /* When a track's buffer has been overwritten or cleared */
253 void (*track_unbuffer_callback
)(struct mp3entry
*id3
, bool last_track
) = NULL
;
256 static size_t conf_watermark
= 0; /* Level to trigger filebuf fill (A/C) FIXME */
257 static size_t conf_filechunk
= 0; /* Largest chunk the codec accepts (A/C) FIXME */
258 static size_t conf_preseek
= 0; /* Codec pre-seek margin (A/C) FIXME */
259 static size_t buffer_margin
= 0; /* Buffer margin aka anti-skip buffer (A/C-) */
261 static size_t high_watermark
= 0; /* High watermark for rebuffer (A/V/other) */
264 /* Multiple threads */
265 static void set_current_codec(int codec_idx
);
266 /* Set the watermark to trigger buffer fill (A/C) FIXME */
267 static void set_filebuf_watermark(int seconds
);
270 static struct event_queue audio_queue NOCACHEBSS_ATTR
;
271 static struct queue_sender_list audio_queue_sender_list NOCACHEBSS_ATTR
;
272 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
273 static const char audio_thread_name
[] = "audio";
275 static void audio_thread(void);
276 static void audio_initiate_track_change(long direction
);
277 static bool audio_have_tracks(void);
278 static void audio_reset_buffer(void);
281 extern struct codec_api ci
;
282 static struct event_queue codec_queue NOCACHEBSS_ATTR
;
283 static struct queue_sender_list codec_queue_sender_list
;
284 static long codec_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)]
286 static const char codec_thread_name
[] = "codec";
287 struct thread_entry
*codec_thread_p
; /* For modifying thread priority later. */
289 static volatile int current_codec IDATA_ATTR
; /* Current codec (normal/voice) */
292 #ifdef PLAYBACK_VOICE
294 extern struct codec_api ci_voice
;
296 static struct thread_entry
*voice_thread_p
= NULL
;
297 static struct event_queue voice_queue NOCACHEBSS_ATTR
;
298 static long voice_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)]
299 IBSS_ATTR_VOICE_STACK
;
300 static const char voice_thread_name
[] = "voice codec";
302 /* Voice codec swapping control */
303 extern unsigned char codecbuf
[]; /* DRAM codec swap buffer */
306 /* IRAM codec swap buffer for sim*/
307 static unsigned char sim_iram
[CODEC_IRAM_SIZE
];
308 #undef CODEC_IRAM_ORIGIN
309 #define CODEC_IRAM_ORIGIN sim_iram
312 /* iram_buf and dram_buf are either both NULL or both non-NULL */
313 /* Pointer to IRAM buffer for codec swapping */
314 static unsigned char *iram_buf
= NULL
;
315 /* Pointer to DRAM buffer for codec swapping */
316 static unsigned char *dram_buf
= NULL
;
317 /* Parity of swap_codec calls - needed because one codec swapping itself in
318 automatically swaps in the other and the swap when unlocking should not
319 happen if the parity is even.
321 static bool swap_codec_parity NOCACHEBSS_ATTR
= false; /* true=odd, false=even */
322 /* Locking to control which codec (normal/voice) is running */
323 static struct semaphore sem_codecthread NOCACHEBSS_ATTR
;
324 static struct event event_codecthread NOCACHEBSS_ATTR
;
327 static volatile bool voice_thread_start
= false; /* Triggers voice playback (A/V) */
328 static volatile bool voice_is_playing NOCACHEBSS_ATTR
= false; /* Is voice currently playing? (V) */
329 static volatile bool voice_codec_loaded NOCACHEBSS_ATTR
= false; /* Is voice codec loaded (V/A-) */
330 static unsigned char *voicebuf
= NULL
;
331 static size_t voice_remaining
= 0;
334 /* Voice IRAM has been stolen for other use */
335 static bool voice_iram_stolen
= false;
338 static void (*voice_getmore
)(unsigned char** start
, size_t* size
) = NULL
;
341 void (*callback
)(unsigned char **start
, size_t* size
);
345 static void voice_thread(void);
346 static void voice_stop(void);
348 #endif /* PLAYBACK_VOICE */
351 /* --- Helper functions --- */
353 struct mp3entry
*bufgetid3(int handle_id
)
358 struct mp3entry
*id3
;
359 ssize_t ret
= bufgetdata(handle_id
, 0, (void *)&id3
);
361 if (ret
< 0 || ret
!= sizeof(struct mp3entry
))
367 void *bufgetcodec(struct track_info
*track
)
370 ssize_t ret
= bufgetdata(track
->codec_hid
, track
->codecsize
, &ptr
);
373 request_buffer_handle(CUR_TI
->audio_hid
);
378 ret
= bufgetdata(track
->codec_hid
, track
->codecsize
, &ptr
);
387 void clear_track_info(struct track_info
*track
)
392 if (track
->codec_hid
> 0) {
393 bufclose(track
->codec_hid
);
396 if (track
->id3_hid
> 0) {
397 bufclose(track
->id3_hid
);
400 if (track
->audio_hid
> 0) {
401 bufclose(track
->audio_hid
);
404 memset(track
, 0, sizeof(struct track_info
));
407 /* --- External interfaces --- */
409 void mp3_play_data(const unsigned char* start
, int size
,
410 void (*get_more
)(unsigned char** start
, size_t* size
))
412 #ifdef PLAYBACK_VOICE
413 static struct voice_info voice_clip
;
414 voice_clip
.callback
= get_more
;
415 voice_clip
.buf
= (unsigned char*)start
;
416 voice_clip
.size
= size
;
417 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
418 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
419 LOGFQUEUE("mp3 > voice Q_VOICE_PLAY");
420 queue_post(&voice_queue
, Q_VOICE_PLAY
, (intptr_t)&voice_clip
);
421 voice_thread_start
= true;
430 void mp3_play_stop(void)
432 #ifdef PLAYBACK_VOICE
433 queue_remove_from_head(&voice_queue
, Q_VOICE_STOP
);
434 LOGFQUEUE("mp3 > voice Q_VOICE_STOP");
435 queue_post(&voice_queue
, Q_VOICE_STOP
, 1);
439 void mp3_play_pause(bool play
)
445 bool mp3_is_playing(void)
447 #ifdef PLAYBACK_VOICE
448 return voice_is_playing
;
454 /* If voice could be swapped out - wait for it to return
455 * Used by buffer claming functions.
457 static void wait_for_voice_swap_in(void)
459 #ifdef PLAYBACK_VOICE
460 if (NULL
== iram_buf
)
463 event_wait(&event_codecthread
, STATE_NONSIGNALED
);
464 #endif /* PLAYBACK_VOICE */
467 /* This sends a stop message and the audio thread will dump all it's
468 subsequenct messages */
469 static void audio_hard_stop(void)
472 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
473 queue_send(&audio_queue
, Q_AUDIO_STOP
, 1);
476 unsigned char *audio_get_buffer(bool talk_buf
, size_t *buffer_size
)
478 unsigned char *buf
, *end
;
480 if (audio_is_initialized
)
483 wait_for_voice_swap_in();
484 #ifdef PLAYBACK_VOICE
488 /* else buffer_state will be BUFFER_STATE_TRASHED at this point */
490 if (buffer_size
== NULL
)
492 /* Special case for talk_init to use since it already knows it's
494 buffer_state
= BUFFER_STATE_TRASHED
;
498 if (talk_buf
|| buffer_state
== BUFFER_STATE_TRASHED
499 || !talk_voice_required())
501 logf("get buffer: talk, audio");
502 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
503 the talk buffer is not needed because voice isn't being used, or
504 could be BUFFER_STATE_TRASHED already. If state is
505 BUFFER_STATE_VOICED_ONLY, no problem as long as memory isn't written
506 without the caller knowing what's going on. Changing certain settings
507 may move it to a worse condition but the memory in use by something
508 else will remain undisturbed.
510 if (buffer_state
!= BUFFER_STATE_TRASHED
)
513 buffer_state
= BUFFER_STATE_TRASHED
;
521 /* Safe to just return this if already BUFFER_STATE_VOICED_ONLY or
522 still BUFFER_STATE_INITIALIZED */
523 /* Skip talk buffer and move pcm buffer to end to maximize available
524 contiguous memory - no audio running means voice will not need the
526 logf("get buffer: audio");
527 buf
= audiobuf
+ talk_get_bufsize();
528 end
= audiobufend
- pcmbuf_init(audiobufend
);
529 buffer_state
= BUFFER_STATE_VOICED_ONLY
;
532 *buffer_size
= end
- buf
;
538 void audio_iram_steal(void)
540 /* We need to stop audio playback in order to use codec IRAM */
543 #ifdef PLAYBACK_VOICE
544 if (NULL
!= iram_buf
)
546 /* Can't already be stolen */
547 if (voice_iram_stolen
)
550 /* Must wait for voice to be current again if it is swapped which
551 would cause the caller's buffer to get clobbered when voice locks
552 and runs - we'll wait for it to lock and yield again then make sure
553 the ride has come to a complete stop */
554 wait_for_voice_swap_in();
557 /* Save voice IRAM but just memcpy - safe to do here since voice
558 is current and no audio codec is loaded */
559 memcpy(iram_buf
, CODEC_IRAM_ORIGIN
, CODEC_IRAM_SIZE
);
560 voice_iram_stolen
= true;
564 /* Nothing much to do if no voice */
565 voice_iram_stolen
= false;
569 #endif /* IRAM_STEAL */
571 #ifdef HAVE_RECORDING
572 unsigned char *audio_get_recording_buffer(size_t *buffer_size
)
574 /* Don't allow overwrite of voice swap area or we'll trash the
575 swapped-out voice codec but can use whole thing if none */
578 /* Stop audio and voice. Wait for voice to swap in and be clear
579 of pending events to ensure trouble-free operation of encoders */
581 wait_for_voice_swap_in();
582 #ifdef PLAYBACK_VOICE
587 #ifdef PLAYBACK_VOICE
588 /* If no dram_buf, swap space not used and recording gets more
589 memory. Codec swap areas will remain unaffected by the next init
590 since they're allocated at the end of the buffer and their sizes
591 don't change between calls */
594 #endif /* PLAYBACK_VOICE */
597 buffer_state
= BUFFER_STATE_TRASHED
;
599 *buffer_size
= end
- audiobuf
;
601 return (unsigned char *)audiobuf
;
604 bool audio_load_encoder(int afmt
)
607 const char *enc_fn
= get_codec_filename(afmt
| CODEC_TYPE_ENCODER
);
611 audio_remove_encoder();
612 ci
.enc_codec_loaded
= 0; /* clear any previous error condition */
614 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
615 queue_post(&codec_queue
, Q_ENCODER_LOAD_DISK
, (intptr_t)enc_fn
);
617 while (ci
.enc_codec_loaded
== 0)
620 logf("codec loaded: %d", ci
.enc_codec_loaded
);
622 return ci
.enc_codec_loaded
> 0;
627 } /* audio_load_encoder */
629 void audio_remove_encoder(void)
632 /* force encoder codec unload (if currently loaded) */
633 if (ci
.enc_codec_loaded
<= 0)
636 ci
.stop_encoder
= true;
637 while (ci
.enc_codec_loaded
> 0)
640 } /* audio_remove_encoder */
642 #endif /* HAVE_RECORDING */
644 struct mp3entry
* audio_current_track(void)
646 const char *filename
;
648 static struct mp3entry temp_id3
;
650 int offset
= ci
.new_track
+ wps_offset
;
652 cur_idx
= track_ridx
+ offset
;
653 cur_idx
&= MAX_TRACK_MASK
;
655 if (cur_idx
== track_ridx
&& *curtrack_id3
.path
)
656 return &curtrack_id3
;
657 else if (tracks
[cur_idx
].id3_hid
> 0)
658 return bufgetid3(tracks
[cur_idx
].id3_hid
);
660 memset(&temp_id3
, 0, sizeof(struct mp3entry
));
662 filename
= playlist_peek(0);
664 filename
= "No file!";
666 #ifdef HAVE_TC_RAMCACHE
667 if (tagcache_fill_tags(&temp_id3
, filename
))
671 p
= strrchr(filename
, '/');
677 strncpy(temp_id3
.path
, p
, sizeof(temp_id3
.path
)-1);
678 temp_id3
.title
= &temp_id3
.path
[0];
683 struct mp3entry
* audio_next_track(void)
685 int next_idx
= track_ridx
;
687 if (!audio_have_tracks())
691 next_idx
&= MAX_TRACK_MASK
;
693 if (tracks
[next_idx
].id3_hid
<= 0)
696 return &nexttrack_id3
;
699 bool audio_has_changed_track(void)
703 track_changed
= false;
710 void audio_play(long offset
)
714 #ifdef PLAYBACK_VOICE
715 /* Truncate any existing voice output so we don't have spelling
716 * etc. over the first part of the played track */
721 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset
);
722 /* Don't return until playback has actually started */
723 queue_send(&audio_queue
, Q_AUDIO_PLAY
, offset
);
726 void audio_stop(void)
729 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
730 /* Don't return until playback has actually stopped */
731 queue_send(&audio_queue
, Q_AUDIO_STOP
, 0);
734 void audio_pause(void)
736 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
737 /* Don't return until playback has actually paused */
738 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, true);
741 void audio_resume(void)
743 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
744 /* Don't return until playback has actually resumed */
745 queue_send(&audio_queue
, Q_AUDIO_PAUSE
, false);
748 void audio_next(void)
750 if (playlist_check(ci
.new_track
+ wps_offset
+ 1))
752 if (global_settings
.beep
)
753 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
755 LOGFQUEUE("audio > audio Q_AUDIO_SKIP 1");
756 queue_post(&audio_queue
, Q_AUDIO_SKIP
, 1);
757 /* Update wps while our message travels inside deep playback queues. */
759 track_changed
= true;
763 /* No more tracks. */
764 if (global_settings
.beep
)
765 pcmbuf_beep(1000, 100, 1000*global_settings
.beep
);
769 void audio_prev(void)
771 if (playlist_check(ci
.new_track
+ wps_offset
- 1))
773 if (global_settings
.beep
)
774 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
776 LOGFQUEUE("audio > audio Q_AUDIO_SKIP -1");
777 queue_post(&audio_queue
, Q_AUDIO_SKIP
, -1);
778 /* Update wps while our message travels inside deep playback queues. */
780 track_changed
= true;
784 /* No more tracks. */
785 if (global_settings
.beep
)
786 pcmbuf_beep(1000, 100, 1000*global_settings
.beep
);
790 void audio_next_dir(void)
792 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
793 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, 1);
796 void audio_prev_dir(void)
798 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
799 queue_post(&audio_queue
, Q_AUDIO_DIR_SKIP
, -1);
802 void audio_pre_ff_rewind(void)
804 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
805 queue_post(&audio_queue
, Q_AUDIO_PRE_FF_REWIND
, 0);
808 void audio_ff_rewind(long newpos
)
810 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
811 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, newpos
);
814 void audio_flush_and_reload_tracks(void)
816 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
817 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
820 void audio_error_clear(void)
822 #ifdef AUDIO_HAVE_RECORDING
823 pcm_rec_error_clear();
827 int audio_status(void)
832 ret
|= AUDIO_STATUS_PLAY
;
835 ret
|= AUDIO_STATUS_PAUSE
;
837 #ifdef HAVE_RECORDING
838 /* Do this here for constitency with mpeg.c version */
839 ret
|= pcm_rec_status();
845 int audio_get_file_pos(void)
850 #ifndef HAVE_FLASH_STORAGE
851 void audio_set_buffer_margin(int setting
)
853 static const int lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
854 buffer_margin
= lookup
[setting
];
855 logf("buffer margin: %d", buffer_margin
);
856 set_filebuf_watermark(buffer_margin
);
860 /* Take nescessary steps to enable or disable the crossfade setting */
861 void audio_set_crossfade(int enable
)
867 /* Tell it the next setting to use */
868 pcmbuf_crossfade_enable(enable
);
870 /* Return if size hasn't changed or this is too early to determine
871 which in the second case there's no way we could be playing
873 if (pcmbuf_is_same_size())
875 /* This function is a copout and just syncs some variables -
876 to be removed at a later date */
877 pcmbuf_crossfade_enable_finished();
882 was_playing
= playing
;
884 /* Playback has to be stopped before changing the buffer size */
887 /* Store the track resume position */
888 offset
= curtrack_id3
.offset
;
889 gui_syncsplash(0, str(LANG_RESTARTING_PLAYBACK
));
892 /* Blast it - audio buffer will have to be setup again next time
894 audio_get_buffer(true, &size
);
896 /* Restart playback if audio was running previously */
901 /* --- Routines called from multiple threads --- */
902 static void set_current_codec(int codec_idx
)
904 current_codec
= codec_idx
;
905 dsp_configure(DSP_SWITCH_CODEC
, codec_idx
);
908 #ifdef PLAYBACK_VOICE
909 static void swap_codec(void)
913 /* Swap nothing if no swap buffers exist */
914 if (dram_buf
== NULL
)
916 logf("swap: no swap buffers");
920 my_codec
= current_codec
;
922 logf("swapping out codec: %d", my_codec
);
924 /* Invert this when a codec thread enters and leaves */
925 swap_codec_parity
= !swap_codec_parity
;
927 /* If this is true, an odd number of calls has occurred and there's
928 no codec thread waiting to swap us out when it locks and runs. This
929 occurs when playback is stopped or when just starting playback and
930 the audio thread is loading a codec; parities should always be even
931 on entry when a thread calls this during playback */
932 if (swap_codec_parity
)
934 /* Save our current IRAM and DRAM */
936 if (voice_iram_stolen
)
938 logf("swap: iram restore");
939 voice_iram_stolen
= false;
940 /* Don't swap trashed data into buffer as the voice IRAM will
941 already be swapped out - should _always_ be the case if
942 voice_iram_stolen is true since the voice has been swapped
944 if (my_codec
== CODEC_IDX_VOICE
)
946 logf("voice iram already swapped");
952 memswap128(iram_buf
, CODEC_IRAM_ORIGIN
, CODEC_IRAM_SIZE
);
958 memswap128(dram_buf
, codecbuf
, CODEC_SIZE
);
959 /* No cache invalidation needed; it will be done in codec_load_ram
960 or we won't be here otherwise */
963 /* Release my semaphore */
964 semaphore_release(&sem_codecthread
);
965 logf("unlocked: %d", my_codec
);
967 /* Wait for other codec */
968 event_wait(&event_codecthread
,
969 (my_codec
== CODEC_IDX_AUDIO
) ? STATE_NONSIGNALED
: STATE_SIGNALED
);
971 /* Wait for other codec to unlock */
972 logf("waiting for lock: %d", my_codec
);
973 semaphore_wait(&sem_codecthread
);
976 set_current_codec(my_codec
);
977 event_set_state(&event_codecthread
,
978 (my_codec
== CODEC_IDX_AUDIO
) ? STATE_SIGNALED
: STATE_NONSIGNALED
);
980 /* Reload our IRAM and DRAM */
981 memswap128(iram_buf
, CODEC_IRAM_ORIGIN
, CODEC_IRAM_SIZE
);
982 memswap128(dram_buf
, codecbuf
, CODEC_SIZE
);
985 /* Flip parity again */
986 swap_codec_parity
= !swap_codec_parity
;
988 logf("resuming codec: %d", my_codec
);
991 /* This function is meant to be used by the buffer stealing functions to
992 ensure the codec is no longer active and so voice will be swapped-in
993 before it is called */
994 static void voice_stop(void)
996 /* Must have a voice codec loaded or we'll hang forever here */
997 if (!voice_codec_loaded
)
1000 talk_force_shutup();
1002 /* Loop until voice empties it's queue, stops and picks up on the new
1003 track; the voice thread must be stopped and waiting for messages
1004 outside the codec */
1005 while (voice_is_playing
|| !queue_empty(&voice_queue
) ||
1013 /* Is voice still speaking */
1014 /* Unfortunately only reliable when music is not also playing. */
1015 static bool is_voice_speaking(void)
1017 return is_voice_queued()
1019 || (!playing
&& pcm_is_playing());
1022 #endif /* PLAYBACK_VOICE */
1024 /* Wait for voice to finish speaking. */
1025 /* Also only reliable when music is not also playing. */
1026 void voice_wait(void)
1028 #ifdef PLAYBACK_VOICE
1029 while (is_voice_speaking())
1034 static void set_filebuf_watermark(int seconds
)
1039 return; /* Audio buffers not yet set up */
1041 bytes
= MAX(curtrack_id3
.bitrate
* seconds
* (1000/8), conf_watermark
);
1042 bytes
= MIN(bytes
, filebuflen
/ 2);
1043 conf_watermark
= bytes
;
1046 const char * get_codec_filename(int cod_spec
)
1050 #ifdef HAVE_RECORDING
1051 /* Can choose decoder or encoder if one available */
1052 int type
= cod_spec
& CODEC_TYPE_MASK
;
1053 int afmt
= cod_spec
& CODEC_AFMT_MASK
;
1055 if ((unsigned)afmt
>= AFMT_NUM_CODECS
)
1056 type
= AFMT_UNKNOWN
| (type
& CODEC_TYPE_MASK
);
1058 fname
= (type
== CODEC_TYPE_ENCODER
) ?
1059 audio_formats
[afmt
].codec_enc_root_fn
:
1060 audio_formats
[afmt
].codec_root_fn
;
1063 (type
== CODEC_TYPE_ENCODER
) ? "Encoder" : "Decoder",
1064 afmt
, fname
? fname
: "<unknown>");
1065 #else /* !HAVE_RECORDING */
1066 /* Always decoder */
1067 if ((unsigned)cod_spec
>= AFMT_NUM_CODECS
)
1068 cod_spec
= AFMT_UNKNOWN
;
1069 fname
= audio_formats
[cod_spec
].codec_root_fn
;
1070 logf("Codec: %d - %s", cod_spec
, fname
? fname
: "<unknown>");
1071 #endif /* HAVE_RECORDING */
1074 } /* get_codec_filename */
1077 /* --- Voice thread --- */
1079 #ifdef PLAYBACK_VOICE
1081 static bool voice_pcmbuf_insert_callback(
1082 const void *ch1
, const void *ch2
, int count
)
1084 const char *src
[2] = { ch1
, ch2
};
1088 int out_count
= dsp_output_count(count
);
1092 while ((dest
= pcmbuf_request_voice_buffer(
1093 &out_count
, playing
)) == NULL
)
1095 if (playing
&& audio_codec_loaded
)
1101 /* Get the real input_size for output_size bytes, guarding
1102 * against resampling buffer overflows. */
1103 inp_count
= dsp_input_count(out_count
);
1108 /* Input size has grown, no error, just don't write more than length */
1109 if (inp_count
> count
)
1112 out_count
= dsp_process(dest
, src
, inp_count
);
1119 pcmbuf_mix_voice(out_count
);
1120 if ((pcmbuf_usage() < 10 || pcmbuf_mix_free() < 30) &&
1125 pcmbuf_write_complete(out_count
);
1131 } /* voice_pcmbuf_insert_callback */
1133 static void* voice_get_memory_callback(size_t *size
)
1135 /* Voice should have no use for this. If it did, we'd have to
1136 swap the malloc buffer as well. */
1141 static void voice_set_elapsed_callback(unsigned int value
)
1146 static void voice_set_offset_callback(size_t value
)
1151 static void voice_configure_callback(int setting
, intptr_t value
)
1153 if (!dsp_configure(setting
, value
))
1155 logf("Illegal key:%d", setting
);
1159 static size_t voice_filebuf_callback(void *ptr
, size_t size
)
1167 /* Handle Q_VOICE_STOP and part of SYS_USB_CONNECTED */
1168 static bool voice_on_voice_stop(bool aborting
, size_t *realsize
)
1170 if (aborting
&& !playing
)
1172 /* Aborting: Slight hack - flush PCM buffer if
1173 only being used for voice */
1177 if (voice_is_playing
)
1179 /* Clear the current buffer */
1180 voice_is_playing
= false;
1181 voice_getmore
= NULL
;
1182 voice_remaining
= 0;
1185 /* Cancel any automatic boost if no more clips requested. */
1186 if (!playing
|| !voice_thread_start
)
1189 /* Force the codec to think it's changing tracks */
1190 ci_voice
.new_track
= 1;
1193 return true; /* Yes, change tracks */
1199 static void* voice_request_buffer_callback(size_t *realsize
, size_t reqsize
)
1201 struct queue_event ev
;
1203 if (ci_voice
.new_track
)
1211 if (voice_is_playing
|| playing
)
1213 queue_wait_w_tmo(&voice_queue
, &ev
, 0);
1214 if (!voice_is_playing
&& ev
.id
== SYS_TIMEOUT
)
1215 ev
.id
= Q_AUDIO_PLAY
;
1219 queue_wait(&voice_queue
, &ev
);
1224 LOGFQUEUE("voice < Q_AUDIO_PLAY");
1227 if (audio_codec_loaded
)
1233 #ifdef AUDIO_HAVE_RECORDING
1234 case Q_ENCODER_RECORD
:
1235 LOGFQUEUE("voice < Q_ENCODER_RECORD");
1241 LOGFQUEUE("voice < Q_VOICE_STOP");
1242 if (voice_on_voice_stop(ev
.data
, realsize
))
1246 case SYS_USB_CONNECTED
:
1248 LOGFQUEUE("voice < SYS_USB_CONNECTED");
1249 bool change_tracks
= voice_on_voice_stop(ev
.data
, realsize
);
1250 /* Voice is obviously current so let us swap ourselves away if
1251 playing so audio may stop itself - audio_codec_loaded can
1252 only be true in this case if we're here even if the codec
1253 is only about to load */
1254 if (audio_codec_loaded
)
1256 /* Playback should be finished by now - ack and wait */
1257 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1258 usb_wait_for_disconnect(&voice_queue
);
1265 LOGFQUEUE("voice < Q_VOICE_PLAY");
1266 if (!voice_is_playing
)
1268 /* Set up new voice data */
1269 struct voice_info
*voice_data
;
1271 if (voice_iram_stolen
)
1273 /* Voice is the first to run again and is currently
1275 logf("voice: iram restore");
1276 memcpy(CODEC_IRAM_ORIGIN
, iram_buf
, CODEC_IRAM_SIZE
);
1277 voice_iram_stolen
= false;
1280 /* Must reset the buffer before any playback begins if
1282 if (buffer_state
== BUFFER_STATE_TRASHED
)
1283 audio_reset_buffer();
1285 voice_is_playing
= true;
1286 trigger_cpu_boost();
1287 voice_data
= (struct voice_info
*)ev
.data
;
1288 voice_remaining
= voice_data
->size
;
1289 voicebuf
= voice_data
->buf
;
1290 voice_getmore
= voice_data
->callback
;
1292 goto voice_play_clip
; /* To exit both switch and while */
1295 LOGFQUEUE_SYS_TIMEOUT("voice < SYS_TIMEOUT");
1296 goto voice_play_clip
;
1299 LOGFQUEUE("voice < default");
1305 if (voice_remaining
== 0 || voicebuf
== NULL
)
1308 voice_getmore((unsigned char **)&voicebuf
, &voice_remaining
);
1310 /* If this clip is done */
1311 if (voice_remaining
== 0)
1313 LOGFQUEUE("voice > voice Q_VOICE_STOP");
1314 queue_post(&voice_queue
, Q_VOICE_STOP
, 0);
1315 /* Force pcm playback. */
1316 if (!pcm_is_playing())
1317 pcmbuf_play_start();
1321 *realsize
= MIN(voice_remaining
, reqsize
);
1327 } /* voice_request_buffer_callback */
1329 static void voice_advance_buffer_callback(size_t amount
)
1331 amount
= MIN(amount
, voice_remaining
);
1333 voice_remaining
-= amount
;
1336 static void voice_advance_buffer_loc_callback(void *ptr
)
1338 size_t amount
= (size_t)ptr
- (size_t)voicebuf
;
1340 voice_advance_buffer_callback(amount
);
1343 static off_t
voice_mp3_get_filepos_callback(int newtime
)
1350 static void voice_do_nothing(void)
1355 static bool voice_seek_buffer_callback(size_t newpos
)
1362 static bool voice_request_next_track_callback(void)
1364 ci_voice
.new_track
= 0;
1368 static void voice_thread(void)
1370 logf("Loading voice codec");
1371 voice_codec_loaded
= true;
1372 semaphore_wait(&sem_codecthread
);
1373 event_set_state(&event_codecthread
, false);
1374 set_current_codec(CODEC_IDX_VOICE
);
1375 dsp_configure(DSP_RESET
, 0);
1376 voice_remaining
= 0;
1377 voice_getmore
= NULL
;
1379 /* FIXME: If we being starting the voice thread without reboot, the
1380 voice_queue could be full of old stuff and we must flush it. */
1381 codec_load_file(get_codec_filename(AFMT_MPA_L3
), &ci_voice
);
1383 logf("Voice codec finished");
1384 voice_codec_loaded
= false;
1385 voice_thread_p
= NULL
;
1386 semaphore_release(&sem_codecthread
);
1387 } /* voice_thread */
1389 #endif /* PLAYBACK_VOICE */
1391 /* --- Codec thread --- */
1392 static bool codec_pcmbuf_insert_callback(
1393 const void *ch1
, const void *ch2
, int count
)
1395 const char *src
[2] = { ch1
, ch2
};
1399 int out_count
= dsp_output_count(count
);
1403 /* Prevent audio from a previous track from playing */
1404 if (ci
.new_track
|| ci
.stop_codec
)
1407 while ((dest
= pcmbuf_request_buffer(&out_count
)) == NULL
)
1410 if (ci
.seek_time
|| ci
.new_track
|| ci
.stop_codec
)
1414 /* Get the real input_size for output_size bytes, guarding
1415 * against resampling buffer overflows. */
1416 inp_count
= dsp_input_count(out_count
);
1421 /* Input size has grown, no error, just don't write more than length */
1422 if (inp_count
> count
)
1425 out_count
= dsp_process(dest
, src
, inp_count
);
1430 pcmbuf_write_complete(out_count
);
1432 #ifdef PLAYBACK_VOICE
1433 if ((voice_is_playing
|| voice_thread_start
)
1434 && pcm_is_playing() && voice_codec_loaded
&&
1435 pcmbuf_usage() > 30 && pcmbuf_mix_free() > 80)
1437 voice_thread_start
= false;
1446 } /* codec_pcmbuf_insert_callback */
1448 static void* codec_get_memory_callback(size_t *size
)
1450 *size
= MALLOC_BUFSIZE
;
1455 static void codec_pcmbuf_position_callback(size_t size
) ICODE_ATTR
;
1456 static void codec_pcmbuf_position_callback(size_t size
)
1458 /* This is called from an ISR, so be quick */
1459 unsigned int time
= size
* 1000 / 4 / NATIVE_FREQUENCY
+
1460 prev_ti
->id3
.elapsed
;
1462 if (time
>= prev_ti
->id3
.length
)
1464 pcmbuf_set_position_callback(NULL
);
1465 prev_ti
->id3
.elapsed
= prev_ti
->id3
.length
;
1468 prev_ti
->id3
.elapsed
= time
;
1472 static void codec_set_elapsed_callback(unsigned int value
)
1474 unsigned int latency
;
1478 #ifdef AB_REPEAT_ENABLE
1479 ab_position_report(value
);
1482 latency
= pcmbuf_get_latency();
1483 if (value
< latency
)
1484 curtrack_id3
.elapsed
= 0;
1485 else if (value
- latency
> curtrack_id3
.elapsed
||
1486 value
- latency
< curtrack_id3
.elapsed
- 2)
1488 curtrack_id3
.elapsed
= value
- latency
;
1492 static void codec_set_offset_callback(size_t value
)
1494 unsigned int latency
;
1499 latency
= pcmbuf_get_latency() * curtrack_id3
.bitrate
/ 8;
1500 if (value
< latency
)
1501 curtrack_id3
.offset
= 0;
1503 curtrack_id3
.offset
= value
- latency
;
1506 static void codec_advance_buffer_counters(size_t amount
)
1508 bufadvance(CUR_TI
->audio_hid
, amount
);
1509 ci
.curpos
+= amount
;
1511 /* Start buffer filling as necessary. */
1512 if (!pcmbuf_is_lowdata() && !buffering
)
1514 if (useful_data(CUR_TI
->audio_hid
) < conf_watermark
&&
1515 playing
&& !playlist_end
)
1517 LOGFQUEUE("codec > audio Q_AUDIO_FILL_BUFFER");
1518 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER
, 0);
1523 /* copy up-to size bytes into ptr and return the actual size copied */
1524 static size_t codec_filebuf_callback(void *ptr
, size_t size
)
1528 if (ci
.stop_codec
|| !playing
)
1531 copy_n
= bufread(CUR_TI
->audio_hid
, size
, ptr
);
1533 /* Nothing requested OR nothing left */
1540 request_buffer_handle(CUR_TI
->audio_hid
);
1543 /* Let the disk buffer catch fill until enough data is available */
1544 while (copy_n
== -2)
1548 if (ci
.stop_codec
|| ci
.new_track
)
1551 copy_n
= bufread(CUR_TI
->audio_hid
, size
, ptr
);
1554 /* Update read and other position pointers */
1555 codec_advance_buffer_counters(copy_n
);
1557 /* Return the actual amount of data copied to the buffer */
1559 } /* codec_filebuf_callback */
1561 static void* codec_request_buffer_callback(size_t *realsize
, size_t reqsize
)
1563 size_t copy_n
= reqsize
;
1573 ret
= bufgetdata(CUR_TI
->audio_hid
, reqsize
, &ptr
);
1575 copy_n
= MIN((size_t)ret
, reqsize
);
1585 request_buffer_handle(CUR_TI
->audio_hid
);
1588 /* Let the disk buffer catch fill until enough data is available */
1593 if (ci
.stop_codec
|| ci
.new_track
)
1598 ret
= bufgetdata(CUR_TI
->audio_hid
, reqsize
, &ptr
);
1600 copy_n
= MIN((size_t)ret
, reqsize
);
1605 } /* codec_request_buffer_callback */
1607 static int get_codec_base_type(int type
)
1619 static void codec_advance_buffer_callback(size_t amount
)
1621 codec_advance_buffer_counters(amount
);
1622 codec_set_offset_callback(ci
.curpos
);
1625 static void codec_advance_buffer_loc_callback(void *ptr
)
1627 size_t amount
= get_offset(CUR_TI
->audio_hid
, ptr
);
1629 codec_advance_buffer_callback(amount
);
1632 /* Copied from mpeg.c. Should be moved somewhere else. */
1633 static int codec_get_file_pos(void)
1636 struct mp3entry
*id3
= audio_current_track();
1642 /* Use the TOC to find the new position */
1643 unsigned int percent
, remainder
;
1644 int curtoc
, nexttoc
, plen
;
1646 percent
= (id3
->elapsed
*100)/id3
->length
;
1650 curtoc
= id3
->toc
[percent
];
1653 nexttoc
= id3
->toc
[percent
+1];
1657 pos
= (id3
->filesize
/256)*curtoc
;
1659 /* Use the remainder to get a more accurate position */
1660 remainder
= (id3
->elapsed
*100)%id3
->length
;
1661 remainder
= (remainder
*100)/id3
->length
;
1662 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
1663 pos
+= (plen
/100)*remainder
;
1667 /* No TOC exists, estimate the new position */
1668 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
1669 (id3
->elapsed
/ 1000);
1672 else if (id3
->bitrate
)
1673 pos
= id3
->elapsed
* (id3
->bitrate
/ 8);
1677 pos
+= id3
->first_frame_offset
;
1679 /* Don't seek right to the end of the file so that we can
1680 transition properly to the next song */
1681 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
1682 pos
= id3
->filesize
- id3
->id3v1len
- 1;
1687 static off_t
codec_mp3_get_filepos_callback(int newtime
)
1691 curtrack_id3
.elapsed
= newtime
;
1692 newpos
= codec_get_file_pos();
1697 static void codec_seek_complete_callback(void)
1699 logf("seek_complete");
1700 if (pcm_is_paused())
1702 /* If this is not a seamless seek, clear the buffer */
1704 dsp_configure(DSP_FLUSH
, 0);
1706 /* If playback was not 'deliberately' paused, unpause now */
1708 pcmbuf_pause(false);
1713 static bool codec_seek_buffer_callback(size_t newpos
)
1715 logf("codec_seek_buffer_callback");
1717 int ret
= bufseek(CUR_TI
->audio_hid
, newpos
);
1727 static void codec_configure_callback(int setting
, intptr_t value
)
1730 case CODEC_SET_FILEBUF_WATERMARK
:
1731 conf_watermark
= value
;
1732 set_filebuf_watermark(buffer_margin
);
1735 case CODEC_SET_FILEBUF_CHUNKSIZE
:
1736 conf_filechunk
= value
;
1739 case CODEC_SET_FILEBUF_PRESEEK
:
1740 conf_preseek
= value
;
1744 if (!dsp_configure(setting
, value
)) { logf("Illegal key:%d", setting
); }
1748 static void codec_track_changed(void)
1750 automatic_skip
= false;
1751 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1752 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1755 static void codec_pcmbuf_track_changed_callback(void)
1757 pcmbuf_set_position_callback(NULL
);
1758 codec_track_changed();
1761 static void codec_discard_codec_callback(void)
1763 if (CUR_TI
->codec_hid
> 0)
1765 bufclose(CUR_TI
->codec_hid
);
1766 CUR_TI
->codec_hid
= 0;
1767 CUR_TI
->codecsize
= 0;
1771 static inline void codec_gapless_track_change(void) {
1772 /* callback keeps the progress bar moving while the pcmbuf empties */
1773 /* pcmbuf_set_position_callback(codec_pcmbuf_position_callback); */
1774 /* set the pcmbuf callback for when the track really changes */
1775 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback
);
1778 static inline void codec_crossfade_track_change(void) {
1779 /* Initiate automatic crossfade mode */
1780 pcmbuf_crossfade_init(false);
1781 /* Notify the wps that the track change starts now */
1782 codec_track_changed();
1785 static void codec_track_skip_done(bool was_manual
)
1787 int crossfade_mode
= global_settings
.crossfade
;
1789 /* Manual track change (always crossfade or flush audio). */
1792 pcmbuf_crossfade_init(true);
1793 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1794 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
1796 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1797 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1798 && crossfade_mode
!= CROSSFADE_ENABLE_TRACKSKIP
)
1800 if (crossfade_mode
== CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP
)
1802 if (global_settings
.playlist_shuffle
)
1803 /* shuffle mode is on, so crossfade: */
1804 codec_crossfade_track_change();
1806 /* shuffle mode is off, so do a gapless track change */
1807 codec_gapless_track_change();
1810 /* normal crossfade: */
1811 codec_crossfade_track_change();
1814 /* normal gapless playback. */
1815 codec_gapless_track_change();
1818 static bool codec_load_next_track(void)
1820 intptr_t result
= Q_CODEC_REQUEST_FAILED
;
1822 prev_track_elapsed
= curtrack_id3
.elapsed
;
1825 codec_seek_complete_callback();
1827 #ifdef AB_REPEAT_ENABLE
1828 ab_end_of_track_report();
1831 logf("Request new track");
1833 if (ci
.new_track
== 0)
1836 automatic_skip
= true;
1841 trigger_cpu_boost();
1842 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1843 result
= queue_send(&audio_queue
, Q_AUDIO_CHECK_NEW_TRACK
, 0);
1848 case Q_CODEC_REQUEST_COMPLETE
:
1849 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1850 codec_track_skip_done(!automatic_skip
);
1853 case Q_CODEC_REQUEST_FAILED
:
1854 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1856 ci
.stop_codec
= true;
1860 LOGFQUEUE("codec |< default");
1861 ci
.stop_codec
= true;
1866 static bool codec_request_next_track_callback(void)
1870 if (ci
.stop_codec
|| !playing
)
1873 prev_codectype
= get_codec_base_type(curtrack_id3
.codectype
);
1875 if (!codec_load_next_track())
1878 /* Seek to the beginning of the new track because if the struct mp3entry was
1879 buffered, "elapsed" might not be zero (if the track has been played
1880 already but not unbuffered) */
1881 codec_seek_buffer_callback(0);
1883 /* Check if the next codec is the same file. */
1884 if (prev_codectype
== get_codec_base_type(curtrack_id3
.codectype
))
1886 logf("New track loaded");
1887 codec_discard_codec_callback();
1892 logf("New codec:%d/%d", curtrack_id3
.codectype
, prev_codectype
);
1897 static void codec_thread(void)
1899 struct queue_event ev
;
1905 queue_wait(&codec_queue
, &ev
);
1908 case Q_CODEC_LOAD_DISK
:
1909 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1910 queue_reply(&codec_queue
, 1);
1911 audio_codec_loaded
= true;
1912 #ifdef PLAYBACK_VOICE
1913 /* Don't sent messages to voice codec if it's already swapped
1914 out or it will never get this */
1915 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1917 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1918 queue_post(&voice_queue
, Q_AUDIO_PLAY
, 0);
1920 semaphore_wait(&sem_codecthread
);
1921 event_set_state(&event_codecthread
, true);
1923 set_current_codec(CODEC_IDX_AUDIO
);
1924 ci
.stop_codec
= false;
1925 status
= codec_load_file((const char *)ev
.data
, &ci
);
1926 DEBUGF("codec_load = %d\n", status
);
1927 #ifdef PLAYBACK_VOICE
1928 semaphore_release(&sem_codecthread
);
1933 LOGFQUEUE("codec < Q_CODEC_LOAD");
1934 if (CUR_TI
->codec_hid
<= 0) {
1935 logf("Codec slot is empty!");
1936 /* Wait for the pcm buffer to go empty */
1937 while (pcm_is_playing())
1939 /* This must be set to prevent an infinite loop */
1940 ci
.stop_codec
= true;
1941 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1942 queue_post(&codec_queue
, Q_AUDIO_PLAY
, 0);
1946 audio_codec_loaded
= true;
1947 #ifdef PLAYBACK_VOICE
1948 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1950 LOGFQUEUE("codec > voice Q_AUDIO_PLAY");
1951 queue_post(&voice_queue
, Q_AUDIO_PLAY
, 0);
1953 semaphore_wait(&sem_codecthread
);
1954 event_set_state(&event_codecthread
, true);
1956 set_current_codec(CODEC_IDX_AUDIO
);
1957 ci
.stop_codec
= false;
1958 wrap
= (size_t)&filebuf
[filebuflen
] - (size_t)bufgetcodec(CUR_TI
);
1959 status
= codec_load_ram(bufgetcodec(CUR_TI
), CUR_TI
->codecsize
,
1960 &filebuf
[0], wrap
, &ci
);
1961 #ifdef PLAYBACK_VOICE
1962 semaphore_release(&sem_codecthread
);
1966 #ifdef AUDIO_HAVE_RECORDING
1967 case Q_ENCODER_LOAD_DISK
:
1968 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1969 audio_codec_loaded
= false; /* Not audio codec! */
1970 #ifdef PLAYBACK_VOICE
1971 if (voice_codec_loaded
&& current_codec
== CODEC_IDX_VOICE
)
1973 LOGFQUEUE("codec > voice Q_ENCODER_RECORD");
1974 queue_post(&voice_queue
, Q_ENCODER_RECORD
, 0);
1976 semaphore_wait(&sem_codecthread
);
1977 event_set_state(&event_codecthread
, true);
1979 logf("loading encoder");
1980 set_current_codec(CODEC_IDX_AUDIO
);
1981 ci
.stop_encoder
= false;
1982 status
= codec_load_file((const char *)ev
.data
, &ci
);
1983 #ifdef PLAYBACK_VOICE
1984 semaphore_release(&sem_codecthread
);
1986 logf("encoder stopped");
1988 #endif /* AUDIO_HAVE_RECORDING */
1991 case SYS_USB_CONNECTED
:
1992 LOGFQUEUE("codec < SYS_USB_CONNECTED");
1993 queue_clear(&codec_queue
);
1994 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1995 usb_wait_for_disconnect(&codec_queue
);
2000 LOGFQUEUE("codec < default");
2003 if (audio_codec_loaded
)
2012 audio_codec_loaded
= false;
2016 case Q_CODEC_LOAD_DISK
:
2018 LOGFQUEUE("codec < Q_CODEC_LOAD");
2021 if (ci
.new_track
|| status
!= CODEC_OK
)
2025 logf("Codec failure");
2026 gui_syncsplash(HZ
*2, "Codec failure");
2029 if (!codec_load_next_track())
2031 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2032 /* End of playlist */
2033 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
2039 logf("Codec finished");
2042 /* Wait for the audio to stop playing before
2043 * triggering the WPS exit */
2044 while(pcm_is_playing())
2046 curtrack_id3
.elapsed
=
2047 curtrack_id3
.length
- pcmbuf_get_latency();
2050 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
2051 /* End of playlist */
2052 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
2057 if (CUR_TI
->codec_hid
> 0)
2059 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
2060 queue_post(&codec_queue
, Q_CODEC_LOAD
, 0);
2064 const char *codec_fn
=
2065 get_codec_filename(curtrack_id3
.codectype
);
2066 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2067 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
,
2068 (intptr_t)codec_fn
);
2073 #ifdef AUDIO_HAVE_RECORDING
2074 case Q_ENCODER_LOAD_DISK
:
2075 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
2077 if (status
== CODEC_OK
)
2080 logf("Encoder failure");
2081 gui_syncsplash(HZ
*2, "Encoder failure");
2083 if (ci
.enc_codec_loaded
< 0)
2086 logf("Encoder failed to load");
2087 ci
.enc_codec_loaded
= -1;
2089 #endif /* AUDIO_HAVE_RECORDING */
2092 LOGFQUEUE("codec < default");
2099 /* --- Audio thread --- */
2101 static bool audio_have_tracks(void)
2103 return track_ridx
!= track_widx
|| CUR_TI
->filesize
;
2106 static bool audio_have_free_tracks(void)
2108 if (track_widx
< track_ridx
)
2109 return track_widx
+ 1 < track_ridx
;
2110 else if (track_ridx
== 0)
2111 return track_widx
< MAX_TRACK
- 1;
2116 int audio_track_count(void)
2118 if (audio_have_tracks())
2120 int relative_track_widx
= track_widx
;
2122 if (track_ridx
> track_widx
)
2123 relative_track_widx
+= MAX_TRACK
;
2125 return relative_track_widx
- track_ridx
+ 1;
2131 long audio_filebufused(void)
2133 return (long) bufused();
2136 static void audio_update_trackinfo(void)
2138 if (CUR_TI
->id3_hid
> 0)
2139 copy_mp3entry(&curtrack_id3
, bufgetid3(CUR_TI
->id3_hid
));
2141 CUR_TI
->taginfo_ready
= (CUR_TI
->id3_hid
> 0);
2143 int next_idx
= track_ridx
+ 1;
2144 next_idx
&= MAX_TRACK_MASK
;
2146 if (tracks
[next_idx
].id3_hid
> 0)
2147 copy_mp3entry(&nexttrack_id3
, bufgetid3(tracks
[next_idx
].id3_hid
));
2149 tracks
[next_idx
].taginfo_ready
= (tracks
[next_idx
].id3_hid
> 0);
2151 ci
.filesize
= CUR_TI
->filesize
;
2152 curtrack_id3
.elapsed
= 0;
2153 curtrack_id3
.offset
= 0;
2154 ci
.id3
= &curtrack_id3
;
2156 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
2159 static void audio_clear_track_entries(bool clear_unbuffered
)
2161 int cur_idx
= track_widx
;
2164 logf("Clearing tracks:%d/%d, %d", track_ridx
, track_widx
, clear_unbuffered
);
2166 /* Loop over all tracks from write-to-read */
2170 cur_idx
&= MAX_TRACK_MASK
;
2172 if (cur_idx
== track_ridx
)
2175 /* If the track is buffered, conditionally clear/notify,
2176 * otherwise clear the track if that option is selected */
2177 if (tracks
[cur_idx
].event_sent
)
2181 /* If there is an unbuffer callback, call it, otherwise,
2182 * just clear the track */
2183 if (track_unbuffer_callback
&& tracks
[last_idx
].id3_hid
> 0)
2184 track_unbuffer_callback(bufgetid3(tracks
[last_idx
].id3_hid
), false);
2186 clear_track_info(&tracks
[last_idx
]);
2190 else if (clear_unbuffered
)
2191 clear_track_info(&tracks
[cur_idx
]);
2194 /* We clear the previous instance of a buffered track throughout
2195 * the above loop to facilitate 'last' detection. Clear/notify
2196 * the last track here */
2199 if (track_unbuffer_callback
&& tracks
[last_idx
].id3_hid
> 0)
2200 track_unbuffer_callback(bufgetid3(tracks
[last_idx
].id3_hid
), true);
2201 clear_track_info(&tracks
[last_idx
]);
2205 static void audio_release_tracks(void)
2209 logf("releasing all tracks");
2211 for(i
= 0; i
< MAX_TRACKS
; i
++)
2213 cur_idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
2214 clear_track_info(&tracks
[cur_idx
]);
2219 /* FIXME: This code should be made more generic and move to metadata.c */
2220 static void audio_strip_tags(void)
2223 static const unsigned char tag
[] = "TAG";
2224 static const unsigned char apetag
[] = "APETAGEX";
2227 size_t len
, version
;
2229 tag_idx
= RINGBUF_SUB(buf_widx
, 128);
2231 if (bufused() > 128 && tag_idx
> buf_ridx
)
2234 for(i
= 0;i
< 3;i
++)
2236 if(filebuf
[cur_idx
] != tag
[i
])
2239 cur_idx
= RINGBUF_ADD(cur_idx
, 1);
2242 /* Skip id3v1 tag */
2243 logf("Skipping ID3v1 tag");
2245 tracks
[track_widx
].available
-= 128;
2246 tracks
[track_widx
].filesize
-= 128;
2250 /* Check for APE tag (look for the APE tag footer) */
2251 tag_idx
= RINGBUF_SUB(buf_widx
, 32);
2253 if (bufused() > 32 && tag_idx
> buf_ridx
)
2256 for(i
= 0;i
< 8;i
++)
2258 if(filebuf
[cur_idx
] != apetag
[i
])
2261 cur_idx
= RINGBUF_ADD(cur_idx
, 1);
2264 /* Read the version and length from the footer */
2265 version
= filebuf
[tag_idx
+8] | (filebuf
[tag_idx
+9] << 8) |
2266 (filebuf
[tag_idx
+10] << 16) | (filebuf
[tag_idx
+11] << 24);
2267 len
= filebuf
[tag_idx
+12] | (filebuf
[tag_idx
+13] << 8) |
2268 (filebuf
[tag_idx
+14] << 16) | (filebuf
[tag_idx
+15] << 24);
2269 if (version
== 2000)
2270 len
+= 32; /* APEv2 has a 32 byte header */
2273 if (bufused() > len
)
2275 logf("Skipping APE tag (%ldB)", len
);
2276 buf_widx
= RINGBUF_SUB(buf_widx
, len
);
2277 tracks
[track_widx
].available
-= len
;
2278 tracks
[track_widx
].filesize
-= len
;
2284 static bool audio_loadcodec(bool start_play
)
2288 char codec_path
[MAX_PATH
]; /* Full path to codec */
2290 DEBUGF("audio_loadcodec(start_play = %s)\n", start_play
? "true" : "false");
2292 if (tracks
[track_widx
].id3_hid
<= 0) {
2293 DEBUGF("track ID3 info not ready\n");
2297 const char * codec_fn
=
2298 get_codec_filename(bufgetid3(tracks
[track_widx
].id3_hid
)->codectype
);
2299 if (codec_fn
== NULL
)
2302 tracks
[track_widx
].codec_hid
= 0;
2306 /* Load the codec directly from disk and save some memory. */
2307 track_ridx
= track_widx
;
2308 ci
.filesize
= CUR_TI
->filesize
;
2309 ci
.id3
= &curtrack_id3
;
2310 ci
.taginfo_ready
= &CUR_TI
->taginfo_ready
;
2312 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
2313 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
, (intptr_t)codec_fn
);
2318 /* If we already have another track than this one buffered */
2319 if (track_widx
!= track_ridx
)
2321 prev_track
= (track_widx
- 1) & MAX_TRACK_MASK
;
2323 /* If the previous codec is the same as this one, there is no need
2324 * to put another copy of it on the file buffer */
2325 if (get_codec_base_type(
2326 bufgetid3(tracks
[track_widx
].id3_hid
)->codectype
) ==
2327 get_codec_base_type(
2328 bufgetid3(tracks
[prev_track
].id3_hid
)->codectype
)
2329 && audio_codec_loaded
)
2331 logf("Reusing prev. codec");
2337 codec_get_full_path(codec_path
, codec_fn
);
2339 fd
= open(codec_path
, O_RDONLY
);
2342 logf("Codec doesn't exist!");
2346 tracks
[track_widx
].codecsize
= filesize(fd
);
2348 tracks
[track_widx
].codec_hid
= bufopen(codec_path
, 0, TYPE_CODEC
);
2349 if (tracks
[track_widx
].codec_hid
< 0)
2351 logf("Not enough space");
2357 logf("Loaded codec");
2362 /* TODO: Copied from mpeg.c. Should be moved somewhere else. */
2363 static void audio_set_elapsed(struct mp3entry
* id3
)
2365 unsigned long offset
= id3
->offset
> id3
->first_frame_offset
?
2366 id3
->offset
- id3
->first_frame_offset
: 0;
2369 if ( id3
->has_toc
) {
2370 /* calculate elapsed time using TOC */
2372 unsigned int remainder
, plen
, relpos
, nextpos
;
2374 /* find wich percent we're at */
2375 for (i
=0; i
<100; i
++ )
2376 if ( offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
2383 relpos
= id3
->toc
[i
];
2386 nextpos
= id3
->toc
[i
+1];
2390 remainder
= offset
- (relpos
* (id3
->filesize
/ 256));
2392 /* set time for this percent (divide before multiply to prevent
2393 overflow on long files. loss of precision is negligible on
2395 id3
->elapsed
= i
* (id3
->length
/ 100);
2397 /* calculate remainder time */
2398 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
2399 id3
->elapsed
+= (((remainder
* 100) / plen
) *
2400 (id3
->length
/ 10000));
2403 /* no TOC exists. set a rough estimate using average bitrate */
2404 int tpk
= id3
->length
/
2405 ((id3
->filesize
- id3
->first_frame_offset
- id3
->id3v1len
) /
2407 id3
->elapsed
= offset
/ 1024 * tpk
;
2412 /* constant bitrate, use exact calculation */
2413 if (id3
->bitrate
!= 0)
2414 id3
->elapsed
= offset
/ (id3
->bitrate
/ 8);
2418 /* Load one track by making the appropriate bufopen calls. Return true if
2419 everything required was loaded correctly, false if not. */
2420 static bool audio_load_track(int offset
, bool start_play
, bool rebuffer
)
2426 int file_offset
= 0;
2427 struct mp3entry id3
;
2429 /* Stop buffer filling if there is no free track entries.
2430 Don't fill up the last track entry (we wan't to store next track
2432 if (!audio_have_free_tracks())
2434 logf("No free tracks");
2440 logf("Buffering track:%d/%d", track_widx
, track_ridx
);
2441 /* Get track name from current playlist read position. */
2442 while ((trackname
= playlist_peek(last_peek_offset
)) != NULL
)
2444 /* Handle broken playlists. */
2445 fd
= open(trackname
, O_RDONLY
);
2448 logf("Open failed");
2449 /* Skip invalid entry from playlist. */
2450 playlist_skip_entry(NULL
, last_peek_offset
);
2458 logf("End-of-playlist");
2459 playlist_end
= true;
2463 tracks
[track_widx
].filesize
= filesize(fd
);
2465 /* Set default values */
2468 int last_codec
= current_codec
;
2470 set_current_codec(CODEC_IDX_AUDIO
);
2471 conf_watermark
= AUDIO_DEFAULT_WATERMARK
;
2472 conf_filechunk
= AUDIO_DEFAULT_FILECHUNK
;
2473 conf_preseek
= AUDIO_REBUFFER_GUESS_SIZE
;
2474 dsp_configure(DSP_RESET
, 0);
2475 set_current_codec(last_codec
);
2477 track_changed
= true;
2478 playlist_update_resume_info(audio_current_track());
2481 /* Get track metadata if we don't already have it. */
2482 if (tracks
[track_widx
].id3_hid
<= 0)
2484 if (get_metadata(&id3
, fd
, trackname
))
2486 tracks
[track_widx
].id3_hid
= bufalloc(&id3
, sizeof(struct mp3entry
),
2488 tracks
[track_widx
].taginfo_ready
= (tracks
[track_widx
].id3_hid
> 0);
2490 if (tracks
[track_widx
].id3_hid
<= 0)
2492 DEBUGF("failed to allocate space for metadata\n");
2498 if (track_widx
== track_ridx
)
2499 copy_mp3entry(&curtrack_id3
, &id3
);
2500 else if (track_widx
== ((track_ridx
+ 1) & MAX_TRACK_MASK
))
2501 copy_mp3entry(&nexttrack_id3
, &id3
);
2505 track_changed
= true;
2506 playlist_update_resume_info(audio_current_track());
2511 logf("mde:%s!",trackname
);
2513 /* Skip invalid entry from playlist. */
2514 playlist_skip_entry(NULL
, last_peek_offset
);
2515 tracks
[track_widx
].taginfo_ready
= false;
2524 if (cuesheet_is_enabled() && tracks
[track_widx
].id3
.cuesheet_type
== 1)
2526 char cuepath
[MAX_PATH
];
2528 struct cuesheet
*cue
= start_play
? curr_cue
: temp_cue
;
2530 if (look_for_cuesheet_file(trackname
, cuepath
) &&
2531 parse_cuesheet(cuepath
, cue
))
2533 strcpy((cue
)->audio_filename
, trackname
);
2535 cue_spoof_id3(curr_cue
, &tracks
[track_widx
].id3
);
2540 /* Load the codec. */
2541 if (!audio_loadcodec(start_play
))
2543 if (tracks
[track_widx
].codecsize
)
2545 /* No space for codec on buffer, not an error */
2546 tracks
[track_widx
].codecsize
= 0;
2550 /* This is an error condition, either no codec was found, or reading
2551 * the codec file failed part way through, either way, skip the track */
2552 snprintf(msgbuf
, sizeof(msgbuf
)-1, "No codec for: %s", trackname
);
2553 /* We should not use gui_syncplash from audio thread! */
2554 gui_syncsplash(HZ
*2, msgbuf
);
2555 /* Skip invalid entry from playlist. */
2556 playlist_skip_entry(NULL
, last_peek_offset
);
2557 tracks
[track_widx
].taginfo_ready
= false;
2561 struct mp3entry
*track_id3
;
2563 if (track_widx
== track_ridx
)
2564 track_id3
= &curtrack_id3
;
2565 else if (track_widx
== ((track_ridx
+ 1) & MAX_TRACK_MASK
))
2566 track_id3
= &nexttrack_id3
;
2568 track_id3
= bufgetid3(tracks
[track_widx
].id3_hid
);
2570 set_filebuf_watermark(buffer_margin
);
2571 track_id3
->elapsed
= 0;
2575 switch (track_id3
->codectype
) {
2579 file_offset
= offset
;
2580 track_id3
->offset
= offset
;
2581 audio_set_elapsed(track_id3
);
2586 file_offset
= offset
;
2587 track_id3
->offset
= offset
;
2588 track_id3
->elapsed
= track_id3
->length
/ 2;
2592 case AFMT_OGG_VORBIS
:
2600 track_id3
->offset
= offset
;
2605 logf("alt:%s", trackname
);
2607 tracks
[track_widx
].audio_hid
= bufopen(trackname
, file_offset
, TYPE_AUDIO
);
2609 if (tracks
[track_widx
].audio_hid
<= 0)
2614 request_buffer_handle(tracks
[track_widx
].audio_hid
);
2618 track_widx
&= MAX_TRACK_MASK
;
2623 /* Send callback events to notify about new tracks. */
2624 static void audio_generate_postbuffer_events(void)
2629 logf("Postbuffer:%d/%d",track_ridx
,track_widx
);
2631 if (audio_have_tracks())
2633 cur_idx
= track_ridx
;
2636 if (!tracks
[cur_idx
].event_sent
)
2638 if (last_idx
>= 0 && !tracks
[last_idx
].event_sent
)
2640 /* Mark the event 'sent' even if we don't really send one */
2641 tracks
[last_idx
].event_sent
= true;
2642 if (track_buffer_callback
&& tracks
[last_idx
].id3_hid
> 0)
2643 track_buffer_callback(bufgetid3(tracks
[last_idx
].id3_hid
), false);
2647 if (cur_idx
== track_widx
)
2650 cur_idx
&= MAX_TRACK_MASK
;
2653 if (last_idx
>= 0 && !tracks
[last_idx
].event_sent
)
2655 tracks
[last_idx
].event_sent
= true;
2656 if (track_buffer_callback
&& tracks
[last_idx
].id3_hid
> 0)
2657 track_buffer_callback(bufgetid3(tracks
[last_idx
].id3_hid
), true);
2662 static bool audio_initialize_buffer_fill(bool clear_tracks
)
2664 /* Don't initialize if we're already initialized */
2668 logf("Starting buffer fill");
2670 /* Set the filling flag true before calling audio_clear_tracks as that
2671 * function can yield and we start looping. */
2675 audio_clear_track_entries(false);
2677 /* Save the current resume position once. */
2678 playlist_update_resume_info(audio_current_track());
2683 static void audio_fill_file_buffer(
2684 bool start_play
, bool rebuffer
, size_t offset
)
2686 bool had_next_track
= audio_next_track() != NULL
;
2687 bool continue_buffering
;
2689 /* Must reset the buffer before use if trashed or voice only - voice
2690 file size shouldn't have changed so we can go straight from
2691 BUFFER_STATE_VOICED_ONLY to BUFFER_STATE_INITIALIZED */
2692 if (buffer_state
!= BUFFER_STATE_INITIALIZED
)
2693 audio_reset_buffer();
2695 if (!audio_initialize_buffer_fill(!start_play
))
2698 continue_buffering
= audio_load_track(offset
, start_play
, rebuffer
);
2700 if (!had_next_track
&& audio_next_track())
2701 track_changed
= true;
2703 /* If we're done buffering */
2704 if (!continue_buffering
)
2706 //audio_read_next_metadata();
2708 audio_generate_postbuffer_events();
2713 static void audio_rebuffer(void)
2715 logf("Forcing rebuffer");
2717 clear_track_info(CUR_TI
);
2719 /* Reset track pointers */
2720 track_widx
= track_ridx
;
2721 audio_clear_track_entries(true);
2723 /* Just to make sure none were forgotten */
2724 audio_release_tracks();
2726 /* Fill the buffer */
2727 last_peek_offset
= -1;
2730 if (!CUR_TI
->taginfo_ready
)
2731 memset(&curtrack_id3
, 0, sizeof(struct mp3entry
));
2733 audio_fill_file_buffer(false, true, 0);
2736 static int audio_check_new_track(void)
2738 DEBUGF("audio_check_new_track\n");
2740 int track_count
= audio_track_count();
2741 int old_track_ridx
= track_ridx
;
2747 if (playlist_next_dir(ci
.new_track
))
2755 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2756 return Q_CODEC_REQUEST_FAILED
;
2763 /* If the playlist isn't that big */
2764 if (!playlist_check(ci
.new_track
))
2766 if (ci
.new_track
>= 0)
2768 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2769 return Q_CODEC_REQUEST_FAILED
;
2771 /* Find the beginning backward if the user over-skips it */
2772 while (!playlist_check(++ci
.new_track
))
2773 if (ci
.new_track
>= 0)
2775 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2776 return Q_CODEC_REQUEST_FAILED
;
2779 /* Update the playlist */
2780 last_peek_offset
-= ci
.new_track
;
2782 if (playlist_next(ci
.new_track
) < 0)
2784 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2785 return Q_CODEC_REQUEST_FAILED
;
2791 new_playlist
= false;
2794 /* Save the old track */
2795 /* prev_ti = CUR_TI; */
2799 for (i
= 0; i
< ci
.new_track
; i
++)
2801 idx
= (track_ridx
+ i
) & MAX_TRACK_MASK
;
2802 clear_track_info(&tracks
[idx
]);
2806 /* Move to the new track */
2807 track_ridx
+= ci
.new_track
;
2808 track_ridx
&= MAX_TRACK_MASK
;
2811 playlist_end
= false;
2813 track_changed
= !automatic_skip
;
2815 /* If it is not safe to even skip this many track entries */
2816 if (ci
.new_track
>= track_count
|| ci
.new_track
<= track_count
- MAX_TRACK
)
2823 forward
= ci
.new_track
> 0;
2826 /* If the target track is clearly not in memory */
2827 if (CUR_TI
->filesize
== 0 || !CUR_TI
->taginfo_ready
)
2833 /* The track may be in memory, see if it really is */
2836 int cur_idx
= track_ridx
;
2837 bool taginfo_ready
= true;
2838 bool wrap
= track_ridx
> old_track_ridx
;
2843 cur_idx
&= MAX_TRACK_MASK
;
2844 if (!(wrap
|| cur_idx
< old_track_ridx
))
2847 /* If we hit a track in between without valid tag info, bail */
2848 if (!tracks
[cur_idx
].taginfo_ready
)
2850 taginfo_ready
= false;
2861 audio_update_trackinfo();
2862 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
2863 return Q_CODEC_REQUEST_COMPLETE
;
2866 void audio_set_track_buffer_event(void (*handler
)(struct mp3entry
*id3
,
2869 track_buffer_callback
= handler
;
2872 void audio_set_track_unbuffer_event(void (*handler
)(struct mp3entry
*id3
,
2875 track_unbuffer_callback
= handler
;
2878 void audio_set_track_changed_event(void (*handler
)(struct mp3entry
*id3
))
2880 track_changed_callback
= handler
;
2883 unsigned long audio_prev_elapsed(void)
2885 return prev_track_elapsed
;
2888 static void audio_stop_codec_flush(void)
2890 ci
.stop_codec
= true;
2893 while (audio_codec_loaded
)
2896 /* If the audio codec is not loaded any more, and the audio is still
2897 * playing, it is now and _only_ now safe to call this function from the
2899 if (pcm_is_playing())
2901 pcmbuf_pause(paused
);
2904 static void audio_stop_playback(void)
2906 /* If we were playing, save resume information */
2909 struct mp3entry
*id3
= NULL
;
2911 if (!playlist_end
|| !ci
.stop_codec
)
2913 /* Set this early, the outside code yields and may allow the codec
2914 to try to wait for a reply on a buffer wait */
2915 ci
.stop_codec
= true;
2916 id3
= audio_current_track();
2919 /* Save the current playing spot, or NULL if the playlist has ended */
2920 playlist_update_resume_info(id3
);
2922 prev_track_elapsed
= curtrack_id3
.elapsed
;
2924 /* Increment index so runtime info is saved in audio_clear_track_entries().
2925 * Done here, as audio_stop_playback() may be called more than once.
2926 * Don't update runtime unless playback is stopped because of end of playlist.
2927 * Updating runtime when manually stopping a tracks, can destroy autoscores
2933 track_ridx
&= MAX_TRACK_MASK
;
2939 audio_stop_codec_flush();
2942 /* Close all tracks */
2943 audio_release_tracks();
2945 /* Mark all entries null. */
2946 audio_clear_track_entries(false);
2948 memset(&curtrack_id3
, 0, sizeof(struct mp3entry
));
2949 memset(&nexttrack_id3
, 0, sizeof(struct mp3entry
));
2952 static void audio_play_start(size_t offset
)
2954 #if INPUT_SRC_CAPS != 0
2955 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
2956 audio_set_output_source(AUDIO_SRC_PLAYBACK
);
2959 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2961 audio_stop_codec_flush();
2963 track_changed
= true;
2964 playlist_end
= false;
2972 sound_set_volume(global_settings
.volume
);
2973 track_widx
= track_ridx
= 0;
2975 /* Mark all entries null. */
2976 memset(tracks
, 0, sizeof(struct track_info
) * MAX_TRACK
);
2978 last_peek_offset
= -1;
2980 /* Officially playing */
2981 queue_reply(&audio_queue
, 1);
2983 audio_fill_file_buffer(true, false, offset
);
2985 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
2986 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
2990 /* Invalidates all but currently playing track. */
2991 static void audio_invalidate_tracks(void)
2993 if (audio_have_tracks())
2995 last_peek_offset
= 0;
2996 playlist_end
= false;
2997 track_widx
= track_ridx
;
2999 /* Mark all other entries null (also buffered wrong metadata). */
3000 audio_clear_track_entries(true);
3002 track_widx
= (track_widx
+ 1) & MAX_TRACK_MASK
;
3004 audio_fill_file_buffer(false, true, 0);
3008 static void audio_new_playlist(void)
3010 /* Prepare to start a new fill from the beginning of the playlist */
3011 last_peek_offset
= -1;
3012 if (audio_have_tracks())
3015 skipped_during_pause
= true;
3016 playlist_end
= false;
3017 track_widx
= track_ridx
;
3018 audio_clear_track_entries(true);
3021 track_widx
&= MAX_TRACK_MASK
;
3023 /* Mark the current track as invalid to prevent skipping back to it */
3024 CUR_TI
->taginfo_ready
= false;
3027 /* Signal the codec to initiate a track change forward */
3028 new_playlist
= true;
3031 /* Officially playing */
3032 queue_reply(&audio_queue
, 1);
3034 audio_fill_file_buffer(false, true, 0);
3037 static void audio_initiate_track_change(long direction
)
3039 playlist_end
= false;
3040 ci
.new_track
+= direction
;
3041 wps_offset
-= direction
;
3043 skipped_during_pause
= true;
3046 static void audio_initiate_dir_change(long direction
)
3048 playlist_end
= false;
3050 ci
.new_track
= direction
;
3052 skipped_during_pause
= true;
3056 * Layout audio buffer as follows - iram buffer depends on target:
3057 * [|SWAP:iram][|TALK]|MALLOC|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
3059 static void audio_reset_buffer(void)
3061 /* see audio_get_recording_buffer if this is modified */
3062 logf("audio_reset_buffer");
3064 /* If the setup of anything allocated before the file buffer is
3065 changed, do check the adjustments after the buffer_alloc call
3066 as it will likely be affected and need sliding over */
3068 /* Initially set up file buffer as all space available */
3069 malloc_buf
= audiobuf
+ talk_get_bufsize();
3070 /* Align the malloc buf to line size. Especially important to cf
3071 targets that do line reads/writes. */
3072 malloc_buf
= (unsigned char *)(((uintptr_t)malloc_buf
+ 15) & ~15);
3073 filebuf
= malloc_buf
+ MALLOC_BUFSIZE
; /* filebuf line align implied */
3074 filebuflen
= audiobufend
- filebuf
;
3076 /* Allow for codec swap space at end of audio buffer */
3077 if (talk_voice_required())
3079 /* Layout of swap buffer:
3080 * #ifdef IRAM_STEAL (dedicated iram_buf):
3081 * |iram_buf|...audiobuf...|dram_buf|audiobufend
3083 * audiobuf...|dram_buf|iram_buf|audiobufend
3085 #ifdef PLAYBACK_VOICE
3086 /* Check for an absolutely nasty situation which should never,
3087 ever happen - frankly should just panic */
3088 if (voice_codec_loaded
&& current_codec
!= CODEC_IDX_VOICE
)
3090 logf("buffer reset with voice swapped");
3092 /* line align length which line aligns the calculations below since
3093 all sizes are also at least line aligned - needed for memswap128 */
3096 filebuflen
-= CODEC_SIZE
;
3098 filebuflen
-= CODEC_SIZE
+ CODEC_IRAM_SIZE
;
3100 /* Allocate buffers for swapping voice <=> audio */
3101 /* If using IRAM for plugins voice IRAM swap buffer must be dedicated
3102 and out of the way of buffer usage or else a call to audio_get_buffer
3103 and subsequent buffer use might trash the swap space. A plugin
3104 initializing IRAM after getting the full buffer would present similar
3105 problem. Options include: failing the request if the other buffer
3106 has been obtained already or never allowing use of the voice IRAM
3107 buffer within the audio buffer. Using buffer_alloc basically
3108 implements the second in a more convenient way. */
3109 dram_buf
= filebuf
+ filebuflen
;
3112 /* Allocate voice IRAM swap buffer once */
3113 if (iram_buf
== NULL
)
3115 iram_buf
= buffer_alloc(CODEC_IRAM_SIZE
);
3116 /* buffer_alloc moves audiobuf; this is safe because only the end
3117 * has been touched so far in this function and the address of
3118 * filebuf + filebuflen is not changed */
3119 malloc_buf
+= CODEC_IRAM_SIZE
;
3120 filebuf
+= CODEC_IRAM_SIZE
;
3121 filebuflen
-= CODEC_IRAM_SIZE
;
3124 /* Allocate iram_buf after dram_buf */
3125 iram_buf
= dram_buf
+ CODEC_SIZE
;
3126 #endif /* IRAM_STEAL */
3127 #endif /* PLAYBACK_VOICE */
3131 #ifdef PLAYBACK_VOICE
3132 /* No swap buffers needed */
3138 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
3139 filebuflen
-= pcmbuf_init(filebuf
+ filebuflen
) + GUARD_BUFSIZE
;
3141 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
3142 will already be line aligned */
3145 /* Set the high watermark as 75% full...or 25% empty :) */
3147 high_watermark
= 3*filebuflen
/ 4;
3150 /* Clear any references to the file buffer */
3151 buffer_state
= BUFFER_STATE_INITIALIZED
;
3153 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
3154 /* Make sure everything adds up - yes, some info is a bit redundant but
3155 aids viewing and the sumation of certain variables should add up to
3156 the location of others. */
3159 unsigned char * pcmbuf
= pcmbuf_get_meminfo(&pcmbufsize
);
3160 logf("mabuf: %08X", (unsigned)malloc_buf
);
3161 logf("mabufe: %08X", (unsigned)(malloc_buf
+ MALLOC_BUFSIZE
));
3162 logf("fbuf: %08X", (unsigned)filebuf
);
3163 logf("fbufe: %08X", (unsigned)(filebuf
+ filebuflen
));
3164 logf("gbuf: %08X", (unsigned)(filebuf
+ filebuflen
));
3165 logf("gbufe: %08X", (unsigned)(filebuf
+ filebuflen
+ GUARD_BUFSIZE
));
3166 logf("pcmb: %08X", (unsigned)pcmbuf
);
3167 logf("pcmbe: %08X", (unsigned)(pcmbuf
+ pcmbufsize
));
3170 logf("dramb: %08X", (unsigned)dram_buf
);
3171 logf("drambe: %08X", (unsigned)(dram_buf
+ CODEC_SIZE
));
3175 logf("iramb: %08X", (unsigned)iram_buf
);
3176 logf("irambe: %08X", (unsigned)(iram_buf
+ CODEC_IRAM_SIZE
));
3183 /* we dont want this rebuffering on targets with little ram
3184 because the disk may never spin down */
3185 static bool ata_fillbuffer_callback(void)
3187 queue_post(&audio_queue
, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA
, 0);
3192 static void audio_thread(void)
3194 struct queue_event ev
;
3198 #ifdef PLAYBACK_VOICE
3199 /* Unlock semaphore that init stage locks before creating this thread */
3200 semaphore_release(&sem_codecthread
);
3202 /* Buffers must be set up by now - should panic - really */
3203 if (buffer_state
!= BUFFER_STATE_INITIALIZED
)
3205 logf("audio_thread start: no buffer");
3208 /* Have to wait for voice to load up or else the codec swap will be
3209 invalid when an audio codec is loaded */
3210 wait_for_voice_swap_in();
3215 queue_wait_w_tmo(&audio_queue
, &ev
, HZ
/2);
3219 if (ev
.id
== SYS_TIMEOUT
)
3220 ev
.id
= Q_AUDIO_FILL_BUFFER
;
3225 if (playing
&& (ev
.id
== SYS_TIMEOUT
) && !buffering
&&
3226 (bufused() < high_watermark
) && (audio_have_free_tracks()))
3227 register_ata_idle_func(ata_fillbuffer_callback
);
3233 case Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA
:
3234 /* only fill if the disk is still spining */
3236 if (!ata_disk_is_active())
3239 #endif /* MEM > 8 */
3240 /* else fall through to Q_AUDIO_FILL_BUFFER */
3241 case Q_AUDIO_FILL_BUFFER
:
3242 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER");
3244 if (!playing
|| playlist_end
|| ci
.stop_codec
)
3246 audio_fill_file_buffer(false, false, 0);
3250 LOGFQUEUE("audio < Q_AUDIO_PLAY");
3251 if (playing
&& ev
.data
<= 0)
3252 audio_new_playlist();
3255 audio_stop_playback();
3256 audio_play_start((size_t)ev
.data
);
3261 LOGFQUEUE("audio < Q_AUDIO_STOP");
3263 audio_stop_playback();
3265 queue_clear(&audio_queue
);
3269 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
3270 if (!(bool) ev
.data
&& skipped_during_pause
&& !pcmbuf_is_crossfade_active())
3271 pcmbuf_play_stop(); /* Flush old track on resume after skip */
3272 skipped_during_pause
= false;
3275 pcmbuf_pause((bool)ev
.data
);
3276 paused
= (bool)ev
.data
;
3280 LOGFQUEUE("audio < Q_AUDIO_SKIP");
3281 audio_initiate_track_change((long)ev
.data
);
3284 case Q_AUDIO_PRE_FF_REWIND
:
3285 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
3291 case Q_AUDIO_FF_REWIND
:
3292 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
3295 ci
.seek_time
= (long)ev
.data
+1;
3298 case Q_AUDIO_CHECK_NEW_TRACK
:
3299 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
3300 queue_reply(&audio_queue
, audio_check_new_track());
3303 case Q_AUDIO_DIR_SKIP
:
3304 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
3305 playlist_end
= false;
3306 audio_initiate_dir_change(ev
.data
);
3310 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
3311 audio_invalidate_tracks();
3314 case Q_AUDIO_TRACK_CHANGED
:
3315 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
3316 if (track_changed_callback
)
3317 track_changed_callback(&curtrack_id3
);
3318 track_changed
= true;
3319 playlist_update_resume_info(audio_current_track());
3323 case SYS_USB_CONNECTED
:
3324 LOGFQUEUE("audio < SYS_USB_CONNECTED");
3326 audio_stop_playback();
3327 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
3328 usb_wait_for_disconnect(&audio_queue
);
3333 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
3337 //LOGFQUEUE("audio < default");
3343 #ifdef ROCKBOX_HAS_LOGF
3344 static void audio_test_track_changed_event(struct mp3entry
*id3
)
3348 logf("tce:%s", id3
->path
);
3352 /* Initialize the audio system - called from init() in main.c.
3353 * Last function because of all the references to internal symbols
3355 void audio_init(void)
3357 #ifdef PLAYBACK_VOICE
3358 static bool voicetagtrue
= true;
3359 static struct mp3entry id3_voice
;
3360 struct thread_entry
*voice_thread_p
= NULL
;
3362 struct thread_entry
*audio_thread_p
;
3364 /* Can never do this twice */
3365 if (audio_is_initialized
)
3367 logf("audio: already initialized");
3371 logf("audio: initializing");
3373 /* Initialize queues before giving control elsewhere in case it likes
3374 to send messages. Thread creation will be delayed however so nothing
3375 starts running until ready if something yields such as talk_init. */
3376 #ifdef PLAYBACK_VOICE
3377 /* Take ownership of lock to prevent playback of anything before audio
3378 hardware is initialized - audio thread unlocks it after final init
3380 semaphore_init(&sem_codecthread
, 1, 0);
3381 event_init(&event_codecthread
, EVENT_MANUAL
| STATE_SIGNALED
);
3383 queue_init(&audio_queue
, true);
3384 queue_enable_queue_send(&audio_queue
, &audio_queue_sender_list
);
3385 queue_init(&codec_queue
, true);
3386 queue_enable_queue_send(&codec_queue
, &codec_queue_sender_list
);
3390 #ifdef ROCKBOX_HAS_LOGF
3391 audio_set_track_changed_event(audio_test_track_changed_event
);
3394 /* Initialize codec api. */
3395 ci
.read_filebuf
= codec_filebuf_callback
;
3396 ci
.pcmbuf_insert
= codec_pcmbuf_insert_callback
;
3397 ci
.get_codec_memory
= codec_get_memory_callback
;
3398 ci
.request_buffer
= codec_request_buffer_callback
;
3399 ci
.advance_buffer
= codec_advance_buffer_callback
;
3400 ci
.advance_buffer_loc
= codec_advance_buffer_loc_callback
;
3401 ci
.request_next_track
= codec_request_next_track_callback
;
3402 ci
.mp3_get_filepos
= codec_mp3_get_filepos_callback
;
3403 ci
.seek_buffer
= codec_seek_buffer_callback
;
3404 ci
.seek_complete
= codec_seek_complete_callback
;
3405 ci
.set_elapsed
= codec_set_elapsed_callback
;
3406 ci
.set_offset
= codec_set_offset_callback
;
3407 ci
.configure
= codec_configure_callback
;
3408 ci
.discard_codec
= codec_discard_codec_callback
;
3410 /* Initialize voice codec api. */
3411 #ifdef PLAYBACK_VOICE
3412 memcpy(&ci_voice
, &ci
, sizeof(ci_voice
));
3413 memset(&id3_voice
, 0, sizeof(id3_voice
));
3414 ci_voice
.read_filebuf
= voice_filebuf_callback
;
3415 ci_voice
.pcmbuf_insert
= voice_pcmbuf_insert_callback
;
3416 ci_voice
.get_codec_memory
= voice_get_memory_callback
;
3417 ci_voice
.request_buffer
= voice_request_buffer_callback
;
3418 ci_voice
.advance_buffer
= voice_advance_buffer_callback
;
3419 ci_voice
.advance_buffer_loc
= voice_advance_buffer_loc_callback
;
3420 ci_voice
.request_next_track
= voice_request_next_track_callback
;
3421 ci_voice
.mp3_get_filepos
= voice_mp3_get_filepos_callback
;
3422 ci_voice
.seek_buffer
= voice_seek_buffer_callback
;
3423 ci_voice
.seek_complete
= voice_do_nothing
;
3424 ci_voice
.set_elapsed
= voice_set_elapsed_callback
;
3425 ci_voice
.set_offset
= voice_set_offset_callback
;
3426 ci_voice
.configure
= voice_configure_callback
;
3427 ci_voice
.discard_codec
= voice_do_nothing
;
3428 ci_voice
.taginfo_ready
= &voicetagtrue
;
3429 ci_voice
.id3
= &id3_voice
;
3430 id3_voice
.frequency
= 11200;
3431 id3_voice
.length
= 1000000L;
3434 /* initialize the buffer */
3437 /* audio_reset_buffer must to know the size of voice buffer so init
3441 codec_thread_p
= create_thread(
3442 codec_thread
, codec_stack
, sizeof(codec_stack
),
3443 CREATE_THREAD_FROZEN
,
3444 codec_thread_name
IF_PRIO(, PRIORITY_PLAYBACK
)
3447 audio_thread_p
= create_thread(audio_thread
, audio_stack
,
3448 sizeof(audio_stack
), CREATE_THREAD_FROZEN
,
3449 audio_thread_name
IF_PRIO(, PRIORITY_BACKGROUND
)
3452 #ifdef PLAYBACK_VOICE
3453 /* TODO: Change this around when various speech codecs can be used */
3454 if (talk_voice_required())
3456 logf("Starting voice codec");
3457 queue_init(&voice_queue
, true);
3458 voice_thread_p
= create_thread(voice_thread
, voice_stack
,
3459 sizeof(voice_stack
), CREATE_THREAD_FROZEN
,
3461 IF_PRIO(, PRIORITY_PLAYBACK
) IF_COP(, CPU
));
3465 /* Set crossfade setting for next buffer init which should be about... */
3466 pcmbuf_crossfade_enable(global_settings
.crossfade
);
3468 /* ...now! Set up the buffers */
3469 audio_reset_buffer();
3471 buffering_init(filebuf
, filebuflen
);
3473 /* Probably safe to say */
3474 audio_is_initialized
= true;
3476 sound_settings_apply();
3478 eq_hw_enable(global_settings
.eq_hw_enabled
);
3480 #ifndef HAVE_FLASH_STORAGE
3481 audio_set_buffer_margin(global_settings
.buffer_margin
);
3484 /* it's safe to let the threads run now */
3485 thread_thaw(codec_thread_p
);
3486 #ifdef PLAYBACK_VOICE
3488 thread_thaw(voice_thread_p
);
3490 thread_thaw(audio_thread_p
);