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 ****************************************************************************/
29 #include "backlight.h"
39 #include "mp3_playback.h"
42 #include "main_menu.h"
48 #include "pcm_playback.h"
49 #include "pcm_record.h"
53 #ifdef HAVE_LCD_BITMAP
55 #include "peakmeter.h"
69 static volatile bool audio_codec_loaded
;
70 static volatile bool voice_codec_loaded
;
71 static volatile bool playing
;
72 static volatile bool paused
;
74 #define CODEC_VORBIS "/.rockbox/codecs/vorbis.codec"
75 #define CODEC_MPA_L3 "/.rockbox/codecs/mpa.codec"
76 #define CODEC_FLAC "/.rockbox/codecs/flac.codec"
77 #define CODEC_WAV "/.rockbox/codecs/wav.codec"
78 #define CODEC_A52 "/.rockbox/codecs/a52.codec"
79 #define CODEC_MPC "/.rockbox/codecs/mpc.codec"
80 #define CODEC_WAVPACK "/.rockbox/codecs/wavpack.codec"
81 #define CODEC_ALAC "/.rockbox/codecs/alac.codec"
82 #define CODEC_AAC "/.rockbox/codecs/aac.codec"
83 #define CODEC_SHN "/.rockbox/codecs/shorten.codec"
84 #define CODEC_AIFF "/.rockbox/codecs/aiff.codec"
86 #define AUDIO_DEFAULT_FIRST_LIMIT (1024*1024*10)
87 #define AUDIO_FILL_CYCLE (1024*256)
88 #define AUDIO_DEFAULT_WATERMARK (1024*512)
89 #define AUDIO_DEFAULT_FILECHUNK (1024*32)
102 Q_AUDIO_TRACK_CHANGED
,
105 Q_AUDIO_SEAMLESS_SEEK
,
112 /* As defined in plugins/lib/xxx2wav.h */
113 #define MALLOC_BUFSIZE (512*1024)
114 #define GUARD_BUFSIZE (32*1024)
116 /* As defined in plugin.lds */
117 #define CODEC_IRAM_ORIGIN 0x1000c000
118 #define CODEC_IRAM_SIZE 0xc000
120 extern bool audio_is_initialized
;
122 /* Buffer control thread. */
123 static struct event_queue audio_queue
;
124 static long audio_stack
[(DEFAULT_STACK_SIZE
+ 0x1000)/sizeof(long)];
125 static const char audio_thread_name
[] = "audio";
128 static struct event_queue codec_queue
;
129 static long codec_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)] IBSS_ATTR
;
130 static const char codec_thread_name
[] = "codec";
132 /* Voice codec thread. */
133 static struct event_queue voice_codec_queue
;
134 /* Not enough IRAM for this. */
135 static long voice_codec_stack
[(DEFAULT_STACK_SIZE
+ 0x2000)/sizeof(long)] IBSS_ATTR
;
136 static const char voice_codec_thread_name
[] = "voice codec";
138 static struct mutex mutex_bufferfill
;
139 static struct mutex mutex_codecthread
;
141 static struct mp3entry id3_voice
;
143 static char *voicebuf
;
144 static int voice_remaining
;
145 static bool voice_is_playing
;
146 static void (*voice_getmore
)(unsigned char** start
, int* size
);
148 /* Is file buffer currently being refilled? */
149 static volatile bool filling
;
151 volatile int current_codec
;
152 extern unsigned char codecbuf
[];
154 /* Ring buffer where tracks and codecs are loaded. */
155 static char *filebuf
;
157 /* Total size of the ring buffer. */
160 /* Bytes available in the buffer. */
163 /* Ring buffer read and write indexes. */
164 static volatile int buf_ridx
;
165 static volatile int buf_widx
;
167 /* Step count to the next unbuffered track. */
168 static int last_peek_offset
;
170 /* Track information (count in file buffer, read/write indexes for
171 track ring structure. */
173 static volatile int track_ridx
;
174 static volatile int track_widx
;
175 static bool track_changed
;
177 /* Partially loaded song's file handle to continue buffering later. */
178 static int current_fd
;
180 /* Information about how many bytes left on the buffer re-fill run. */
181 static long fill_bytesleft
;
183 /* Track info structure about songs in the file buffer. */
184 static struct track_info tracks
[MAX_TRACK
];
186 /* Pointer to track info structure about current song playing. */
187 static struct track_info
*cur_ti
;
188 static struct track_info
*prev_ti
;
190 /* Have we reached end of the current playlist. */
191 static bool playlist_end
= false;
193 /* Codec API including function callbacks. */
194 extern struct codec_api ci
;
195 extern struct codec_api ci_voice
;
197 /* When we change a song and buffer is not in filling state, this
198 variable keeps information about whether to go a next/previous track. */
199 static int new_track
;
201 /* Callback function to call when current track has really changed. */
202 void (*track_changed_callback
)(struct mp3entry
*id3
);
203 void (*track_buffer_callback
)(struct mp3entry
*id3
, bool last_track
);
204 void (*track_unbuffer_callback
)(struct mp3entry
*id3
, bool last_track
);
206 static void playback_init(void);
209 static int conf_bufferlimit
;
210 static int conf_watermark
;
211 static int conf_filechunk
;
212 static int buffer_margin
;
214 static bool v1first
= false;
216 static void mp3_set_elapsed(struct mp3entry
* id3
);
217 int mp3_get_file_pos(void);
220 bool is_filling(void)
226 static void do_swap(int idx_old
, int idx_new
)
229 unsigned char *iram_p
= (unsigned char *)(CODEC_IRAM_ORIGIN
);
230 unsigned char *iram_buf
[2];
232 unsigned char *dram_buf
[2];
236 iram_buf
[0] = &filebuf
[filebuflen
];
237 iram_buf
[1] = &filebuf
[filebuflen
+CODEC_IRAM_SIZE
];
238 memcpy(iram_buf
[idx_old
], iram_p
, CODEC_IRAM_SIZE
);
239 memcpy(iram_p
, iram_buf
[idx_new
], CODEC_IRAM_SIZE
);
242 dram_buf
[0] = (unsigned char *)&filebuf
[filebuflen
+CODEC_IRAM_SIZE
*2];
243 dram_buf
[1] = (unsigned char *)&filebuf
[filebuflen
+CODEC_IRAM_SIZE
*2+CODEC_SIZE
];
244 memcpy(dram_buf
[idx_old
], codecbuf
, CODEC_SIZE
);
245 memcpy(codecbuf
, dram_buf
[idx_new
], CODEC_SIZE
);
248 static void swap_codec(void)
252 logf("swapping codec:%d", current_codec
);
254 /* We should swap codecs' IRAM contents and code space. */
255 do_swap(current_codec
, !current_codec
);
257 last_codec
= current_codec
;
258 current_codec
= !current_codec
;
260 /* Release the semaphore and force a task switch. */
261 mutex_unlock(&mutex_codecthread
);
264 /* Waiting until we are ready to run again. */
265 mutex_lock(&mutex_codecthread
);
267 /* Check if codec swap did not happen. */
268 if (current_codec
!= last_codec
)
270 logf("no codec switch happened!");
271 do_swap(current_codec
, !current_codec
);
272 current_codec
= !current_codec
;
276 logf("codec resuming:%d", current_codec
);
279 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
280 static void voice_boost_cpu(bool state
)
282 static bool voice_cpu_boosted
= false;
284 if (!voice_codec_loaded
)
287 if (state
!= voice_cpu_boosted
)
290 voice_cpu_boosted
= state
;
294 #define voice_boost_cpu(state) do { } while(0)
297 bool codec_pcmbuf_insert_split_callback(const void *ch1
, const void *ch2
,
311 if (ci
.stop_codec
|| ci
.reload_codec
|| ci
.seek_time
)
315 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED
)
317 length
*= 2; /* Length is per channel */
321 long est_output_size
= dsp_output_size(length
);
322 /* This will prevent old audio from playing when skipping tracks. */
323 if (current_codec
== CODEC_IDX_VOICE
) {
324 while ((dest
= pcmbuf_request_voice_buffer(est_output_size
,
325 &output_size
, audio_codec_loaded
)) == NULL
)
330 if (ci
.reload_codec
|| ci
.stop_codec
)
333 while ((dest
= pcmbuf_request_buffer(est_output_size
,
334 &output_size
)) == NULL
) {
336 if (ci
.reload_codec
|| ci
.stop_codec
)
341 /* Get the real input_size for output_size bytes, guarding
342 * against resampling buffer overflows. */
343 input_size
= dsp_input_size(output_size
);
345 if (input_size
<= 0) {
346 DEBUGF("Warning: dsp_input_size(%ld=dsp_output_size(%ld))=%ld <= 0\n",
347 output_size
, length
, input_size
);
348 /* this cannot happen */
352 if ((size_t)input_size
> length
) {
353 DEBUGF("Error: dsp_input_size(%ld=dsp_output_size(%ld))=%ld > %ld\n",
354 output_size
, length
, input_size
, length
);
358 output_size
= dsp_process(dest
, src
, input_size
);
360 /* Hotswap between audio and voice codecs as necessary. */
361 switch (current_codec
)
363 case CODEC_IDX_AUDIO
:
364 pcmbuf_write_complete(output_size
);
365 if (voice_is_playing
&& pcmbuf_usage() > 30
366 && pcmbuf_mix_usage() < 20)
368 voice_boost_cpu(true);
370 voice_boost_cpu(false);
374 case CODEC_IDX_VOICE
:
375 if (audio_codec_loaded
) {
376 pcmbuf_mix(dest
, output_size
);
377 if ((pcmbuf_usage() < 10)
378 || pcmbuf_mix_usage() > 70)
381 pcmbuf_write_complete(output_size
);
386 length
-= input_size
;
392 bool codec_pcmbuf_insert_callback(const char *buf
, size_t length
)
394 /* TODO: The audiobuffer API should probably be updated, and be based on
395 * pcmbuf_insert_split().
397 long real_length
= length
;
399 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED
)
401 length
/= 2; /* Length is per channel */
404 /* Second channel is only used for non-interleaved stereo. */
405 return codec_pcmbuf_insert_split_callback(buf
, buf
+ (real_length
/ 2),
409 void* get_codec_memory_callback(long *size
)
411 *size
= MALLOC_BUFSIZE
;
412 if (voice_codec_loaded
)
413 return &audiobuf
[talk_get_bufsize()];
418 static void pcmbuf_position_callback(size_t size
) ICODE_ATTR
;
419 static void pcmbuf_position_callback(size_t size
) {
420 unsigned int time
= size
* 1000 / 4 / NATIVE_FREQUENCY
+
421 prev_ti
->id3
.elapsed
;
422 if (time
>= prev_ti
->id3
.length
) {
423 pcmbuf_set_position_callback(NULL
);
424 prev_ti
->id3
.elapsed
= prev_ti
->id3
.length
;
426 prev_ti
->id3
.elapsed
= time
;
430 void codec_set_elapsed_callback(unsigned int value
)
432 unsigned int latency
;
434 if (ci
.stop_codec
|| current_codec
== CODEC_IDX_VOICE
)
437 #ifdef AB_REPEAT_ENABLE
438 ab_position_report(value
);
440 latency
= pcmbuf_get_latency();
442 if (value
< latency
) {
443 cur_ti
->id3
.elapsed
= 0;
444 } else if (value
- latency
> cur_ti
->id3
.elapsed
445 || value
- latency
< cur_ti
->id3
.elapsed
- 2) {
446 cur_ti
->id3
.elapsed
= value
- latency
;
450 void codec_set_offset_callback(unsigned int value
)
452 unsigned int latency
;
454 if (ci
.stop_codec
|| current_codec
== CODEC_IDX_VOICE
)
457 latency
= pcmbuf_get_latency() * cur_ti
->id3
.bitrate
/ 8;
459 if (value
< latency
) {
460 cur_ti
->id3
.offset
= 0;
462 cur_ti
->id3
.offset
= value
- latency
;
466 long codec_filebuf_callback(void *ptr
, long size
)
468 char *buf
= (char *)ptr
;
472 if (ci
.stop_codec
|| !playing
|| current_codec
== CODEC_IDX_VOICE
)
475 copy_n
= MIN((off_t
)size
, (off_t
)cur_ti
->available
+ cur_ti
->filerem
);
477 while (copy_n
> cur_ti
->available
) {
479 if (ci
.stop_codec
|| ci
.reload_codec
)
486 part_n
= MIN(copy_n
, filebuflen
- buf_ridx
);
487 memcpy(buf
, &filebuf
[buf_ridx
], part_n
);
488 if (part_n
< copy_n
) {
489 memcpy(&buf
[part_n
], &filebuf
[0], copy_n
- part_n
);
493 if (buf_ridx
>= filebuflen
)
494 buf_ridx
-= filebuflen
;
496 cur_ti
->available
-= copy_n
;
497 filebufused
-= copy_n
;
502 void* voice_request_data(long *realsize
, long reqsize
)
504 while (queue_empty(&voice_codec_queue
) && (voice_remaining
== 0
505 || voicebuf
== NULL
) && !ci_voice
.stop_codec
)
508 if (audio_codec_loaded
&& (pcmbuf_usage() < 30
509 || !voice_is_playing
|| voicebuf
== NULL
))
513 else if (!voice_is_playing
)
515 voice_boost_cpu(false);
516 if (!pcm_is_playing())
523 voice_is_playing
= true;
527 if (voice_getmore
!= NULL
)
529 voice_getmore((unsigned char **)&voicebuf
, (int *)&voice_remaining
);
531 if (!voice_remaining
)
533 voice_is_playing
= false;
534 /* Force pcm playback. */
543 voice_is_playing
= true;
544 *realsize
= voice_remaining
;
545 if (*realsize
> reqsize
)
554 void* codec_request_buffer_callback(long *realsize
, long reqsize
)
559 if (current_codec
== CODEC_IDX_VOICE
) {
560 return voice_request_data(realsize
, reqsize
);
563 if (ci
.stop_codec
|| !playing
) {
568 *realsize
= MIN((off_t
)reqsize
, (off_t
)cur_ti
->available
+ cur_ti
->filerem
);
569 if (*realsize
== 0) {
573 while ((int)*realsize
> cur_ti
->available
) {
575 if (ci
.stop_codec
|| ci
.reload_codec
) {
581 part_n
= MIN((int)*realsize
, filebuflen
- buf_ridx
);
582 if (part_n
< *realsize
) {
583 part_n
+= GUARD_BUFSIZE
;
584 if (part_n
< *realsize
)
586 memcpy(&filebuf
[filebuflen
], &filebuf
[0], *realsize
-
587 (filebuflen
- buf_ridx
));
590 return (char *)&filebuf
[buf_ridx
];
593 static bool rebuffer_and_seek(int newpos
)
597 logf("Re-buffering song");
598 mutex_lock(&mutex_bufferfill
);
600 /* (Re-)open current track's file handle. */
601 fd
= open(playlist_peek(0), O_RDONLY
);
603 logf("Open failed!");
604 mutex_unlock(&mutex_bufferfill
);
611 /* Clear codec buffer. */
612 audio_invalidate_tracks();
614 playlist_end
= false;
615 buf_ridx
= buf_widx
= 0;
616 cur_ti
->filerem
= cur_ti
->filesize
- newpos
;
617 cur_ti
->filepos
= newpos
;
618 cur_ti
->start_pos
= newpos
;
620 cur_ti
->available
= 0;
621 lseek(current_fd
, newpos
, SEEK_SET
);
623 mutex_unlock(&mutex_bufferfill
);
625 while (cur_ti
->available
== 0 && cur_ti
->filerem
> 0) {
627 if (ci
.stop_codec
|| ci
.reload_codec
|| !queue_empty(&audio_queue
))
634 void codec_advance_buffer_callback(long amount
)
636 if (current_codec
== CODEC_IDX_VOICE
) {
637 //logf("voice ad.buf:%d", amount);
638 amount
= MAX(0, MIN(amount
, voice_remaining
));
640 voice_remaining
-= amount
;
645 if (amount
> cur_ti
->available
+ cur_ti
->filerem
)
646 amount
= cur_ti
->available
+ cur_ti
->filerem
;
648 while (amount
> cur_ti
->available
&& filling
)
651 if (amount
> cur_ti
->available
) {
652 if (!rebuffer_and_seek(ci
.curpos
+ amount
))
653 ci
.stop_codec
= true;
658 if (buf_ridx
>= filebuflen
)
659 buf_ridx
-= filebuflen
;
660 cur_ti
->available
-= amount
;
661 filebufused
-= amount
;
663 codec_set_offset_callback(ci
.curpos
);
666 void codec_advance_buffer_loc_callback(void *ptr
)
670 if (current_codec
== CODEC_IDX_VOICE
)
671 amount
= (int)ptr
- (int)voicebuf
;
673 amount
= (int)ptr
- (int)&filebuf
[buf_ridx
];
674 codec_advance_buffer_callback(amount
);
677 off_t
codec_mp3_get_filepos_callback(int newtime
)
681 cur_ti
->id3
.elapsed
= newtime
;
682 newpos
= mp3_get_file_pos();
687 void codec_seek_complete_callback(void)
689 /* assume we're called from non-voice codec, as they shouldn't seek */
693 bool codec_seek_buffer_callback(off_t newpos
)
697 if (current_codec
== CODEC_IDX_VOICE
)
703 if (newpos
>= cur_ti
->filesize
)
704 newpos
= cur_ti
->filesize
- 1;
706 difference
= newpos
- ci
.curpos
;
707 /* Seeking forward */
708 if (difference
>= 0) {
709 logf("seek: +%d", difference
);
710 codec_advance_buffer_callback(difference
);
714 /* Seeking backward */
715 difference
= -difference
;
716 if (ci
.curpos
- difference
< 0)
717 difference
= ci
.curpos
;
719 /* We need to reload the song. */
720 if (newpos
< cur_ti
->start_pos
)
721 return rebuffer_and_seek(newpos
);
723 /* Seeking inside buffer space. */
724 logf("seek: -%d", difference
);
725 filebufused
+= difference
;
726 cur_ti
->available
+= difference
;
727 buf_ridx
-= difference
;
729 buf_ridx
= filebuflen
+ buf_ridx
;
730 ci
.curpos
-= difference
;
735 static void set_filebuf_watermark(int seconds
)
739 if (current_codec
== CODEC_IDX_VOICE
)
743 return; /* Audio buffers not yet set up */
745 bytes
= MAX((int)cur_ti
->id3
.bitrate
* seconds
* (1000/8), conf_watermark
);
746 bytes
= MIN(bytes
, filebuflen
/ 2);
747 conf_watermark
= bytes
;
750 static void codec_configure_callback(int setting
, void *value
)
753 case CODEC_SET_FILEBUF_WATERMARK
:
754 conf_watermark
= (unsigned int)value
;
755 set_filebuf_watermark(buffer_margin
);
758 case CODEC_SET_FILEBUF_CHUNKSIZE
:
759 conf_filechunk
= (unsigned int)value
;
762 case CODEC_DSP_ENABLE
:
764 ci
.pcmbuf_insert
= codec_pcmbuf_insert_callback
;
766 ci
.pcmbuf_insert
= pcmbuf_insert_buffer
;
770 if (!dsp_configure(setting
, value
)) {
771 logf("Illegal key: %d", setting
);
776 void audio_set_track_buffer_event(void (*handler
)(struct mp3entry
*id3
,
779 track_buffer_callback
= handler
;
782 void audio_set_track_unbuffer_event(void (*handler
)(struct mp3entry
*id3
,
785 track_unbuffer_callback
= handler
;
788 void audio_set_track_changed_event(void (*handler
)(struct mp3entry
*id3
))
790 track_changed_callback
= handler
;
793 static void codec_track_changed(void)
795 track_changed
= true;
796 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
799 static void pcmbuf_track_changed_callback(void)
801 track_changed
= true;
802 pcmbuf_set_position_callback(NULL
);
803 queue_post(&audio_queue
, Q_AUDIO_TRACK_CHANGED
, 0);
806 /* Give codecs or file buffering the right amount of processing time
807 to prevent pcm audio buffer from going empty. */
808 static void yield_codecs(void)
811 if (!pcm_is_playing() && !paused
)
813 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
814 && !ci
.stop_codec
&& playing
&& queue_empty(&audio_queue
)
815 && filebufused
> (128*1024))
819 /* FIXME: This code should be made more generic and move to metadata.c */
820 void strip_id3v1_tag(void)
823 static const unsigned char tag
[] = "TAG";
827 if (filebufused
>= 128)
829 tagptr
= buf_widx
- 128;
831 tagptr
+= filebuflen
;
835 if(tagptr
>= filebuflen
)
836 tagptr
-= filebuflen
;
838 if(filebuf
[tagptr
] != tag
[i
])
850 logf("Skipping ID3v1 tag\n");
852 tracks
[track_widx
].available
-= 128;
858 static void audio_fill_file_buffer(void)
866 /* Throw away buffered codec. */
867 if (tracks
[track_widx
].start_pos
!= 0)
868 tracks
[track_widx
].codecsize
= 0;
870 mutex_lock(&mutex_bufferfill
);
872 size
= MIN(tracks
[track_widx
].filerem
, AUDIO_FILL_CYCLE
);
874 /* Give codecs some processing time. */
877 if (fill_bytesleft
== 0)
879 rc
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
880 rc
= MIN(rc
, fill_bytesleft
);
881 rc
= read(current_fd
, &filebuf
[buf_widx
], rc
);
883 tracks
[track_widx
].filerem
= 0;
888 if (buf_widx
>= filebuflen
)
889 buf_widx
-= filebuflen
;
891 tracks
[track_widx
].available
+= rc
;
892 tracks
[track_widx
].filerem
-= rc
;
893 tracks
[track_widx
].filepos
+= rc
;
895 fill_bytesleft
-= rc
;
898 if (tracks
[track_widx
].filerem
== 0) {
902 mutex_unlock(&mutex_bufferfill
);
904 /*logf("Filled:%d/%d", tracks[track_widx].available,
905 tracks[track_widx].filerem);*/
908 static int get_codec_base_type(int type
)
920 static bool loadcodec(bool start_play
)
925 const char *codec_path
;
929 switch (tracks
[track_widx
].id3
.codectype
) {
930 case AFMT_OGG_VORBIS
:
931 logf("Codec: Vorbis");
932 codec_path
= CODEC_VORBIS
;
937 logf("Codec: MPA L1/L2/L3");
938 codec_path
= CODEC_MPA_L3
;
941 logf("Codec: PCM WAV");
942 codec_path
= CODEC_WAV
;
946 codec_path
= CODEC_FLAC
;
950 codec_path
= CODEC_A52
;
953 logf("Codec: Musepack");
954 codec_path
= CODEC_MPC
;
957 logf("Codec: WAVPACK");
958 codec_path
= CODEC_WAVPACK
;
962 codec_path
= CODEC_ALAC
;
966 codec_path
= CODEC_AAC
;
970 codec_path
= CODEC_SHN
;
973 logf("Codec: PCM AIFF");
974 codec_path
= CODEC_AIFF
;
977 logf("Codec: Unsupported");
982 tracks
[track_widx
].codecsize
= 0;
985 prev_track
= track_widx
- 1;
987 prev_track
= MAX_TRACK
-1;
988 if (track_count
> 0 &&
989 get_codec_base_type(tracks
[track_widx
].id3
.codectype
) ==
990 get_codec_base_type(tracks
[prev_track
].id3
.codectype
))
992 logf("Reusing prev. codec");
996 /* Load the codec directly from disk and save some memory. */
997 cur_ti
= &tracks
[track_widx
];
998 ci
.filesize
= cur_ti
->filesize
;
999 ci
.id3
= (struct mp3entry
*)&cur_ti
->id3
;
1000 ci
.taginfo_ready
= (bool *)&cur_ti
->taginfo_ready
;
1003 logf("Starting codec");
1004 queue_post(&codec_queue
, Q_CODEC_LOAD_DISK
, (void *)codec_path
);
1008 fd
= open(codec_path
, O_RDONLY
);
1010 logf("Codec doesn't exist!");
1014 size
= filesize(fd
);
1015 if ((off_t
)fill_bytesleft
< size
+ conf_watermark
) {
1016 logf("Not enough space");
1017 /* Set codectype back to zero to indicate no codec was loaded. */
1018 tracks
[track_widx
].id3
.codectype
= 0;
1028 copy_n
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
1029 rc
= read(fd
, &filebuf
[buf_widx
], copy_n
);
1034 fill_bytesleft
-= rc
;
1035 if (buf_widx
>= filebuflen
)
1036 buf_widx
-= filebuflen
;
1040 logf("Done: %dB", i
);
1042 tracks
[track_widx
].codecsize
= size
;
1047 static bool read_next_metadata(void)
1054 next_track
= track_widx
;
1055 if (tracks
[track_widx
].taginfo_ready
)
1058 if (next_track
>= MAX_TRACK
)
1059 next_track
-= MAX_TRACK
;
1061 if (tracks
[next_track
].taginfo_ready
)
1064 trackname
= playlist_peek(last_peek_offset
+ 1);
1068 fd
= open(trackname
, O_RDONLY
);
1072 /** Start buffer refilling also because we need to spin-up the disk.
1073 * In fact, it might be better not to start filling here, because if user
1074 * is manipulating the playlist a lot, we will just lose battery. */
1076 status
= get_metadata(&tracks
[next_track
],fd
,trackname
,v1first
);
1077 /* Preload the glyphs in the tags */
1079 if (tracks
[next_track
].id3
.title
)
1080 lcd_getstringsize(tracks
[next_track
].id3
.title
, NULL
, NULL
);
1081 if (tracks
[next_track
].id3
.artist
)
1082 lcd_getstringsize(tracks
[next_track
].id3
.artist
, NULL
, NULL
);
1083 if (tracks
[next_track
].id3
.album
)
1084 lcd_getstringsize(tracks
[next_track
].id3
.album
, NULL
, NULL
);
1086 track_changed
= true;
1092 static bool audio_load_track(int offset
, bool start_play
, int peek_offset
)
1101 /* Stop buffer filling if there is no free track entries.
1102 Don't fill up the last track entry (we wan't to store next track
1104 if (track_count
>= MAX_TRACK
- 1) {
1109 /* Don't start loading track if the current write position already
1110 contains a BUFFERED track. The entry may contain the metadata
1112 if (tracks
[track_widx
].filesize
!= 0)
1116 /* Get track name from current playlist read position. */
1117 logf("Buffering track:%d/%d", track_widx
, track_ridx
);
1118 /* Handle broken playlists. */
1119 while ( (trackname
= playlist_peek(peek_offset
)) != NULL
) {
1120 fd
= open(trackname
, O_RDONLY
);
1122 logf("Open failed");
1123 /* Skip invalid entry from playlist. */
1124 playlist_skip_entry(NULL
, peek_offset
);
1131 logf("End-of-playlist");
1132 playlist_end
= true;
1136 /* Initialize track entry. */
1137 size
= filesize(fd
);
1138 tracks
[track_widx
].filerem
= size
;
1139 tracks
[track_widx
].filesize
= size
;
1140 tracks
[track_widx
].filepos
= 0;
1141 tracks
[track_widx
].available
= 0;
1142 //tracks[track_widx].taginfo_ready = false;
1143 tracks
[track_widx
].playlist_offset
= peek_offset
;
1144 last_peek_offset
= peek_offset
;
1146 if (buf_widx
>= filebuflen
)
1147 buf_widx
-= filebuflen
;
1149 /* Set default values */
1151 int last_codec
= current_codec
;
1152 current_codec
= CODEC_IDX_AUDIO
;
1153 conf_bufferlimit
= AUDIO_DEFAULT_FIRST_LIMIT
;
1154 conf_watermark
= AUDIO_DEFAULT_WATERMARK
;
1155 conf_filechunk
= AUDIO_DEFAULT_FILECHUNK
;
1156 dsp_configure(DSP_RESET
, 0);
1157 ci
.configure(CODEC_DSP_ENABLE
, false);
1158 current_codec
= last_codec
;
1161 /* Get track metadata if we don't already have it. */
1162 if (!tracks
[track_widx
].taginfo_ready
) {
1163 if (!get_metadata(&tracks
[track_widx
],fd
,trackname
,v1first
)) {
1164 logf("Metadata error!");
1165 tracks
[track_widx
].filesize
= 0;
1166 tracks
[track_widx
].filerem
= 0;
1167 tracks
[track_widx
].taginfo_ready
= false;
1169 /* Skip invalid entry from playlist. */
1170 playlist_skip_entry(NULL
, peek_offset
);
1175 /* Load the codec. */
1176 tracks
[track_widx
].codecbuf
= &filebuf
[buf_widx
];
1177 if (!loadcodec(start_play
)) {
1178 /* We should not use gui_syncplash from audio thread! */
1179 snprintf(msgbuf
, sizeof(msgbuf
)-1, "No codec for: %s", trackname
);
1180 gui_syncsplash(HZ
*2, true, msgbuf
);
1183 /* Set filesize to zero to indicate no file was loaded. */
1184 tracks
[track_widx
].filesize
= 0;
1185 tracks
[track_widx
].filerem
= 0;
1186 tracks
[track_widx
].taginfo_ready
= false;
1188 /* Try skipping to next track. */
1189 if (fill_bytesleft
> 0) {
1190 /* Skip invalid entry from playlist. */
1191 playlist_skip_entry(NULL
, peek_offset
);
1197 tracks
[track_widx
].start_pos
= 0;
1198 set_filebuf_watermark(buffer_margin
);
1199 tracks
[track_widx
].id3
.elapsed
= 0;
1201 /* Starting playback from an offset is only support in MPA at the moment */
1203 switch (tracks
[track_widx
].id3
.codectype
) {
1206 lseek(fd
, offset
, SEEK_SET
);
1207 tracks
[track_widx
].id3
.offset
= offset
;
1208 mp3_set_elapsed(&tracks
[track_widx
].id3
);
1209 tracks
[track_widx
].filepos
= offset
;
1210 tracks
[track_widx
].filerem
= tracks
[track_widx
].filesize
- offset
;
1212 tracks
[track_widx
].start_pos
= offset
;
1216 lseek(fd
, offset
, SEEK_SET
);
1217 tracks
[track_widx
].id3
.offset
= offset
;
1218 tracks
[track_widx
].id3
.elapsed
= tracks
[track_widx
].id3
.length
/ 2;
1219 tracks
[track_widx
].filepos
= offset
;
1220 tracks
[track_widx
].filerem
= tracks
[track_widx
].filesize
- offset
;
1222 tracks
[track_widx
].start_pos
= offset
;
1224 case AFMT_OGG_VORBIS
:
1226 tracks
[track_widx
].id3
.offset
= offset
;
1233 codec_track_changed();
1236 /* Do some initial file buffering. */
1237 mutex_lock(&mutex_bufferfill
);
1238 i
= tracks
[track_widx
].start_pos
;
1239 size
= MIN(size
, AUDIO_FILL_CYCLE
);
1241 /* Give codecs some processing time to prevent glitches. */
1244 if (fill_bytesleft
== 0)
1247 copy_n
= MIN(conf_filechunk
, filebuflen
- buf_widx
);
1248 copy_n
= MIN(size
- i
, copy_n
);
1249 copy_n
= MIN((int)fill_bytesleft
, copy_n
);
1250 rc
= read(fd
, &filebuf
[buf_widx
], copy_n
);
1252 logf("File error!");
1253 tracks
[track_widx
].filesize
= 0;
1254 tracks
[track_widx
].filerem
= 0;
1256 mutex_unlock(&mutex_bufferfill
);
1260 if (buf_widx
>= filebuflen
)
1261 buf_widx
-= filebuflen
;
1263 tracks
[track_widx
].available
+= rc
;
1264 tracks
[track_widx
].filerem
-= rc
;
1266 fill_bytesleft
-= rc
;
1268 mutex_unlock(&mutex_bufferfill
);
1273 tracks
[track_widx
].filepos
= i
;
1275 if (current_fd
>= 0) {
1280 /* Leave the file handle open for faster buffer refill. */
1281 if (tracks
[track_widx
].filerem
!= 0) {
1283 logf("Partially buf:%d", tracks
[track_widx
].available
);
1285 logf("Completely buf.");
1290 if (++track_widx
>= MAX_TRACK
) {
1293 tracks
[track_widx
].filerem
= 0;
1299 static void audio_clear_track_entries(bool buffered_only
)
1301 int cur_idx
, event_count
;
1304 cur_idx
= track_widx
;
1306 for (i
= 0; i
< MAX_TRACK
- track_count
; i
++) {
1307 if (++cur_idx
>= MAX_TRACK
)
1310 if (tracks
[cur_idx
].event_sent
)
1313 if (!track_unbuffer_callback
)
1314 memset(&tracks
[cur_idx
], 0, sizeof(struct track_info
));
1317 if (!track_unbuffer_callback
)
1320 cur_idx
= track_widx
;
1321 for (i
= 0; i
< MAX_TRACK
- track_count
; i
++) {
1322 if (++cur_idx
>= MAX_TRACK
)
1325 /* Send an event to notify that track has finished. */
1326 if (tracks
[cur_idx
].event_sent
) {
1328 track_unbuffer_callback(&tracks
[cur_idx
].id3
, event_count
== 0);
1331 if (tracks
[cur_idx
].event_sent
|| !buffered_only
)
1332 memset(&tracks
[cur_idx
], 0, sizeof(struct track_info
));
1336 static void stop_codec_flush(void)
1338 ci
.stop_codec
= true;
1340 while (audio_codec_loaded
)
1345 static void audio_stop_playback(bool resume
)
1347 logf("stop_playback:%d", resume
);
1350 playlist_update_resume_info(resume
? audio_current_track() : NULL
);
1354 if (current_fd
>= 0) {
1360 /* Mark all entries null. */
1361 audio_clear_track_entries(false);
1364 static void audio_play_start(int offset
)
1366 if (current_fd
>= 0) {
1371 memset(&tracks
, 0, sizeof(struct track_info
) * MAX_TRACK
);
1372 sound_set_volume(global_settings
.volume
);
1379 pcmbuf_set_boost_mode(true);
1381 fill_bytesleft
= filebuflen
;
1383 last_peek_offset
= -1;
1385 if (audio_load_track(offset
, true, 0)) {
1386 if (track_buffer_callback
) {
1387 cur_ti
->event_sent
= true;
1388 track_buffer_callback(&cur_ti
->id3
, true);
1392 audio_stop_playback(false);
1395 pcmbuf_set_boost_mode(false);
1398 /* Send callback events to notify about new tracks. */
1399 static void generate_postbuffer_events(void)
1402 int cur_ridx
, event_count
;
1404 /* At first determine how many unsent events we have. */
1405 cur_ridx
= track_ridx
;
1407 for (i
= 0; i
< track_count
; i
++) {
1408 if (!tracks
[cur_ridx
].event_sent
)
1410 if (++cur_ridx
>= MAX_TRACK
)
1411 cur_ridx
-= MAX_TRACK
;
1414 /* Now sent these events. */
1415 cur_ridx
= track_ridx
;
1416 for (i
= 0; i
< track_count
; i
++) {
1417 if (!tracks
[cur_ridx
].event_sent
) {
1418 tracks
[cur_ridx
].event_sent
= true;
1420 /* We still want to set event_sent flags even if not using
1422 if (track_buffer_callback
)
1423 track_buffer_callback(&tracks
[cur_ridx
].id3
, event_count
== 0);
1425 if (++cur_ridx
>= MAX_TRACK
)
1426 cur_ridx
-= MAX_TRACK
;
1430 static void initialize_buffer_fill(void)
1434 /* Initialize only once; do not truncate the tracks. */
1438 /* Save the current resume position once. */
1439 playlist_update_resume_info(audio_current_track());
1441 fill_bytesleft
= filebuflen
- filebufused
;
1442 cur_ti
->start_pos
= ci
.curpos
;
1444 pcmbuf_set_boost_mode(true);
1448 /* Calculate real track count after throwing away old tracks. */
1449 cur_idx
= track_ridx
;
1450 for (i
= 0; i
< track_count
; i
++) {
1451 if (cur_idx
== track_widx
)
1454 if (++cur_idx
>= MAX_TRACK
)
1459 if (tracks
[track_widx
].filesize
== 0) {
1460 if (--track_widx
< 0)
1461 track_widx
= MAX_TRACK
- 1;
1466 /* Mark all buffered entries null (not metadata for next track). */
1467 audio_clear_track_entries(true);
1470 static void audio_check_buffer(void)
1472 /* Start buffer filling as necessary. */
1473 if ((!conf_watermark
|| filebufused
> conf_watermark
1474 || !queue_empty(&audio_queue
) || !playing
|| ci
.stop_codec
1475 || ci
.reload_codec
|| playlist_end
) && !filling
)
1478 mutex_lock(&mutex_bufferfill
);
1479 initialize_buffer_fill();
1480 mutex_unlock(&mutex_bufferfill
);
1482 /* Limit buffering size at first run. */
1483 if (conf_bufferlimit
&& fill_bytesleft
> conf_bufferlimit
1485 fill_bytesleft
= MAX(0, conf_bufferlimit
- filebufused
);
1488 /* Try to load remainings of the file. */
1489 if (tracks
[track_widx
].filerem
> 0)
1490 audio_fill_file_buffer();
1492 /* Increase track write index as necessary. */
1493 if (tracks
[track_widx
].filerem
== 0 && tracks
[track_widx
].filesize
!= 0) {
1494 if (++track_widx
== MAX_TRACK
)
1498 /* Load new files to fill the entire buffer. */
1499 if (audio_load_track(0, false, last_peek_offset
+ 1)) {
1500 if (conf_bufferlimit
)
1503 else if (tracks
[track_widx
].filerem
== 0)
1506 if (fill_bytesleft
<= 0)
1508 /* Read next unbuffered track's metadata as necessary. */
1509 read_next_metadata();
1511 generate_postbuffer_events();
1513 conf_bufferlimit
= 0;
1514 pcmbuf_set_boost_mode(false);
1523 static void audio_update_trackinfo(void)
1525 ci
.filesize
= cur_ti
->filesize
;
1526 cur_ti
->id3
.elapsed
= 0;
1527 cur_ti
->id3
.offset
= 0;
1528 ci
.id3
= (struct mp3entry
*)&cur_ti
->id3
;
1530 cur_ti
->start_pos
= 0;
1531 ci
.taginfo_ready
= (bool *)&cur_ti
->taginfo_ready
;
1533 /* Manual track change (always crossfade or flush audio). */
1536 pcmbuf_crossfade_init(true);
1537 codec_track_changed();
1540 /* Automatic track change with crossfade. */
1541 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active())
1543 pcmbuf_crossfade_init(false);
1544 codec_track_changed();
1547 /* Gapless playback. */
1550 pcmbuf_set_event_handler(pcmbuf_track_changed_callback
);
1560 /* Should handle all situations. */
1561 static int skip_next_track(bool inside_codec_thread
)
1564 /* Manual track skipping. */
1568 /* Automatic track skipping. */
1571 if (!playlist_check(1)) {
1572 ci
.reload_codec
= false;
1579 if (++track_ridx
>= MAX_TRACK
)
1582 /* Wait for new track data. */
1583 while (tracks
[track_ridx
].filesize
== 0 && filling
1587 if (tracks
[track_ridx
].filesize
<= 0)
1589 logf("Loading from disk...");
1590 ci
.reload_codec
= true;
1591 /* Stop playback if manual track change. */
1592 if (new_track
!= 0 && !pcmbuf_is_crossfade_enabled())
1594 if (inside_codec_thread
)
1599 else if (pcmbuf_is_crossfade_enabled())
1600 pcmbuf_crossfade_init(new_track
!= 0);
1602 queue_post(&audio_queue
, Q_AUDIO_PLAY
, 0);
1603 return SKIP_OK_DISK
;
1606 buf_ridx
+= cur_ti
->available
;
1607 filebufused
-= cur_ti
->available
;
1609 cur_ti
= &tracks
[track_ridx
];
1610 buf_ridx
+= cur_ti
->codecsize
;
1611 filebufused
-= cur_ti
->codecsize
;
1612 if (buf_ridx
>= filebuflen
)
1613 buf_ridx
-= filebuflen
;
1614 audio_update_trackinfo();
1617 pcmbuf_set_boost_mode(false);
1622 static int skip_previous_track(bool inside_codec_thread
)
1624 logf("skip previous");
1626 if (--track_ridx
< 0)
1627 track_ridx
+= MAX_TRACK
;
1629 if (tracks
[track_ridx
].filesize
== 0 ||
1630 filebufused
+ci
.curpos
+tracks
[track_ridx
].filesize
1631 /*+ (off_t)tracks[track_ridx].codecsize*/ > filebuflen
) {
1632 logf("Loading from disk...");
1633 ci
.reload_codec
= true;
1634 /* Stop playback. */
1635 /* FIXME: Only stop playback if disk is not spinning! */
1636 if (pcmbuf_is_crossfade_enabled())
1637 pcmbuf_crossfade_init(true);
1638 else if (inside_codec_thread
)
1643 queue_post(&audio_queue
, Q_AUDIO_PLAY
, 0);
1644 return SKIP_OK_DISK
;
1647 buf_ridx
-= ci
.curpos
+ cur_ti
->codecsize
;
1648 filebufused
+= ci
.curpos
+ cur_ti
->codecsize
;
1649 cur_ti
->available
= cur_ti
->filesize
- cur_ti
->filerem
;
1651 cur_ti
= &tracks
[track_ridx
];
1652 buf_ridx
-= cur_ti
->filesize
;
1653 filebufused
+= cur_ti
->filesize
;
1654 cur_ti
->available
= cur_ti
->filesize
;
1656 buf_ridx
+= filebuflen
;
1658 audio_update_trackinfo();
1663 /* Request the next track with new codec. */
1664 static void audio_change_track(void)
1666 logf("change track");
1668 if (!ci
.reload_codec
)
1670 if (skip_next_track(false) == SKIP_FAIL
)
1672 logf("No more tracks");
1673 while (pcm_is_playing())
1675 audio_stop_playback(false);
1680 ci
.reload_codec
= false;
1681 /* Needed for fast skipping. */
1682 if (cur_ti
->codecsize
> 0)
1683 queue_post(&codec_queue
, Q_CODEC_LOAD
, 0);
1686 bool codec_request_next_track_callback(void)
1690 if (current_codec
== CODEC_IDX_VOICE
) {
1691 voice_remaining
= 0;
1692 /* Terminate the codec if there are messages waiting on the queue or
1693 the core has been requested the codec to be terminated. */
1694 return !ci_voice
.stop_codec
&& queue_empty(&voice_codec_queue
);
1697 if (ci
.stop_codec
|| !playing
)
1700 #ifdef AB_REPEAT_ENABLE
1701 ab_end_of_track_report();
1705 pcmbuf_set_position_callback(pcmbuf_position_callback
);
1707 logf("Request new track");
1709 /* Advance to next track. */
1710 if (new_track
>= 0 || !ci
.reload_codec
) {
1711 if (skip_next_track(true) != SKIP_OK_RAM
)
1715 /* Advance to previous track. */
1717 if (skip_previous_track(true) != SKIP_OK_RAM
)
1722 ci
.reload_codec
= false;
1724 logf("On-the-fly change");
1726 /* Check if the next codec is the same file. */
1727 if (get_codec_base_type(prev_ti
->id3
.codectype
) !=
1728 get_codec_base_type(cur_ti
->id3
.codectype
))
1730 logf("New codec:%d/%d", cur_ti
->id3
.codectype
,
1731 tracks
[track_ridx
].id3
.codectype
);
1733 if (cur_ti
->codecsize
== 0)
1735 logf("Loading from disk [2]...");
1736 queue_post(&audio_queue
, Q_AUDIO_PLAY
, 0);
1739 ci
.reload_codec
= true;
1747 /* Invalidates all but currently playing track. */
1748 void audio_invalidate_tracks(void)
1750 if (track_count
== 0) {
1751 /* This call doesn't seem necessary anymore. Uncomment it
1753 /* queue_post(&audio_queue, Q_AUDIO_PLAY, 0); */
1757 playlist_end
= false;
1759 last_peek_offset
= 0;
1760 track_widx
= track_ridx
;
1761 /* Mark all other entries null (also buffered wrong metadata). */
1762 audio_clear_track_entries(false);
1763 filebufused
= cur_ti
->available
;
1764 buf_widx
= buf_ridx
+ cur_ti
->available
;
1765 if (buf_widx
>= filebuflen
)
1766 buf_widx
-= filebuflen
;
1767 read_next_metadata();
1770 static void initiate_track_change(int peek_index
)
1772 /* Detect if disk is spinning or already loading. */
1773 if (filling
|| ci
.reload_codec
|| !audio_codec_loaded
) {
1774 if (pcmbuf_is_crossfade_enabled())
1775 pcmbuf_crossfade_init(true);
1778 ci
.stop_codec
= true;
1779 queue_post(&audio_queue
, Q_AUDIO_PLAY
, 0);
1781 new_track
= peek_index
;
1782 ci
.reload_codec
= true;
1785 codec_track_changed();
1788 static void initiate_dir_change(int direction
)
1790 if(!playlist_next_dir(direction
))
1793 queue_post(&audio_queue
, Q_AUDIO_PLAY
, (bool *)true);
1795 codec_track_changed();
1798 void audio_thread(void)
1802 bool play_pending
= false;
1804 /* At first initialize audio system in background. */
1808 if (!play_pending
&& queue_empty(&audio_queue
))
1811 audio_check_buffer();
1819 queue_wait_w_tmo(&audio_queue
, &ev
, 0);
1820 if (ev
.id
== SYS_TIMEOUT
&& play_pending
)
1822 ev
.id
= Q_AUDIO_PLAY
;
1823 ev
.data
= (bool *)1;
1828 /* Don't start playing immediately if user is skipping tracks
1829 * fast to prevent UI lag. */
1831 last_peek_offset
= 0;
1832 track_changed
= true;
1833 playlist_end
= false;
1834 if (current_tick
- last_tick
< HZ
/2)
1836 play_pending
= true;
1839 play_pending
= false;
1840 last_tick
= current_tick
;
1842 /* Do not start crossfading if audio is paused. */
1847 /* check if radio is playing */
1848 if (get_radio_status() != FMRADIO_OFF
) {
1853 logf("starting...");
1855 ci
.stop_codec
= true;
1856 ci
.reload_codec
= false;
1859 while (audio_codec_loaded
)
1862 audio_play_start((int)ev
.data
);
1863 playlist_update_resume_info(audio_current_track());
1865 /* If there are no tracks in the playlist, then the playlist
1866 was empty or none of the filenames were valid. No point
1867 in playing an empty playlist. */
1868 if (playlist_amount() == 0) {
1869 audio_stop_playback(false);
1874 audio_stop_playback(true);
1878 logf("audio_pause");
1883 case Q_AUDIO_RESUME
:
1884 logf("audio_resume");
1885 pcmbuf_pause(false);
1891 last_tick
= current_tick
;
1892 playlist_end
= false;
1893 initiate_track_change(1);
1898 last_tick
= current_tick
;
1899 playlist_end
= false;
1900 initiate_track_change(-1);
1903 case Q_AUDIO_FF_REWIND
:
1907 ci
.seek_time
= (int)ev
.data
+1;
1910 case Q_AUDIO_SEAMLESS_SEEK
:
1913 ci
.seek_time
= (int)ev
.data
+1;
1916 case Q_AUDIO_DIR_NEXT
:
1917 logf("audio_dir_next");
1918 playlist_end
= false;
1919 if (global_settings
.beep
)
1920 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
1921 initiate_dir_change(1);
1924 case Q_AUDIO_DIR_PREV
:
1925 logf("audio_dir_prev");
1926 playlist_end
= false;
1927 if (global_settings
.beep
)
1928 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
1929 initiate_dir_change(-1);
1933 audio_invalidate_tracks();
1936 case Q_AUDIO_TRACK_CHANGED
:
1937 if (track_changed_callback
)
1938 track_changed_callback(&cur_ti
->id3
);
1939 playlist_update_resume_info(audio_current_track());
1940 pcmbuf_set_position_callback(NULL
);
1943 case Q_AUDIO_CODEC_DONE
:
1947 case SYS_USB_CONNECTED
:
1948 logf("USB: Audio core");
1949 audio_stop_playback(true);
1950 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
1951 usb_wait_for_disconnect(&audio_queue
);
1960 void codec_thread(void)
1969 queue_wait(&codec_queue
, &ev
);
1973 case Q_CODEC_LOAD_DISK
:
1974 ci
.stop_codec
= false;
1975 audio_codec_loaded
= true;
1976 mutex_lock(&mutex_codecthread
);
1977 current_codec
= CODEC_IDX_AUDIO
;
1978 status
= codec_load_file((char *)ev
.data
, &ci
);
1979 mutex_unlock(&mutex_codecthread
);
1983 logf("Codec start");
1984 codecsize
= cur_ti
->codecsize
;
1985 if (codecsize
== 0) {
1986 logf("Codec slot is empty!");
1987 /* Wait for the pcm buffer to go empty */
1988 while (pcm_is_playing())
1990 audio_stop_playback(true);
1994 ci
.stop_codec
= false;
1995 wrap
= (int)&filebuf
[filebuflen
] - (int)cur_ti
->codecbuf
;
1996 audio_codec_loaded
= true;
1997 mutex_lock(&mutex_codecthread
);
1998 current_codec
= CODEC_IDX_AUDIO
;
1999 status
= codec_load_ram(cur_ti
->codecbuf
, codecsize
,
2000 &filebuf
[0], wrap
, &ci
);
2001 mutex_unlock(&mutex_codecthread
);
2005 case SYS_USB_CONNECTED
:
2006 while (voice_codec_loaded
) {
2007 if (current_codec
!= CODEC_IDX_VOICE
)
2011 logf("USB: Audio codec");
2012 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2013 usb_wait_for_disconnect(&codec_queue
);
2018 audio_codec_loaded
= false;
2021 case Q_CODEC_LOAD_DISK
:
2023 if (status
!= CODEC_OK
) {
2024 logf("Codec failure");
2025 // audio_stop_playback();
2026 ci
.reload_codec
= false;
2027 gui_syncsplash(HZ
*2, true, "Codec failure");
2029 logf("Codec finished");
2032 if (playing
&& !ci
.stop_codec
)
2033 audio_change_track();
2035 // queue_post(&audio_queue, Q_AUDIO_CODEC_DONE, (void *)status);
2040 static void reset_buffer(void)
2042 filebuf
= (char *)&audiobuf
[MALLOC_BUFSIZE
];
2043 filebuflen
= audiobufend
- audiobuf
- MALLOC_BUFSIZE
- GUARD_BUFSIZE
-
2044 (pcmbuf_get_bufsize() + get_pcmbuf_descsize() + PCMBUF_FADE_CHUNK
);
2047 if (talk_get_bufsize() && voice_codec_loaded
)
2049 filebuf
= &filebuf
[talk_get_bufsize()];
2050 filebuflen
-= 2*CODEC_IRAM_SIZE
+ 2*CODEC_SIZE
+ talk_get_bufsize();
2054 void voice_codec_thread(void)
2059 current_codec
= CODEC_IDX_AUDIO
;
2060 voice_codec_loaded
= false;
2063 voice_is_playing
= false;
2064 queue_wait(&voice_codec_queue
, &ev
);
2066 case Q_CODEC_LOAD_DISK
:
2067 logf("Loading voice codec");
2068 audio_stop_playback(true);
2069 mutex_lock(&mutex_codecthread
);
2070 current_codec
= CODEC_IDX_VOICE
;
2071 dsp_configure(DSP_RESET
, 0);
2072 ci
.configure(CODEC_DSP_ENABLE
, (bool *)true);
2073 voice_remaining
= 0;
2074 voice_getmore
= NULL
;
2075 voice_codec_loaded
= true;
2077 ci_voice
.stop_codec
= false;
2079 status
= codec_load_file((char *)ev
.data
, &ci_voice
);
2081 logf("Voice codec finished");
2082 audio_stop_playback(true);
2083 mutex_unlock(&mutex_codecthread
);
2084 current_codec
= CODEC_IDX_AUDIO
;
2085 voice_codec_loaded
= false;
2090 case SYS_USB_CONNECTED
:
2091 logf("USB: Voice codec");
2092 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2093 usb_wait_for_disconnect(&voice_codec_queue
);
2100 void voice_init(void)
2103 return; /* Audio buffers not yet set up */
2105 while (voice_codec_loaded
)
2107 logf("Terminating voice codec");
2108 ci_voice
.stop_codec
= true;
2109 if (current_codec
!= CODEC_IDX_VOICE
)
2114 if (!talk_get_bufsize())
2117 logf("Starting voice codec");
2118 queue_post(&voice_codec_queue
, Q_CODEC_LOAD_DISK
, (void *)CODEC_MPA_L3
);
2119 while (!voice_codec_loaded
)
2123 struct mp3entry
* audio_current_track(void)
2125 const char *filename
;
2127 static struct mp3entry temp_id3
;
2129 if (track_count
> 0 && cur_ti
->taginfo_ready
)
2130 return (struct mp3entry
*)&cur_ti
->id3
;
2132 filename
= playlist_peek(0);
2134 filename
= "No file!";
2136 // if (tagcache_fill_tags(&temp_id3, filename))
2137 // return &temp_id3;
2139 p
= strrchr(filename
, '/');
2145 memset(&temp_id3
, 0, sizeof(struct mp3entry
));
2146 strncpy(temp_id3
.path
, p
, sizeof(temp_id3
.path
)-1);
2147 temp_id3
.title
= &temp_id3
.path
[0];
2152 struct mp3entry
* audio_next_track(void)
2154 int next_idx
= track_ridx
+ 1;
2156 if (track_count
== 0)
2159 if (next_idx
>= MAX_TRACK
)
2162 if (!tracks
[next_idx
].taginfo_ready
)
2165 return &tracks
[next_idx
].id3
;
2168 bool audio_has_changed_track(void)
2170 if (track_changed
) {
2171 track_changed
= false;
2178 void audio_play(int offset
)
2181 if (pcmbuf_is_crossfade_enabled())
2183 ci
.stop_codec
= true;
2185 pcmbuf_crossfade_init(true);
2193 queue_post(&audio_queue
, Q_AUDIO_PLAY
, (void *)offset
);
2196 void audio_stop(void)
2199 queue_post(&audio_queue
, Q_AUDIO_STOP
, 0);
2200 while (playing
|| audio_codec_loaded
)
2204 bool mp3_pause_done(void)
2209 void audio_pause(void)
2211 queue_post(&audio_queue
, Q_AUDIO_PAUSE
, 0);
2214 void audio_resume(void)
2216 queue_post(&audio_queue
, Q_AUDIO_RESUME
, 0);
2219 void audio_next(void)
2221 /* Prevent UI lag and update the WPS immediately. */
2222 if (global_settings
.beep
)
2223 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
2225 if (!playlist_check(1))
2228 track_changed
= true;
2230 /* Force WPS to update even if audio thread is blocked spinning. */
2231 if (mutex_bufferfill
.locked
)
2232 cur_ti
->taginfo_ready
= false;
2234 queue_post(&audio_queue
, Q_AUDIO_NEXT
, 0);
2237 void audio_prev(void)
2239 /* Prevent UI lag and update the WPS immediately. */
2240 if (global_settings
.beep
)
2241 pcmbuf_beep(5000, 100, 2500*global_settings
.beep
);
2243 if (!playlist_check(-1))
2246 track_changed
= true;
2248 /* Force WPS to update even if audio thread is blocked spinning. */
2249 if (mutex_bufferfill
.locked
)
2250 cur_ti
->taginfo_ready
= false;
2252 queue_post(&audio_queue
, Q_AUDIO_PREV
, 0);
2255 void audio_next_dir(void)
2257 queue_post(&audio_queue
, Q_AUDIO_DIR_NEXT
, 0);
2260 void audio_prev_dir(void)
2262 queue_post(&audio_queue
, Q_AUDIO_DIR_PREV
, 0);
2265 void audio_ff_rewind(int newpos
)
2267 logf("rewind: %d", newpos
);
2268 queue_post(&audio_queue
, Q_AUDIO_FF_REWIND
, (int *)newpos
);
2271 void audio_seamless_seek(int newpos
)
2273 logf("seamless_seek: %d", newpos
);
2274 queue_post(&audio_queue
, Q_AUDIO_SEAMLESS_SEEK
, (int *)newpos
);
2277 void audio_flush_and_reload_tracks(void)
2279 logf("flush & reload");
2280 queue_post(&audio_queue
, Q_AUDIO_FLUSH
, 0);
2283 void audio_error_clear(void)
2287 int audio_status(void)
2292 ret
|= AUDIO_STATUS_PLAY
;
2295 ret
|= AUDIO_STATUS_PAUSE
;
2300 int audio_get_file_pos(void)
2306 /* Copied from mpeg.c. Should be moved somewhere else. */
2307 static void mp3_set_elapsed(struct mp3entry
* id3
)
2310 if ( id3
->has_toc
) {
2311 /* calculate elapsed time using TOC */
2313 unsigned int remainder
, plen
, relpos
, nextpos
;
2315 /* find wich percent we're at */
2316 for (i
=0; i
<100; i
++ )
2318 if ( id3
->offset
< id3
->toc
[i
] * (id3
->filesize
/ 256) )
2328 relpos
= id3
->toc
[i
];
2332 nextpos
= id3
->toc
[i
+1];
2339 remainder
= id3
->offset
- (relpos
* (id3
->filesize
/ 256));
2341 /* set time for this percent (divide before multiply to prevent
2342 overflow on long files. loss of precision is negligible on
2344 id3
->elapsed
= i
* (id3
->length
/ 100);
2346 /* calculate remainder time */
2347 plen
= (nextpos
- relpos
) * (id3
->filesize
/ 256);
2348 id3
->elapsed
+= (((remainder
* 100) / plen
) *
2349 (id3
->length
/ 10000));
2352 /* no TOC exists. set a rough estimate using average bitrate */
2353 int tpk
= id3
->length
/ (id3
->filesize
/ 1024);
2354 id3
->elapsed
= id3
->offset
/ 1024 * tpk
;
2358 /* constant bitrate, use exact calculation */
2359 id3
->elapsed
= id3
->offset
/ (id3
->bitrate
/ 8);
2362 /* Copied from mpeg.c. Should be moved somewhere else. */
2363 int mp3_get_file_pos(void)
2366 struct mp3entry
*id3
= audio_current_track();
2372 /* Use the TOC to find the new position */
2373 unsigned int percent
, remainder
;
2374 int curtoc
, nexttoc
, plen
;
2376 percent
= (id3
->elapsed
*100)/id3
->length
;
2380 curtoc
= id3
->toc
[percent
];
2383 nexttoc
= id3
->toc
[percent
+1];
2387 pos
= (id3
->filesize
/256)*curtoc
;
2389 /* Use the remainder to get a more accurate position */
2390 remainder
= (id3
->elapsed
*100)%id3
->length
;
2391 remainder
= (remainder
*100)/id3
->length
;
2392 plen
= (nexttoc
- curtoc
)*(id3
->filesize
/256);
2393 pos
+= (plen
/100)*remainder
;
2397 /* No TOC exists, estimate the new position */
2398 pos
= (id3
->filesize
/ (id3
->length
/ 1000)) *
2399 (id3
->elapsed
/ 1000);
2402 else if (id3
->bitrate
)
2403 pos
= id3
->elapsed
* (id3
->bitrate
/ 8);
2409 if (pos
>= (int)(id3
->filesize
- id3
->id3v1len
))
2411 /* Don't seek right to the end of the file so that we can
2412 transition properly to the next song */
2413 pos
= id3
->filesize
- id3
->id3v1len
- 1;
2415 else if (pos
< (int)id3
->first_frame_offset
)
2417 /* skip past id3v2 tag and other leading garbage */
2418 pos
= id3
->first_frame_offset
;
2423 void mp3_play_data(const unsigned char* start
, int size
,
2424 void (*get_more
)(unsigned char** start
, int* size
))
2426 voice_getmore
= get_more
;
2427 voicebuf
= (char *)start
;
2428 voice_remaining
= size
;
2429 voice_is_playing
= true;
2430 pcmbuf_reset_mixpos();
2433 void audio_set_buffer_margin(int setting
)
2435 static const int lookup
[] = {5, 15, 30, 60, 120, 180, 300, 600};
2436 buffer_margin
= lookup
[setting
];
2437 logf("buffer margin: %ds", buffer_margin
);
2438 set_filebuf_watermark(buffer_margin
);
2441 /* Set crossfade & PCM buffer length. */
2442 void audio_set_crossfade(int enable
)
2445 bool was_playing
= playing
;
2450 return; /* Audio buffers not yet set up */
2452 /* Store the track resume position */
2454 offset
= cur_ti
->id3
.offset
;
2458 seconds
= global_settings
.crossfade_fade_out_delay
2459 + global_settings
.crossfade_fade_out_duration
;
2462 /* Buffer has to be at least 2s long. */
2464 logf("buf len: %d", seconds
);
2465 size
= seconds
* (NATIVE_FREQUENCY
*4);
2466 if (pcmbuf_get_bufsize() == size
)
2469 /* Playback has to be stopped before changing the buffer size. */
2470 audio_stop_playback(true);
2472 /* Re-initialize audio system. */
2474 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK
));
2476 pcmbuf_crossfade_enable(enable
);
2478 logf("abuf:%dB", pcmbuf_get_bufsize());
2479 logf("fbuf:%dB", filebuflen
);
2483 /* Restart playback. */
2487 /* Wait for the playback to start again (and display the splash
2488 screen during that period. */
2490 while (playing
&& !audio_codec_loaded
)
2495 void mpeg_id3_options(bool _v1first
)
2500 void test_buffer_event(struct mp3entry
*id3
, bool last_track
)
2505 logf("be:%d%s", last_track
, id3
->path
);
2508 void test_unbuffer_event(struct mp3entry
*id3
, bool last_track
)
2513 logf("ube:%d%s", last_track
, id3
->path
);
2516 static void playback_init(void)
2518 static bool voicetagtrue
= true;
2521 logf("playback api init");
2524 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
2525 /* Set the input multiplexer to Line In */
2529 audio_set_track_buffer_event(test_buffer_event
);
2530 audio_set_track_unbuffer_event(test_unbuffer_event
);
2532 /* Initialize codec api. */
2533 ci
.read_filebuf
= codec_filebuf_callback
;
2534 ci
.pcmbuf_insert
= pcmbuf_insert_buffer
;
2535 ci
.pcmbuf_insert_split
= codec_pcmbuf_insert_split_callback
;
2536 ci
.get_codec_memory
= get_codec_memory_callback
;
2537 ci
.request_buffer
= codec_request_buffer_callback
;
2538 ci
.advance_buffer
= codec_advance_buffer_callback
;
2539 ci
.advance_buffer_loc
= codec_advance_buffer_loc_callback
;
2540 ci
.request_next_track
= codec_request_next_track_callback
;
2541 ci
.mp3_get_filepos
= codec_mp3_get_filepos_callback
;
2542 ci
.seek_buffer
= codec_seek_buffer_callback
;
2543 ci
.seek_complete
= codec_seek_complete_callback
;
2544 ci
.set_elapsed
= codec_set_elapsed_callback
;
2545 ci
.set_offset
= codec_set_offset_callback
;
2546 ci
.configure
= codec_configure_callback
;
2548 memcpy(&ci_voice
, &ci
, sizeof(struct codec_api
));
2549 memset(&id3_voice
, 0, sizeof(struct mp3entry
));
2550 ci_voice
.taginfo_ready
= &voicetagtrue
;
2551 ci_voice
.id3
= &id3_voice
;
2552 ci_voice
.pcmbuf_insert
= codec_pcmbuf_insert_callback
;
2553 id3_voice
.frequency
= 11200;
2554 id3_voice
.length
= 1000000L;
2556 create_thread(codec_thread
, codec_stack
, sizeof(codec_stack
),
2558 create_thread(voice_codec_thread
, voice_codec_stack
,
2559 sizeof(voice_codec_stack
), voice_codec_thread_name
);
2563 queue_wait(&audio_queue
, &ev
);
2564 if (ev
.id
== Q_AUDIO_POSTINIT
)
2568 if (ev
.id
== SYS_USB_CONNECTED
)
2570 logf("USB: Audio preinit");
2571 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
2572 usb_wait_for_disconnect(&audio_queue
);
2577 filebuf
= (char *)&audiobuf
[MALLOC_BUFSIZE
];
2579 /* Apply relevant settings */
2580 audio_set_buffer_margin(global_settings
.buffer_margin
);
2581 audio_set_crossfade(global_settings
.crossfade
);
2583 sound_settings_apply();
2586 void audio_preinit(void)
2588 logf("playback system pre-init");
2592 current_codec
= CODEC_IDX_AUDIO
;
2594 audio_codec_loaded
= false;
2595 voice_is_playing
= false;
2597 track_changed
= false;
2599 track_buffer_callback
= NULL
;
2600 track_unbuffer_callback
= NULL
;
2601 track_changed_callback
= NULL
;
2602 /* Just to prevent cur_ti never be anything random. */
2603 cur_ti
= &tracks
[0];
2605 mutex_init(&mutex_bufferfill
);
2606 mutex_init(&mutex_codecthread
);
2608 queue_init(&audio_queue
);
2609 queue_init(&codec_queue
);
2610 queue_init(&voice_codec_queue
);
2612 create_thread(audio_thread
, audio_stack
, sizeof(audio_stack
),
2616 void audio_init(void)
2618 logf("playback system post-init");
2620 queue_post(&audio_queue
, Q_AUDIO_POSTINIT
, 0);