Patch #3060 from Andrew Scott - iPod mini button driver
[Rockbox.git] / apps / playback.c
blob921121163fa036fb215249f439badb7ddae98308
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
24 #include "system.h"
25 #include "thread.h"
26 #include "file.h"
27 #include "lcd.h"
28 #include "font.h"
29 #include "backlight.h"
30 #include "button.h"
31 #include "kernel.h"
32 #include "tree.h"
33 #include "debug.h"
34 #include "sprintf.h"
35 #include "settings.h"
36 #include "codecs.h"
37 #include "audio.h"
38 #include "logf.h"
39 #include "mp3_playback.h"
40 #include "usb.h"
41 #include "status.h"
42 #include "main_menu.h"
43 #include "ata.h"
44 #include "screens.h"
45 #include "playlist.h"
46 #include "playback.h"
47 #include "pcmbuf.h"
48 #include "pcm_playback.h"
49 #include "pcm_record.h"
50 #include "buffer.h"
51 #include "dsp.h"
52 #include "abrepeat.h"
53 #ifdef HAVE_LCD_BITMAP
54 #include "icons.h"
55 #include "peakmeter.h"
56 #include "action.h"
57 #endif
58 #include "lang.h"
59 #include "bookmark.h"
60 #include "misc.h"
61 #include "sound.h"
62 #include "metadata.h"
63 #include "talk.h"
64 #ifdef CONFIG_TUNER
65 #include "radio.h"
66 #endif
67 #include "splash.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)
91 enum {
92 Q_AUDIO_PLAY = 1,
93 Q_AUDIO_STOP,
94 Q_AUDIO_PAUSE,
95 Q_AUDIO_RESUME,
96 Q_AUDIO_NEXT,
97 Q_AUDIO_PREV,
98 Q_AUDIO_FF_REWIND,
99 Q_AUDIO_FLUSH_RELOAD,
100 Q_AUDIO_CODEC_DONE,
101 Q_AUDIO_FLUSH,
102 Q_AUDIO_TRACK_CHANGED,
103 Q_AUDIO_DIR_NEXT,
104 Q_AUDIO_DIR_PREV,
105 Q_AUDIO_SEAMLESS_SEEK,
106 Q_AUDIO_POSTINIT,
108 Q_CODEC_LOAD,
109 Q_CODEC_LOAD_DISK,
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";
127 /* Codec thread. */
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. */
158 int filebuflen;
160 /* Bytes available in the buffer. */
161 int filebufused;
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. */
172 int track_count;
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);
208 /* Configuration */
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);
219 #ifdef TIME_CODEC
220 bool is_filling(void)
222 return filling;
224 #endif
226 static void do_swap(int idx_old, int idx_new)
228 #ifndef SIMULATOR
229 unsigned char *iram_p = (unsigned char *)(CODEC_IRAM_ORIGIN);
230 unsigned char *iram_buf[2];
231 #endif
232 unsigned char *dram_buf[2];
235 #ifndef SIMULATOR
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);
240 #endif
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)
250 int last_codec;
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);
262 sleep(1);
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;
275 invalidate_icache();
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)
285 state = false;
287 if (state != voice_cpu_boosted)
289 cpu_boost(state);
290 voice_cpu_boosted = state;
293 #else
294 #define voice_boost_cpu(state) do { } while(0)
295 #endif
297 bool codec_pcmbuf_insert_split_callback(const void *ch1, const void *ch2,
298 size_t length)
300 const char* src[2];
301 char *dest;
302 long input_size;
303 size_t output_size;
305 src[0] = ch1;
306 src[1] = ch2;
308 while (paused)
310 sleep(1);
311 if (ci.stop_codec || ci.reload_codec || ci.seek_time)
312 return true;
315 if (dsp_stereo_mode() == STEREO_NONINTERLEAVED)
317 length *= 2; /* Length is per channel */
320 while (length > 0) {
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)
326 sleep(1);
328 else
330 if (ci.reload_codec || ci.stop_codec)
331 return true;
333 while ((dest = pcmbuf_request_buffer(est_output_size,
334 &output_size)) == NULL) {
335 sleep(1);
336 if (ci.reload_codec || ci.stop_codec)
337 return true;
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 */
349 break;
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);
355 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);
369 swap_codec();
370 voice_boost_cpu(false);
372 break ;
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)
379 swap_codec();
380 } else {
381 pcmbuf_write_complete(output_size);
383 break ;
386 length -= input_size;
389 return true;
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),
406 length);
409 void* get_codec_memory_callback(long *size)
411 *size = MALLOC_BUFSIZE;
412 if (voice_codec_loaded)
413 return &audiobuf[talk_get_bufsize()];
415 return &audiobuf[0];
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;
425 } else {
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)
435 return ;
437 #ifdef AB_REPEAT_ENABLE
438 ab_position_report(value);
439 #endif
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)
455 return ;
457 latency = pcmbuf_get_latency() * cur_ti->id3.bitrate / 8;
459 if (value < latency) {
460 cur_ti->id3.offset = 0;
461 } else {
462 cur_ti->id3.offset = value - latency;
466 long codec_filebuf_callback(void *ptr, long size)
468 char *buf = (char *)ptr;
469 int copy_n;
470 int part_n;
472 if (ci.stop_codec || !playing || current_codec == CODEC_IDX_VOICE)
473 return 0;
475 copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem);
477 while (copy_n > cur_ti->available) {
478 yield();
479 if (ci.stop_codec || ci.reload_codec)
480 return 0;
483 if (copy_n == 0)
484 return 0;
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);
492 buf_ridx += copy_n;
493 if (buf_ridx >= filebuflen)
494 buf_ridx -= filebuflen;
495 ci.curpos += copy_n;
496 cur_ti->available -= copy_n;
497 filebufused -= copy_n;
499 return 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)
507 yield();
508 if (audio_codec_loaded && (pcmbuf_usage() < 30
509 || !voice_is_playing || voicebuf == NULL))
511 swap_codec();
513 else if (!voice_is_playing)
515 voice_boost_cpu(false);
516 if (!pcm_is_playing())
517 pcmbuf_boost(false);
518 sleep(HZ/16);
521 if (voice_remaining)
523 voice_is_playing = true;
524 break ;
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. */
535 pcmbuf_play_start();
540 if (reqsize < 0)
541 reqsize = 0;
543 voice_is_playing = true;
544 *realsize = voice_remaining;
545 if (*realsize > reqsize)
546 *realsize = reqsize;
548 if (*realsize == 0)
549 return NULL;
551 return voicebuf;
554 void* codec_request_buffer_callback(long *realsize, long reqsize)
556 long part_n;
558 /* Voice codec. */
559 if (current_codec == CODEC_IDX_VOICE) {
560 return voice_request_data(realsize, reqsize);
563 if (ci.stop_codec || !playing) {
564 *realsize = 0;
565 return NULL;
568 *realsize = MIN((off_t)reqsize, (off_t)cur_ti->available + cur_ti->filerem);
569 if (*realsize == 0) {
570 return NULL;
573 while ((int)*realsize > cur_ti->available) {
574 yield();
575 if (ci.stop_codec || ci.reload_codec) {
576 *realsize = 0;
577 return NULL;
581 part_n = MIN((int)*realsize, filebuflen - buf_ridx);
582 if (part_n < *realsize) {
583 part_n += GUARD_BUFSIZE;
584 if (part_n < *realsize)
585 *realsize = part_n;
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)
595 int fd;
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);
602 if (fd < 0) {
603 logf("Open failed!");
604 mutex_unlock(&mutex_bufferfill);
605 return false;
607 if (current_fd >= 0)
608 close(current_fd);
609 current_fd = fd;
611 /* Clear codec buffer. */
612 audio_invalidate_tracks();
613 filebufused = 0;
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;
619 ci.curpos = 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) {
626 sleep(1);
627 if (ci.stop_codec || ci.reload_codec || !queue_empty(&audio_queue))
628 return false;
631 return true;
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));
639 voicebuf += amount;
640 voice_remaining -= amount;
642 return ;
645 if (amount > cur_ti->available + cur_ti->filerem)
646 amount = cur_ti->available + cur_ti->filerem;
648 while (amount > cur_ti->available && filling)
649 sleep(1);
651 if (amount > cur_ti->available) {
652 if (!rebuffer_and_seek(ci.curpos + amount))
653 ci.stop_codec = true;
654 return ;
657 buf_ridx += amount;
658 if (buf_ridx >= filebuflen)
659 buf_ridx -= filebuflen;
660 cur_ti->available -= amount;
661 filebufused -= amount;
662 ci.curpos += amount;
663 codec_set_offset_callback(ci.curpos);
666 void codec_advance_buffer_loc_callback(void *ptr)
668 long amount;
670 if (current_codec == CODEC_IDX_VOICE)
671 amount = (int)ptr - (int)voicebuf;
672 else
673 amount = (int)ptr - (int)&filebuf[buf_ridx];
674 codec_advance_buffer_callback(amount);
677 off_t codec_mp3_get_filepos_callback(int newtime)
679 off_t newpos;
681 cur_ti->id3.elapsed = newtime;
682 newpos = mp3_get_file_pos();
684 return newpos;
687 void codec_seek_complete_callback(void)
689 /* assume we're called from non-voice codec, as they shouldn't seek */
690 ci.seek_time = 0;
693 bool codec_seek_buffer_callback(off_t newpos)
695 int difference;
697 if (current_codec == CODEC_IDX_VOICE)
698 return false;
700 if (newpos < 0)
701 newpos = 0;
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);
711 return true;
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;
728 if (buf_ridx < 0)
729 buf_ridx = filebuflen + buf_ridx;
730 ci.curpos -= difference;
732 return true;
735 static void set_filebuf_watermark(int seconds)
737 long bytes;
739 if (current_codec == CODEC_IDX_VOICE)
740 return ;
742 if (!filebuf)
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)
752 switch (setting) {
753 case CODEC_SET_FILEBUF_WATERMARK:
754 conf_watermark = (unsigned int)value;
755 set_filebuf_watermark(buffer_margin);
756 break;
758 case CODEC_SET_FILEBUF_CHUNKSIZE:
759 conf_filechunk = (unsigned int)value;
760 break;
762 case CODEC_DSP_ENABLE:
763 if ((bool)value)
764 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
765 else
766 ci.pcmbuf_insert = pcmbuf_insert_buffer;
767 break ;
769 default:
770 if (!dsp_configure(setting, value)) {
771 logf("Illegal key: %d", setting);
776 void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
777 bool last_track))
779 track_buffer_callback = handler;
782 void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
783 bool last_track))
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)
810 yield();
811 if (!pcm_is_playing() && !paused)
812 sleep(5);
813 while ((pcmbuf_is_crossfade_active() || pcmbuf_is_lowdata())
814 && !ci.stop_codec && playing && queue_empty(&audio_queue)
815 && filebufused > (128*1024))
816 sleep(1);
819 /* FIXME: This code should be made more generic and move to metadata.c */
820 void strip_id3v1_tag(void)
822 int i;
823 static const unsigned char tag[] = "TAG";
824 int tagptr;
825 bool found = true;
827 if (filebufused >= 128)
829 tagptr = buf_widx - 128;
830 if (tagptr < 0)
831 tagptr += filebuflen;
833 for(i = 0;i < 3;i++)
835 if(tagptr >= filebuflen)
836 tagptr -= filebuflen;
838 if(filebuf[tagptr] != tag[i])
840 found = false;
841 break;
844 tagptr++;
847 if(found)
849 /* Skip id3v1 tag */
850 logf("Skipping ID3v1 tag\n");
851 buf_widx -= 128;
852 tracks[track_widx].available -= 128;
853 filebufused -= 128;
858 static void audio_fill_file_buffer(void)
860 long i, size;
861 int rc;
863 if (current_fd < 0)
864 return ;
866 /* Throw away buffered codec. */
867 if (tracks[track_widx].start_pos != 0)
868 tracks[track_widx].codecsize = 0;
870 mutex_lock(&mutex_bufferfill);
871 i = 0;
872 size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE);
873 while (i < size) {
874 /* Give codecs some processing time. */
875 yield_codecs();
877 if (fill_bytesleft == 0)
878 break ;
879 rc = MIN(conf_filechunk, filebuflen - buf_widx);
880 rc = MIN(rc, fill_bytesleft);
881 rc = read(current_fd, &filebuf[buf_widx], rc);
882 if (rc <= 0) {
883 tracks[track_widx].filerem = 0;
884 break ;
887 buf_widx += rc;
888 if (buf_widx >= filebuflen)
889 buf_widx -= filebuflen;
890 i += rc;
891 tracks[track_widx].available += rc;
892 tracks[track_widx].filerem -= rc;
893 tracks[track_widx].filepos += rc;
894 filebufused += rc;
895 fill_bytesleft -= rc;
898 if (tracks[track_widx].filerem == 0) {
899 strip_id3v1_tag();
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)
910 switch (type) {
911 case AFMT_MPA_L1:
912 case AFMT_MPA_L2:
913 case AFMT_MPA_L3:
914 return AFMT_MPA_L3;
917 return type;
920 static bool loadcodec(bool start_play)
922 off_t size;
923 int fd;
924 int i, rc;
925 const char *codec_path;
926 int copy_n;
927 int prev_track;
929 switch (tracks[track_widx].id3.codectype) {
930 case AFMT_OGG_VORBIS:
931 logf("Codec: Vorbis");
932 codec_path = CODEC_VORBIS;
933 break;
934 case AFMT_MPA_L1:
935 case AFMT_MPA_L2:
936 case AFMT_MPA_L3:
937 logf("Codec: MPA L1/L2/L3");
938 codec_path = CODEC_MPA_L3;
939 break;
940 case AFMT_PCM_WAV:
941 logf("Codec: PCM WAV");
942 codec_path = CODEC_WAV;
943 break;
944 case AFMT_FLAC:
945 logf("Codec: FLAC");
946 codec_path = CODEC_FLAC;
947 break;
948 case AFMT_A52:
949 logf("Codec: A52");
950 codec_path = CODEC_A52;
951 break;
952 case AFMT_MPC:
953 logf("Codec: Musepack");
954 codec_path = CODEC_MPC;
955 break;
956 case AFMT_WAVPACK:
957 logf("Codec: WAVPACK");
958 codec_path = CODEC_WAVPACK;
959 break;
960 case AFMT_ALAC:
961 logf("Codec: ALAC");
962 codec_path = CODEC_ALAC;
963 break;
964 case AFMT_AAC:
965 logf("Codec: AAC");
966 codec_path = CODEC_AAC;
967 break;
968 case AFMT_SHN:
969 logf("Codec: SHN");
970 codec_path = CODEC_SHN;
971 break;
972 case AFMT_AIFF:
973 logf("Codec: PCM AIFF");
974 codec_path = CODEC_AIFF;
975 break;
976 default:
977 logf("Codec: Unsupported");
978 codec_path = NULL;
979 return false;
982 tracks[track_widx].codecsize = 0;
984 if (!start_play) {
985 prev_track = track_widx - 1;
986 if (prev_track < 0)
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");
993 return true;
995 } else {
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;
1001 ci.curpos = 0;
1002 playing = true;
1003 logf("Starting codec");
1004 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (void *)codec_path);
1005 return true;
1008 fd = open(codec_path, O_RDONLY);
1009 if (fd < 0) {
1010 logf("Codec doesn't exist!");
1011 return false;
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;
1019 fill_bytesleft = 0;
1020 close(fd);
1021 return false;
1024 i = 0;
1025 while (i < size) {
1026 yield_codecs();
1028 copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
1029 rc = read(fd, &filebuf[buf_widx], copy_n);
1030 if (rc < 0)
1031 return false;
1032 buf_widx += rc;
1033 filebufused += rc;
1034 fill_bytesleft -= rc;
1035 if (buf_widx >= filebuflen)
1036 buf_widx -= filebuflen;
1037 i += rc;
1039 close(fd);
1040 logf("Done: %dB", i);
1042 tracks[track_widx].codecsize = size;
1044 return true;
1047 static bool read_next_metadata(void)
1049 int fd;
1050 char *trackname;
1051 int next_track;
1052 int status;
1054 next_track = track_widx;
1055 if (tracks[track_widx].taginfo_ready)
1056 next_track++;
1058 if (next_track >= MAX_TRACK)
1059 next_track -= MAX_TRACK;
1061 if (tracks[next_track].taginfo_ready)
1062 return true;
1064 trackname = playlist_peek(last_peek_offset + 1);
1065 if (!trackname)
1066 return false;
1068 fd = open(trackname, O_RDONLY);
1069 if (fd < 0)
1070 return false;
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. */
1075 // filling = true;
1076 status = get_metadata(&tracks[next_track],fd,trackname,v1first);
1077 /* Preload the glyphs in the tags */
1078 if (status) {
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;
1087 close(fd);
1089 return status;
1092 static bool audio_load_track(int offset, bool start_play, int peek_offset)
1094 char *trackname;
1095 int fd = -1;
1096 off_t size;
1097 int rc, i;
1098 int copy_n;
1099 char msgbuf[80];
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
1103 metadata there). */
1104 if (track_count >= MAX_TRACK - 1) {
1105 fill_bytesleft = 0;
1106 return false;
1109 /* Don't start loading track if the current write position already
1110 contains a BUFFERED track. The entry may contain the metadata
1111 which is ok. */
1112 if (tracks[track_widx].filesize != 0)
1113 return false;
1115 peek_again:
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);
1121 if (fd < 0) {
1122 logf("Open failed");
1123 /* Skip invalid entry from playlist. */
1124 playlist_skip_entry(NULL, peek_offset);
1125 continue ;
1127 break ;
1130 if (!trackname) {
1131 logf("End-of-playlist");
1132 playlist_end = true;
1133 return false;
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 */
1150 if (start_play) {
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;
1168 close(fd);
1169 /* Skip invalid entry from playlist. */
1170 playlist_skip_entry(NULL, peek_offset);
1171 goto peek_again;
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);
1181 close(fd);
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);
1192 goto peek_again;
1194 return false;
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 */
1202 if (offset > 0) {
1203 switch (tracks[track_widx].id3.codectype) {
1204 case AFMT_MPA_L2:
1205 case AFMT_MPA_L3:
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;
1211 ci.curpos = offset;
1212 tracks[track_widx].start_pos = offset;
1213 break;
1215 case AFMT_WAVPACK:
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;
1221 ci.curpos = offset;
1222 tracks[track_widx].start_pos = offset;
1223 break;
1224 case AFMT_OGG_VORBIS:
1225 case AFMT_FLAC:
1226 tracks[track_widx].id3.offset = offset;
1227 break;
1231 if (start_play) {
1232 track_count++;
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);
1240 while (i < size) {
1241 /* Give codecs some processing time to prevent glitches. */
1242 yield_codecs();
1244 if (fill_bytesleft == 0)
1245 break ;
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);
1251 if (rc < copy_n) {
1252 logf("File error!");
1253 tracks[track_widx].filesize = 0;
1254 tracks[track_widx].filerem = 0;
1255 close(fd);
1256 mutex_unlock(&mutex_bufferfill);
1257 return false;
1259 buf_widx += rc;
1260 if (buf_widx >= filebuflen)
1261 buf_widx -= filebuflen;
1262 i += rc;
1263 tracks[track_widx].available += rc;
1264 tracks[track_widx].filerem -= rc;
1265 filebufused += rc;
1266 fill_bytesleft -= rc;
1268 mutex_unlock(&mutex_bufferfill);
1270 if (!start_play)
1271 track_count++;
1273 tracks[track_widx].filepos = i;
1275 if (current_fd >= 0) {
1276 close(current_fd);
1277 current_fd = -1;
1280 /* Leave the file handle open for faster buffer refill. */
1281 if (tracks[track_widx].filerem != 0) {
1282 current_fd = fd;
1283 logf("Partially buf:%d", tracks[track_widx].available);
1284 } else {
1285 logf("Completely buf.");
1286 close(fd);
1288 strip_id3v1_tag();
1290 if (++track_widx >= MAX_TRACK) {
1291 track_widx = 0;
1293 tracks[track_widx].filerem = 0;
1296 return true;
1299 static void audio_clear_track_entries(bool buffered_only)
1301 int cur_idx, event_count;
1302 int i;
1304 cur_idx = track_widx;
1305 event_count = 0;
1306 for (i = 0; i < MAX_TRACK - track_count; i++) {
1307 if (++cur_idx >= MAX_TRACK)
1308 cur_idx = 0;
1310 if (tracks[cur_idx].event_sent)
1311 event_count++;
1313 if (!track_unbuffer_callback)
1314 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
1317 if (!track_unbuffer_callback)
1318 return ;
1320 cur_idx = track_widx;
1321 for (i = 0; i < MAX_TRACK - track_count; i++) {
1322 if (++cur_idx >= MAX_TRACK)
1323 cur_idx = 0;
1325 /* Send an event to notify that track has finished. */
1326 if (tracks[cur_idx].event_sent) {
1327 event_count--;
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;
1339 pcmbuf_play_stop();
1340 while (audio_codec_loaded)
1341 yield();
1342 pcmbuf_play_stop();
1345 static void audio_stop_playback(bool resume)
1347 logf("stop_playback:%d", resume);
1348 paused = false;
1349 if (playing)
1350 playlist_update_resume_info(resume ? audio_current_track() : NULL);
1351 playing = false;
1352 filling = false;
1353 stop_codec_flush();
1354 if (current_fd >= 0) {
1355 close(current_fd);
1356 current_fd = -1;
1359 track_count = 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) {
1367 close(current_fd);
1368 current_fd = -1;
1371 memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK);
1372 sound_set_volume(global_settings.volume);
1373 track_count = 0;
1374 track_widx = 0;
1375 track_ridx = 0;
1376 buf_ridx = 0;
1377 buf_widx = 0;
1378 filebufused = 0;
1379 pcmbuf_set_boost_mode(true);
1381 fill_bytesleft = filebuflen;
1382 filling = true;
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);
1390 } else {
1391 logf("Failure");
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)
1401 int i;
1402 int cur_ridx, event_count;
1404 /* At first determine how many unsent events we have. */
1405 cur_ridx = track_ridx;
1406 event_count = 0;
1407 for (i = 0; i < track_count; i++) {
1408 if (!tracks[cur_ridx].event_sent)
1409 event_count++;
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;
1419 event_count--;
1420 /* We still want to set event_sent flags even if not using
1421 event callbacks. */
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)
1432 int cur_idx, i;
1434 /* Initialize only once; do not truncate the tracks. */
1435 if (filling)
1436 return ;
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);
1446 filling = 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)
1452 break ;
1454 if (++cur_idx >= MAX_TRACK)
1455 cur_idx = 0;
1458 track_count = i;
1459 if (tracks[track_widx].filesize == 0) {
1460 if (--track_widx < 0)
1461 track_widx = MAX_TRACK - 1;
1462 } else {
1463 track_count++;
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)
1476 return ;
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
1484 - filebufused) {
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)
1495 track_widx = 0;
1498 /* Load new files to fill the entire buffer. */
1499 if (audio_load_track(0, false, last_peek_offset + 1)) {
1500 if (conf_bufferlimit)
1501 fill_bytesleft = 0;
1503 else if (tracks[track_widx].filerem == 0)
1504 fill_bytesleft = 0;
1506 if (fill_bytesleft <= 0)
1508 /* Read next unbuffered track's metadata as necessary. */
1509 read_next_metadata();
1511 generate_postbuffer_events();
1512 filling = false;
1513 conf_bufferlimit = 0;
1514 pcmbuf_set_boost_mode(false);
1516 #ifndef SIMULATOR
1517 if (playing)
1518 ata_sleep();
1519 #endif
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;
1529 ci.curpos = 0;
1530 cur_ti->start_pos = 0;
1531 ci.taginfo_ready = (bool *)&cur_ti->taginfo_ready;
1533 /* Manual track change (always crossfade or flush audio). */
1534 if (new_track)
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. */
1548 else
1550 pcmbuf_set_event_handler(pcmbuf_track_changed_callback);
1554 enum {
1555 SKIP_FAIL,
1556 SKIP_OK_DISK,
1557 SKIP_OK_RAM,
1560 /* Should handle all situations. */
1561 static int skip_next_track(bool inside_codec_thread)
1563 logf("skip next");
1564 /* Manual track skipping. */
1565 if (new_track > 0)
1566 last_peek_offset--;
1568 /* Automatic track skipping. */
1569 else
1571 if (!playlist_check(1)) {
1572 ci.reload_codec = false;
1573 return SKIP_FAIL;
1575 last_peek_offset--;
1576 playlist_next(1);
1579 if (++track_ridx >= MAX_TRACK)
1580 track_ridx = 0;
1582 /* Wait for new track data. */
1583 while (tracks[track_ridx].filesize == 0 && filling
1584 && !ci.stop_codec)
1585 yield();
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)
1595 pcmbuf_play_stop();
1596 else
1597 stop_codec_flush();
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();
1616 if (!filling)
1617 pcmbuf_set_boost_mode(false);
1619 return SKIP_OK_RAM;
1622 static int skip_previous_track(bool inside_codec_thread)
1624 logf("skip previous");
1625 last_peek_offset++;
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)
1639 pcmbuf_play_stop();
1640 else
1641 stop_codec_flush();
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;
1655 if (buf_ridx < 0)
1656 buf_ridx += filebuflen;
1658 audio_update_trackinfo();
1660 return SKIP_OK_RAM;
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())
1674 sleep(1);
1675 audio_stop_playback(false);
1676 return ;
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)
1688 prev_ti = cur_ti;
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)
1698 return false;
1700 #ifdef AB_REPEAT_ENABLE
1701 ab_end_of_track_report();
1702 #endif
1704 if (!new_track)
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)
1712 return false;
1715 /* Advance to previous track. */
1716 else {
1717 if (skip_previous_track(true) != SKIP_OK_RAM)
1718 return false;
1721 new_track = 0;
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);
1738 else
1739 ci.reload_codec = true;
1741 return false;
1744 return 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
1752 if things break */
1753 /* queue_post(&audio_queue, Q_AUDIO_PLAY, 0); */
1754 return ;
1757 playlist_end = false;
1758 track_count = 1;
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);
1776 else
1777 pcmbuf_play_stop();
1778 ci.stop_codec = true;
1779 queue_post(&audio_queue, Q_AUDIO_PLAY, 0);
1780 } else {
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))
1791 return;
1793 queue_post(&audio_queue, Q_AUDIO_PLAY, (bool *)true);
1795 codec_track_changed();
1798 void audio_thread(void)
1800 struct event ev;
1801 int last_tick = 0;
1802 bool play_pending = false;
1804 /* At first initialize audio system in background. */
1805 playback_init();
1807 while (1) {
1808 if (!play_pending && queue_empty(&audio_queue))
1810 yield_codecs();
1811 audio_check_buffer();
1813 else
1815 // ata_spin();
1816 sleep(1);
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;
1826 switch (ev.id) {
1827 case Q_AUDIO_PLAY:
1828 /* Don't start playing immediately if user is skipping tracks
1829 * fast to prevent UI lag. */
1830 track_count = 0;
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;
1837 break ;
1839 play_pending = false;
1840 last_tick = current_tick;
1842 /* Do not start crossfading if audio is paused. */
1843 if (paused)
1844 pcmbuf_play_stop();
1846 #ifdef CONFIG_TUNER
1847 /* check if radio is playing */
1848 if (get_radio_status() != FMRADIO_OFF) {
1849 radio_stop();
1851 #endif
1853 logf("starting...");
1854 playing = true;
1855 ci.stop_codec = true;
1856 ci.reload_codec = false;
1857 ci.seek_time = 0;
1859 while (audio_codec_loaded)
1860 yield();
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);
1871 break ;
1873 case Q_AUDIO_STOP:
1874 audio_stop_playback(true);
1875 break ;
1877 case Q_AUDIO_PAUSE:
1878 logf("audio_pause");
1879 pcmbuf_pause(true);
1880 paused = true;
1881 break ;
1883 case Q_AUDIO_RESUME:
1884 logf("audio_resume");
1885 pcmbuf_pause(false);
1886 paused = false;
1887 break ;
1889 case Q_AUDIO_NEXT:
1890 logf("audio_next");
1891 last_tick = current_tick;
1892 playlist_end = false;
1893 initiate_track_change(1);
1894 break ;
1896 case Q_AUDIO_PREV:
1897 logf("audio_prev");
1898 last_tick = current_tick;
1899 playlist_end = false;
1900 initiate_track_change(-1);
1901 break;
1903 case Q_AUDIO_FF_REWIND:
1904 if (!playing)
1905 break ;
1906 pcmbuf_play_stop();
1907 ci.seek_time = (int)ev.data+1;
1908 break ;
1910 case Q_AUDIO_SEAMLESS_SEEK:
1911 if (!playing)
1912 break ;
1913 ci.seek_time = (int)ev.data+1;
1914 break ;
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);
1922 break;
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);
1930 break;
1932 case Q_AUDIO_FLUSH:
1933 audio_invalidate_tracks();
1934 break ;
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);
1941 break ;
1943 case Q_AUDIO_CODEC_DONE:
1944 break ;
1946 #ifndef SIMULATOR
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);
1952 break ;
1953 #endif
1954 case SYS_TIMEOUT:
1955 break;
1960 void codec_thread(void)
1962 struct event ev;
1963 long codecsize;
1964 int status;
1965 int wrap;
1967 while (1) {
1968 status = 0;
1969 queue_wait(&codec_queue, &ev);
1970 new_track = 0;
1972 switch (ev.id) {
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);
1980 break ;
1982 case Q_CODEC_LOAD:
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())
1989 yield();
1990 audio_stop_playback(true);
1991 break ;
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);
2002 break ;
2004 #ifndef SIMULATOR
2005 case SYS_USB_CONNECTED:
2006 while (voice_codec_loaded) {
2007 if (current_codec != CODEC_IDX_VOICE)
2008 swap_codec();
2009 sleep(1);
2011 logf("USB: Audio codec");
2012 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2013 usb_wait_for_disconnect(&codec_queue);
2014 break ;
2015 #endif
2018 audio_codec_loaded = false;
2020 switch (ev.id) {
2021 case Q_CODEC_LOAD_DISK:
2022 case Q_CODEC_LOAD:
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");
2028 } else {
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)
2056 struct event ev;
2057 int status;
2059 current_codec = CODEC_IDX_AUDIO;
2060 voice_codec_loaded = false;
2061 while (1) {
2062 status = 0;
2063 voice_is_playing = false;
2064 queue_wait(&voice_codec_queue, &ev);
2065 switch (ev.id) {
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;
2076 reset_buffer();
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;
2086 reset_buffer();
2087 break ;
2089 #ifndef SIMULATOR
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);
2094 break ;
2095 #endif
2100 void voice_init(void)
2102 if (!filebuf)
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)
2110 swap_codec();
2111 sleep(1);
2114 if (!talk_get_bufsize())
2115 return ;
2117 logf("Starting voice codec");
2118 queue_post(&voice_codec_queue, Q_CODEC_LOAD_DISK, (void *)CODEC_MPA_L3);
2119 while (!voice_codec_loaded)
2120 sleep(1);
2123 struct mp3entry* audio_current_track(void)
2125 const char *filename;
2126 const char *p;
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);
2133 if (!filename)
2134 filename = "No file!";
2136 // if (tagcache_fill_tags(&temp_id3, filename))
2137 // return &temp_id3;
2139 p = strrchr(filename, '/');
2140 if (!p)
2141 p = filename;
2142 else
2143 p++;
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];
2149 return &temp_id3;
2152 struct mp3entry* audio_next_track(void)
2154 int next_idx = track_ridx + 1;
2156 if (track_count == 0)
2157 return NULL;
2159 if (next_idx >= MAX_TRACK)
2160 next_idx = 0;
2162 if (!tracks[next_idx].taginfo_ready)
2163 return NULL;
2165 return &tracks[next_idx].id3;
2168 bool audio_has_changed_track(void)
2170 if (track_changed) {
2171 track_changed = false;
2172 return true;
2175 return false;
2178 void audio_play(int offset)
2180 logf("audio_play");
2181 if (pcmbuf_is_crossfade_enabled())
2183 ci.stop_codec = true;
2184 sleep(1);
2185 pcmbuf_crossfade_init(true);
2187 else
2189 stop_codec_flush();
2190 pcmbuf_play_stop();
2193 queue_post(&audio_queue, Q_AUDIO_PLAY, (void *)offset);
2196 void audio_stop(void)
2198 logf("audio_stop");
2199 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
2200 while (playing || audio_codec_loaded)
2201 yield();
2204 bool mp3_pause_done(void)
2206 return paused;
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))
2226 return ;
2227 playlist_next(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))
2244 return ;
2245 playlist_next(-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)
2289 int ret = 0;
2291 if (playing)
2292 ret |= AUDIO_STATUS_PLAY;
2294 if (paused)
2295 ret |= AUDIO_STATUS_PAUSE;
2297 return ret;
2300 int audio_get_file_pos(void)
2302 return 0;
2306 /* Copied from mpeg.c. Should be moved somewhere else. */
2307 static void mp3_set_elapsed(struct mp3entry* id3)
2309 if ( id3->vbr ) {
2310 if ( id3->has_toc ) {
2311 /* calculate elapsed time using TOC */
2312 int i;
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) )
2320 break;
2324 i--;
2325 if (i < 0)
2326 i = 0;
2328 relpos = id3->toc[i];
2330 if (i < 99)
2332 nextpos = id3->toc[i+1];
2334 else
2336 nextpos = 256;
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
2343 short files) */
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));
2351 else {
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;
2357 else
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)
2365 int pos = -1;
2366 struct mp3entry *id3 = audio_current_track();
2368 if (id3->vbr)
2370 if (id3->has_toc)
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;
2377 if (percent > 99)
2378 percent = 99;
2380 curtoc = id3->toc[percent];
2382 if (percent < 99)
2383 nexttoc = id3->toc[percent+1];
2384 else
2385 nexttoc = 256;
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;
2395 else
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);
2404 else
2406 return -1;
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;
2420 return pos;
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)
2444 size_t size;
2445 bool was_playing = playing;
2446 int offset = 0;
2447 int seconds = 1;
2449 if (!filebuf)
2450 return; /* Audio buffers not yet set up */
2452 /* Store the track resume position */
2453 if (playing)
2454 offset = cur_ti->id3.offset;
2456 if (enable)
2458 seconds = global_settings.crossfade_fade_out_delay
2459 + global_settings.crossfade_fade_out_duration;
2462 /* Buffer has to be at least 2s long. */
2463 seconds += 2;
2464 logf("buf len: %d", seconds);
2465 size = seconds * (NATIVE_FREQUENCY*4);
2466 if (pcmbuf_get_bufsize() == size)
2467 return ;
2469 /* Playback has to be stopped before changing the buffer size. */
2470 audio_stop_playback(true);
2472 /* Re-initialize audio system. */
2473 if (was_playing)
2474 gui_syncsplash(0, true, (char *)str(LANG_RESTARTING_PLAYBACK));
2475 pcmbuf_init(size);
2476 pcmbuf_crossfade_enable(enable);
2477 reset_buffer();
2478 logf("abuf:%dB", pcmbuf_get_bufsize());
2479 logf("fbuf:%dB", filebuflen);
2481 voice_init();
2483 /* Restart playback. */
2484 if (was_playing) {
2485 audio_play(offset);
2487 /* Wait for the playback to start again (and display the splash
2488 screen during that period. */
2489 playing = true;
2490 while (playing && !audio_codec_loaded)
2491 yield();
2495 void mpeg_id3_options(bool _v1first)
2497 v1first = _v1first;
2500 void test_buffer_event(struct mp3entry *id3, bool last_track)
2502 (void)id3;
2503 (void)last_track;
2505 logf("be:%d%s", last_track, id3->path);
2508 void test_unbuffer_event(struct mp3entry *id3, bool last_track)
2510 (void)id3;
2511 (void)last_track;
2513 logf("ube:%d%s", last_track, id3->path);
2516 static void playback_init(void)
2518 static bool voicetagtrue = true;
2519 struct event ev;
2521 logf("playback api init");
2522 pcm_init();
2524 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
2525 /* Set the input multiplexer to Line In */
2526 pcm_rec_mux(0);
2527 #endif
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),
2557 codec_thread_name);
2558 create_thread(voice_codec_thread, voice_codec_stack,
2559 sizeof(voice_codec_stack), voice_codec_thread_name);
2561 while (1)
2563 queue_wait(&audio_queue, &ev);
2564 if (ev.id == Q_AUDIO_POSTINIT)
2565 break ;
2567 #ifndef SIMULATOR
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);
2574 #endif
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");
2590 filebufused = 0;
2591 filling = false;
2592 current_codec = CODEC_IDX_AUDIO;
2593 playing = false;
2594 audio_codec_loaded = false;
2595 voice_is_playing = false;
2596 paused = false;
2597 track_changed = false;
2598 current_fd = -1;
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),
2613 audio_thread_name);
2616 void audio_init(void)
2618 logf("playback system post-init");
2620 queue_post(&audio_queue, Q_AUDIO_POSTINIT, 0);