simplify and cleanup usb_serial.c (FS#10149 by Tomer Shalev)
[kugel-rb.git] / apps / playback.c
blobbaed012ddf42c411bf0f20575a69a92d6513f35a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005-2007 Miika Pekkarinen
11 * Copyright (C) 2007-2008 Nicolas Pennequin
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
23 /* TODO: Pause should be handled in here, rather than PCMBUF so that voice can
24 * play whilst audio is paused */
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <ctype.h>
31 #include "system.h"
32 #include "thread.h"
33 #include "file.h"
34 #include "panic.h"
35 #include "memory.h"
36 #include "lcd.h"
37 #include "font.h"
38 #include "button.h"
39 #include "kernel.h"
40 #include "tree.h"
41 #include "debug.h"
42 #include "sprintf.h"
43 #include "settings.h"
44 #include "codecs.h"
45 #include "audio.h"
46 #include "buffering.h"
47 #include "appevents.h"
48 #include "voice_thread.h"
49 #include "mp3_playback.h"
50 #include "usb.h"
51 #include "storage.h"
52 #include "screens.h"
53 #include "playlist.h"
54 #include "playback.h"
55 #include "pcmbuf.h"
56 #include "buffer.h"
57 #include "dsp.h"
58 #include "abrepeat.h"
59 #include "cuesheet.h"
60 #ifdef HAVE_TAGCACHE
61 #include "tagcache.h"
62 #endif
63 #ifdef HAVE_LCD_BITMAP
64 #include "icons.h"
65 #include "peakmeter.h"
66 #include "action.h"
67 #include "albumart.h"
68 #endif
69 #include "lang.h"
70 #include "bookmark.h"
71 #include "misc.h"
72 #include "sound.h"
73 #include "metadata.h"
74 #include "splash.h"
75 #include "talk.h"
76 #include "ata_idle_notify.h"
78 #ifdef HAVE_RECORDING
79 #include "recording.h"
80 #include "talk.h"
81 #include "pcm_record.h"
82 #endif
84 #ifdef IPOD_ACCESSORY_PROTOCOL
85 #include "iap.h"
86 #endif
88 #define PLAYBACK_VOICE
90 /* amount of guess-space to allow for codecs that must hunt and peck
91 * for their correct seeek target, 32k seems a good size */
92 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
94 /* Define LOGF_ENABLE to enable logf output in this file */
95 /*#define LOGF_ENABLE*/
96 #include "logf.h"
98 /* macros to enable logf for queues
99 logging on SYS_TIMEOUT can be disabled */
100 #ifdef SIMULATOR
101 /* Define this for logf output of all queuing except SYS_TIMEOUT */
102 #define PLAYBACK_LOGQUEUES
103 /* Define this to logf SYS_TIMEOUT messages */
104 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
105 #endif
107 #ifdef PLAYBACK_LOGQUEUES
108 #define LOGFQUEUE logf
109 #else
110 #define LOGFQUEUE(...)
111 #endif
113 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
114 #define LOGFQUEUE_SYS_TIMEOUT logf
115 #else
116 #define LOGFQUEUE_SYS_TIMEOUT(...)
117 #endif
120 /* Define one constant that includes recording related functionality */
121 #if defined(HAVE_RECORDING) && !defined(SIMULATOR)
122 #define AUDIO_HAVE_RECORDING
123 #endif
125 enum {
126 Q_NULL = 0,
127 Q_AUDIO_PLAY = 1,
128 Q_AUDIO_STOP,
129 Q_AUDIO_PAUSE,
130 Q_AUDIO_SKIP,
131 Q_AUDIO_PRE_FF_REWIND,
132 Q_AUDIO_FF_REWIND,
133 Q_AUDIO_CHECK_NEW_TRACK,
134 Q_AUDIO_FLUSH,
135 Q_AUDIO_TRACK_CHANGED,
136 Q_AUDIO_DIR_SKIP,
137 Q_AUDIO_POSTINIT,
138 Q_AUDIO_FILL_BUFFER,
139 Q_AUDIO_FINISH_LOAD,
140 Q_CODEC_REQUEST_COMPLETE,
141 Q_CODEC_REQUEST_FAILED,
143 Q_CODEC_LOAD,
144 Q_CODEC_LOAD_DISK,
146 #ifdef AUDIO_HAVE_RECORDING
147 Q_ENCODER_LOAD_DISK,
148 Q_ENCODER_RECORD,
149 #endif
151 Q_CODEC_DO_CALLBACK,
154 enum filling_state {
155 STATE_IDLE, /* audio is stopped: nothing to do */
156 STATE_FILLING, /* adding tracks to the buffer */
157 STATE_FULL, /* can't add any more tracks */
158 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
159 STATE_FINISHED, /* all remaining tracks are fully buffered */
162 #define MAX_TRACK 128
164 #define MAX_TRACK_MASK (MAX_TRACK-1)
166 /* As defined in plugins/lib/xxx2wav.h */
167 #define GUARD_BUFSIZE (32*1024)
169 /* As defined in plugin.lds */
170 #if defined(CPU_PP)
171 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x4000c000)
172 #define CODEC_IRAM_SIZE ((size_t)0xc000)
173 #elif defined(IAUDIO_X5) || defined(IAUDIO_M5)
174 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x10010000)
175 #define CODEC_IRAM_SIZE ((size_t)0x10000)
176 #else
177 #define CODEC_IRAM_ORIGIN ((unsigned char *)0x1000c000)
178 #define CODEC_IRAM_SIZE ((size_t)0xc000)
179 #endif
181 bool audio_is_initialized = false;
182 static bool audio_thread_ready SHAREDBSS_ATTR = false;
184 /* Variables are commented with the threads that use them: *
185 * A=audio, C=codec, V=voice. A suffix of - indicates that *
186 * the variable is read but not updated on that thread. */
187 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
189 /* Main state control */
190 static volatile bool audio_codec_loaded SHAREDBSS_ATTR = false; /* Codec loaded? (C/A-) */
191 static volatile bool playing SHAREDBSS_ATTR = false; /* Is audio playing? (A) */
192 static volatile bool paused SHAREDBSS_ATTR = false; /* Is audio paused? (A/C-) */
194 /* Ring buffer where compressed audio and codecs are loaded */
195 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
196 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
197 /* FIXME: make filebuflen static */
198 size_t filebuflen = 0; /* Size of buffer (A/C-) */
199 /* FIXME: make buf_ridx (C/A-) */
201 /* Possible arrangements of the buffer */
202 static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
204 /* These are used to store the current and next (or prev if the current is the last)
205 * mp3entry's in a round-robin system. This guarentees that the pointer returned
206 * by audio_current/next_track will be valid for the full duration of the
207 * currently playing track */
208 static struct mp3entry mp3entry_buf[2];
209 static struct mp3entry *thistrack_id3, /* the currently playing track */
210 *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
211 * next track otherwise */
212 static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
214 /* Track info structure about songs in the file buffer (A/C-) */
215 struct track_info {
216 int audio_hid; /* The ID for the track's buffer handle */
217 int id3_hid; /* The ID for the track's metadata handle */
218 int codec_hid; /* The ID for the track's codec handle */
219 #ifdef HAVE_ALBUMART
220 int aa_hid; /* The ID for the track's album art handle */
221 #endif
223 size_t filesize; /* File total length */
225 bool taginfo_ready; /* Is metadata read */
228 static struct track_info tracks[MAX_TRACK];
229 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
230 static int track_widx = 0; /* Track being buffered (A) */
232 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
233 static struct track_info *prev_ti = NULL; /* Pointer to the previously played
234 track */
236 /* Information used only for filling the buffer */
237 /* Playlist steps from playing track to next track to be buffered (A) */
238 static int last_peek_offset = 0;
240 /* Scrobbler support */
241 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
243 static enum filling_state filling;
245 /* Track change controls */
246 static bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
247 static bool dir_skip = false; /* Is a directory skip pending? (A) */
248 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
249 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
250 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
252 static bool start_play_g = false; /* Used by audio_load_track to notify
253 audio_finish_load_track about start_play */
255 /* True when a track load is in progress, i.e. audio_load_track() has returned
256 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
257 * audio_load_track() to get called twice in a row, which would cause problems.
259 static bool track_load_started = false;
261 /* Set to true if the codec thread should send an audio stop request
262 * (typically because the end of the playlist has been reached).
264 static bool codec_requested_stop = false;
266 #ifdef HAVE_DISK_STORAGE
267 static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
268 #endif
270 /* Multiple threads */
271 /* Set the watermark to trigger buffer fill (A/C) */
272 static void set_filebuf_watermark(void);
274 /* Audio thread */
275 static struct event_queue audio_queue SHAREDBSS_ATTR;
276 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
277 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
278 static const char audio_thread_name[] = "audio";
280 static void audio_thread(void);
281 static void audio_initiate_track_change(long direction);
282 static bool audio_have_tracks(void);
283 static void audio_reset_buffer(void);
284 static void audio_stop_playback(void);
286 /* Codec thread */
287 extern struct codec_api ci;
288 static struct event_queue codec_queue SHAREDBSS_ATTR;
289 static struct queue_sender_list codec_queue_sender_list;
290 static long codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)]
291 IBSS_ATTR;
292 static const char codec_thread_name[] = "codec";
293 unsigned int codec_thread_id; /* For modifying thread priority later. */
295 /* PCM buffer messaging */
296 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR;
298 /* Function to be called by pcm buffer callbacks.
299 * Permissible Context(s): Audio interrupt
301 static void pcmbuf_callback_queue_post(long id, intptr_t data)
303 /* No lock since we're already in audio interrupt context */
304 queue_post(&pcmbuf_queue, id, data);
307 /* Scan the pcmbuf queue and return true if a message pulled.
308 * Permissible Context(s): Thread
310 static bool pcmbuf_queue_scan(struct queue_event *ev)
312 if (!queue_empty(&pcmbuf_queue))
314 /* Transfer message to audio queue */
315 pcm_play_lock();
316 /* Pull message - never, ever any blocking call! */
317 queue_wait_w_tmo(&pcmbuf_queue, ev, 0);
318 pcm_play_unlock();
319 return true;
322 return false;
325 /* Clear the pcmbuf queue of messages
326 * Permissible Context(s): Thread
328 static void pcmbuf_queue_clear(void)
330 pcm_play_lock();
331 queue_clear(&pcmbuf_queue);
332 pcm_play_unlock();
335 /* --- Helper functions --- */
337 static struct mp3entry *bufgetid3(int handle_id)
339 if (handle_id < 0)
340 return NULL;
342 struct mp3entry *id3;
343 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
345 if (ret < 0 || ret != sizeof(struct mp3entry))
346 return NULL;
348 return id3;
351 static bool clear_track_info(struct track_info *track)
353 /* bufclose returns true if the handle is not found, or if it is closed
354 * successfully, so these checks are safe on non-existant handles */
355 if (!track)
356 return false;
358 if (track->codec_hid >= 0) {
359 if (bufclose(track->codec_hid))
360 track->codec_hid = -1;
361 else
362 return false;
365 if (track->id3_hid >= 0) {
366 if (bufclose(track->id3_hid))
367 track->id3_hid = -1;
368 else
369 return false;
372 if (track->audio_hid >= 0) {
373 if (bufclose(track->audio_hid))
374 track->audio_hid = -1;
375 else
376 return false;
379 #ifdef HAVE_ALBUMART
380 if (track->aa_hid >= 0) {
381 if (bufclose(track->aa_hid))
382 track->aa_hid = -1;
383 else
384 return false;
386 #endif
388 track->filesize = 0;
389 track->taginfo_ready = false;
391 return true;
394 /* --- External interfaces --- */
396 /* This sends a stop message and the audio thread will dump all it's
397 subsequenct messages */
398 void audio_hard_stop(void)
400 /* Stop playback */
401 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
402 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
403 #ifdef PLAYBACK_VOICE
404 voice_stop();
405 #endif
408 bool audio_restore_playback(int type)
410 switch (type)
412 case AUDIO_WANT_PLAYBACK:
413 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
414 audio_reset_buffer();
415 return true;
416 case AUDIO_WANT_VOICE:
417 if (buffer_state == AUDIOBUF_STATE_TRASHED)
418 audio_reset_buffer();
419 return true;
420 default:
421 return false;
425 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
427 unsigned char *buf, *end;
429 if (audio_is_initialized)
431 audio_hard_stop();
433 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
435 /* Reset the buffering thread so that it doesn't try to use the data */
436 buffering_reset(filebuf, filebuflen);
438 if (buffer_size == NULL)
440 /* Special case for talk_init to use since it already knows it's
441 trashed */
442 buffer_state = AUDIOBUF_STATE_TRASHED;
443 return NULL;
446 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
447 || !talk_voice_required())
449 logf("get buffer: talk, audio");
450 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
451 the talk buffer is not needed because voice isn't being used, or
452 could be AUDIOBUF_STATE_TRASHED already. If state is
453 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
454 without the caller knowing what's going on. Changing certain settings
455 may move it to a worse condition but the memory in use by something
456 else will remain undisturbed.
458 if (buffer_state != AUDIOBUF_STATE_TRASHED)
460 talk_buffer_steal();
461 buffer_state = AUDIOBUF_STATE_TRASHED;
464 buf = audiobuf;
465 end = audiobufend;
467 else
469 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
470 still AUDIOBUF_STATE_INITIALIZED */
471 /* Skip talk buffer and move pcm buffer to end to maximize available
472 contiguous memory - no audio running means voice will not need the
473 swap space */
474 logf("get buffer: audio");
475 buf = audiobuf + talk_get_bufsize();
476 end = audiobufend - pcmbuf_init(audiobufend);
477 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
480 *buffer_size = end - buf;
482 return buf;
485 int audio_buffer_state(void)
487 return buffer_state;
490 #ifdef HAVE_RECORDING
491 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
493 /* Stop audio, voice and obtain all available buffer space */
494 audio_hard_stop();
495 talk_buffer_steal();
497 unsigned char *end = audiobufend;
498 buffer_state = AUDIOBUF_STATE_TRASHED;
499 *buffer_size = end - audiobuf;
501 return (unsigned char *)audiobuf;
504 bool audio_load_encoder(int afmt)
506 #ifndef SIMULATOR
507 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
508 if (!enc_fn)
509 return false;
511 audio_remove_encoder();
512 ci.enc_codec_loaded = 0; /* clear any previous error condition */
514 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
515 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
517 while (ci.enc_codec_loaded == 0)
518 yield();
520 logf("codec loaded: %d", ci.enc_codec_loaded);
522 return ci.enc_codec_loaded > 0;
523 #else
524 (void)afmt;
525 return true;
526 #endif
527 } /* audio_load_encoder */
529 void audio_remove_encoder(void)
531 #ifndef SIMULATOR
532 /* force encoder codec unload (if currently loaded) */
533 if (ci.enc_codec_loaded <= 0)
534 return;
536 ci.stop_encoder = true;
537 while (ci.enc_codec_loaded > 0)
538 yield();
539 #endif
540 } /* audio_remove_encoder */
542 #endif /* HAVE_RECORDING */
544 #ifdef HAVE_ALBUMART
545 int audio_current_aa_hid(void)
547 int cur_idx;
548 int offset = ci.new_track + wps_offset;
550 cur_idx = track_ridx + offset;
551 cur_idx &= MAX_TRACK_MASK;
553 return tracks[cur_idx].aa_hid;
555 #endif
557 struct mp3entry* audio_current_track(void)
559 const char *filename;
560 struct playlist_track_info trackinfo;
561 int cur_idx;
562 int offset = ci.new_track + wps_offset;
564 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
566 if (cur_idx == track_ridx && *thistrack_id3->path)
568 /* The usual case */
569 return thistrack_id3;
571 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
573 /* We're in a track transition. The codec has moved on to the next track,
574 but the audio being played is still the same (now previous) track.
575 othertrack_id3.elapsed is being updated in an ISR by
576 codec_pcmbuf_position_callback */
577 return othertrack_id3;
579 else if (tracks[cur_idx].id3_hid >= 0)
581 /* The current track's info has been buffered but not read yet, so get it */
582 if (bufread(tracks[cur_idx].id3_hid, sizeof(struct mp3entry), thistrack_id3)
583 == sizeof(struct mp3entry))
584 return thistrack_id3;
587 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
588 we have and return that. */
590 memset(thistrack_id3, 0, sizeof(struct mp3entry));
592 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo);
593 filename = trackinfo.filename;
594 if (!filename)
595 filename = "No file!";
597 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
598 if (tagcache_fill_tags(thistrack_id3, filename))
599 return thistrack_id3;
600 #endif
602 strncpy(thistrack_id3->path, filename, sizeof(thistrack_id3->path)-1);
603 thistrack_id3->title = strrchr(thistrack_id3->path, '/');
604 if (!thistrack_id3->title)
605 thistrack_id3->title = &thistrack_id3->path[0];
606 else
607 thistrack_id3->title++;
609 return thistrack_id3;
612 struct mp3entry* audio_next_track(void)
614 int next_idx;
615 int offset = ci.new_track + wps_offset;
617 if (!audio_have_tracks())
618 return NULL;
620 if (wps_offset == -1 && *thistrack_id3->path)
622 /* We're in a track transition. The next track for the WPS is the one
623 currently being decoded. */
624 return thistrack_id3;
627 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
629 if (tracks[next_idx].id3_hid >= 0)
631 if (bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), othertrack_id3)
632 == sizeof(struct mp3entry))
633 return othertrack_id3;
634 else
635 return NULL;
638 if (next_idx == track_widx)
640 /* The next track hasn't been buffered yet, so we return the static
641 version of its metadata. */
642 return &unbuffered_id3;
645 return NULL;
648 void audio_play(long offset)
650 logf("audio_play");
652 #ifdef PLAYBACK_VOICE
653 /* Truncate any existing voice output so we don't have spelling
654 * etc. over the first part of the played track */
655 talk_force_shutup();
656 #endif
658 /* Start playback */
659 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
660 /* Don't return until playback has actually started */
661 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
664 void audio_stop(void)
666 /* Stop playback */
667 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
668 /* Don't return until playback has actually stopped */
669 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
672 void audio_pause(void)
674 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
675 /* Don't return until playback has actually paused */
676 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
679 void audio_resume(void)
681 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
682 /* Don't return until playback has actually resumed */
683 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
686 void audio_skip(int direction)
688 if (playlist_check(ci.new_track + wps_offset + direction))
690 if (global_settings.beep)
691 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
693 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction);
694 queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
695 /* Update wps while our message travels inside deep playback queues. */
696 wps_offset += direction;
698 else
700 /* No more tracks. */
701 if (global_settings.beep)
702 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
706 void audio_next(void)
708 audio_skip(1);
711 void audio_prev(void)
713 audio_skip(-1);
716 void audio_next_dir(void)
718 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
719 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
722 void audio_prev_dir(void)
724 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
725 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
728 void audio_pre_ff_rewind(void)
730 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
731 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
734 void audio_ff_rewind(long newpos)
736 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
737 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
740 void audio_flush_and_reload_tracks(void)
742 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
743 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
746 void audio_error_clear(void)
748 #ifdef AUDIO_HAVE_RECORDING
749 pcm_rec_error_clear();
750 #endif
753 int audio_status(void)
755 int ret = 0;
757 if (playing)
758 ret |= AUDIO_STATUS_PLAY;
760 if (paused)
761 ret |= AUDIO_STATUS_PAUSE;
763 #ifdef HAVE_RECORDING
764 /* Do this here for constitency with mpeg.c version */
765 ret |= pcm_rec_status();
766 #endif
768 return ret;
771 int audio_get_file_pos(void)
773 return 0;
776 #ifdef HAVE_DISK_STORAGE
777 void audio_set_buffer_margin(int setting)
779 static const int lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
780 buffer_margin = lookup[setting];
781 logf("buffer margin: %ld", (long)buffer_margin);
782 set_filebuf_watermark();
784 #endif
786 /* Take necessary steps to enable or disable the crossfade setting */
787 void audio_set_crossfade(int enable)
789 size_t offset;
790 bool was_playing;
791 size_t size;
793 /* Tell it the next setting to use */
794 pcmbuf_crossfade_enable(enable);
796 /* Return if size hasn't changed or this is too early to determine
797 which in the second case there's no way we could be playing
798 anything at all */
799 if (pcmbuf_is_same_size())
801 /* This function is a copout and just syncs some variables -
802 to be removed at a later date */
803 pcmbuf_crossfade_enable_finished();
804 return;
807 offset = 0;
808 was_playing = playing;
810 /* Playback has to be stopped before changing the buffer size */
811 if (was_playing)
813 /* Store the track resume position */
814 offset = thistrack_id3->offset;
817 /* Blast it - audio buffer will have to be setup again next time
818 something plays */
819 audio_get_buffer(true, &size);
821 /* Restart playback if audio was running previously */
822 if (was_playing)
823 audio_play(offset);
826 /* --- Routines called from multiple threads --- */
828 static void set_filebuf_watermark(void)
830 if (!filebuf)
831 return; /* Audio buffers not yet set up */
833 #ifdef HAVE_FLASH_STORAGE
834 int seconds = 1;
835 #else
836 int seconds;
837 int spinup = ata_spinup_time();
838 if (spinup)
839 seconds = (spinup / HZ) + 1;
840 else
841 seconds = 5;
842 #endif
844 /* bitrate of last track in buffer dictates watermark */
845 struct mp3entry* id3 = NULL;
846 if (tracks[track_widx].taginfo_ready)
847 id3 = bufgetid3(tracks[track_widx].id3_hid);
848 else
849 id3 = bufgetid3(tracks[track_widx-1].id3_hid);
850 if (!id3) {
851 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
852 return;
854 size_t bytes = id3->bitrate * (1000/8) * seconds;
855 buf_set_watermark(bytes);
856 logf("fwmark: %d", bytes);
859 const char *get_codec_filename(int cod_spec)
861 const char *fname;
863 #ifdef HAVE_RECORDING
864 /* Can choose decoder or encoder if one available */
865 int type = cod_spec & CODEC_TYPE_MASK;
866 int afmt = cod_spec & CODEC_AFMT_MASK;
868 if ((unsigned)afmt >= AFMT_NUM_CODECS)
869 type = AFMT_UNKNOWN | (type & CODEC_TYPE_MASK);
871 fname = (type == CODEC_TYPE_ENCODER) ?
872 audio_formats[afmt].codec_enc_root_fn :
873 audio_formats[afmt].codec_root_fn;
875 logf("%s: %d - %s",
876 (type == CODEC_TYPE_ENCODER) ? "Encoder" : "Decoder",
877 afmt, fname ? fname : "<unknown>");
878 #else /* !HAVE_RECORDING */
879 /* Always decoder */
880 if ((unsigned)cod_spec >= AFMT_NUM_CODECS)
881 cod_spec = AFMT_UNKNOWN;
882 fname = audio_formats[cod_spec].codec_root_fn;
883 logf("Codec: %d - %s", cod_spec, fname ? fname : "<unknown>");
884 #endif /* HAVE_RECORDING */
886 return fname;
887 } /* get_codec_filename */
889 /* --- Codec thread --- */
890 static bool codec_pcmbuf_insert_callback(
891 const void *ch1, const void *ch2, int count)
893 const char *src[2] = { ch1, ch2 };
895 while (count > 0)
897 int out_count = dsp_output_count(ci.dsp, count);
898 int inp_count;
899 char *dest;
901 /* Prevent audio from a previous track from playing */
902 if (ci.new_track || ci.stop_codec)
903 return true;
905 while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
907 cancel_cpu_boost();
908 sleep(1);
909 if (ci.seek_time || ci.new_track || ci.stop_codec)
910 return true;
913 /* Get the real input_size for output_size bytes, guarding
914 * against resampling buffer overflows. */
915 inp_count = dsp_input_count(ci.dsp, out_count);
917 if (inp_count <= 0)
918 return true;
920 /* Input size has grown, no error, just don't write more than length */
921 if (inp_count > count)
922 inp_count = count;
924 out_count = dsp_process(ci.dsp, dest, src, inp_count);
926 if (out_count <= 0)
927 return true;
929 pcmbuf_write_complete(out_count);
931 count -= inp_count;
934 return true;
935 } /* codec_pcmbuf_insert_callback */
937 static void* codec_get_buffer(size_t *size)
939 if (codec_size >= CODEC_SIZE)
940 return NULL;
941 *size = CODEC_SIZE - codec_size;
942 return &codecbuf[codec_size];
945 /* Between the codec and PCM track change, we need to keep updating the
946 "elapsed" value of the previous (to the codec, but current to the
947 user/PCM/WPS) track, so that the progressbar reaches the end.
948 During that transition, the WPS will display prevtrack_id3. */
949 static void codec_pcmbuf_position_callback(size_t size) ICODE_ATTR;
950 static void codec_pcmbuf_position_callback(size_t size)
952 /* This is called from an ISR, so be quick */
953 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
954 othertrack_id3->elapsed;
956 if (time >= othertrack_id3->length)
958 pcmbuf_set_position_callback(NULL);
959 othertrack_id3->elapsed = othertrack_id3->length;
961 else
962 othertrack_id3->elapsed = time;
965 static void codec_set_elapsed_callback(unsigned int value)
967 unsigned int latency;
968 if (ci.seek_time)
969 return;
971 #ifdef AB_REPEAT_ENABLE
972 ab_position_report(value);
973 #endif
975 latency = pcmbuf_get_latency();
976 if (value < latency)
977 thistrack_id3->elapsed = 0;
978 else if (value - latency > thistrack_id3->elapsed ||
979 value - latency < thistrack_id3->elapsed - 2)
981 thistrack_id3->elapsed = value - latency;
985 static void codec_set_offset_callback(size_t value)
987 unsigned int latency;
989 if (ci.seek_time)
990 return;
992 latency = pcmbuf_get_latency() * thistrack_id3->bitrate / 8;
993 if (value < latency)
994 thistrack_id3->offset = 0;
995 else
996 thistrack_id3->offset = value - latency;
999 static void codec_advance_buffer_counters(size_t amount)
1001 bufadvance(CUR_TI->audio_hid, amount);
1002 ci.curpos += amount;
1005 /* copy up-to size bytes into ptr and return the actual size copied */
1006 static size_t codec_filebuf_callback(void *ptr, size_t size)
1008 ssize_t copy_n;
1010 if (ci.stop_codec || !playing)
1011 return 0;
1013 copy_n = bufread(CUR_TI->audio_hid, size, ptr);
1015 /* Nothing requested OR nothing left */
1016 if (copy_n == 0)
1017 return 0;
1019 /* Update read and other position pointers */
1020 codec_advance_buffer_counters(copy_n);
1022 /* Return the actual amount of data copied to the buffer */
1023 return copy_n;
1024 } /* codec_filebuf_callback */
1026 static void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
1028 size_t copy_n = reqsize;
1029 ssize_t ret;
1030 void *ptr;
1032 if (!playing)
1034 *realsize = 0;
1035 return NULL;
1038 ret = bufgetdata(CUR_TI->audio_hid, reqsize, &ptr);
1039 if (ret >= 0)
1040 copy_n = MIN((size_t)ret, reqsize);
1042 if (copy_n == 0)
1044 *realsize = 0;
1045 return NULL;
1048 *realsize = copy_n;
1050 return ptr;
1051 } /* codec_request_buffer_callback */
1053 static int get_codec_base_type(int type)
1055 switch (type) {
1056 case AFMT_MPA_L1:
1057 case AFMT_MPA_L2:
1058 case AFMT_MPA_L3:
1059 return AFMT_MPA_L3;
1062 return type;
1065 static void codec_advance_buffer_callback(size_t amount)
1067 codec_advance_buffer_counters(amount);
1068 codec_set_offset_callback(ci.curpos);
1071 static void codec_advance_buffer_loc_callback(void *ptr)
1073 size_t amount = buf_get_offset(CUR_TI->audio_hid, ptr);
1074 codec_advance_buffer_callback(amount);
1077 static void codec_seek_complete_callback(void)
1079 logf("seek_complete");
1080 if (pcm_is_paused())
1082 /* If this is not a seamless seek, clear the buffer */
1083 pcmbuf_play_stop();
1084 dsp_configure(ci.dsp, DSP_FLUSH, 0);
1086 /* If playback was not 'deliberately' paused, unpause now */
1087 if (!paused)
1088 pcmbuf_pause(false);
1090 ci.seek_time = 0;
1093 static bool codec_seek_buffer_callback(size_t newpos)
1095 logf("codec_seek_buffer_callback");
1097 int ret = bufseek(CUR_TI->audio_hid, newpos);
1098 if (ret == 0) {
1099 ci.curpos = newpos;
1100 return true;
1102 else {
1103 return false;
1107 static void codec_configure_callback(int setting, intptr_t value)
1109 switch (setting) {
1110 default:
1111 if (!dsp_configure(ci.dsp, setting, value))
1112 { logf("Illegal key:%d", setting); }
1116 static void codec_track_changed(void)
1118 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1119 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1122 static void codec_pcmbuf_track_changed_callback(void)
1124 pcmbuf_set_position_callback(NULL);
1125 pcmbuf_callback_queue_post(Q_AUDIO_TRACK_CHANGED, 0);
1128 static void codec_discard_codec_callback(void)
1130 if (CUR_TI->codec_hid >= 0)
1132 bufclose(CUR_TI->codec_hid);
1133 CUR_TI->codec_hid = -1;
1137 static inline void codec_gapless_track_change(void)
1139 /* callback keeps the progress bar moving while the pcmbuf empties */
1140 pcmbuf_set_position_callback(codec_pcmbuf_position_callback);
1141 /* set the pcmbuf callback for when the track really changes */
1142 pcmbuf_set_event_handler(codec_pcmbuf_track_changed_callback);
1145 static inline void codec_crossfade_track_change(void)
1147 /* Initiate automatic crossfade mode */
1148 pcmbuf_crossfade_init(false);
1149 /* Notify the wps that the track change starts now */
1150 codec_track_changed();
1153 static void codec_track_skip_done(bool was_manual)
1155 /* Manual track change (always crossfade or flush audio). */
1156 if (was_manual)
1158 pcmbuf_crossfade_init(true);
1159 LOGFQUEUE("codec > audio Q_AUDIO_TRACK_CHANGED");
1160 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1162 /* Automatic track change w/crossfade, if not in "Track Skip Only" mode. */
1163 else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()
1164 && global_settings.crossfade != CROSSFADE_ENABLE_TRACKSKIP)
1166 if (global_settings.crossfade == CROSSFADE_ENABLE_SHUFFLE_AND_TRACKSKIP)
1168 if (global_settings.playlist_shuffle)
1169 /* shuffle mode is on, so crossfade: */
1170 codec_crossfade_track_change();
1171 else
1172 /* shuffle mode is off, so do a gapless track change */
1173 codec_gapless_track_change();
1175 else
1176 /* normal crossfade: */
1177 codec_crossfade_track_change();
1179 else
1180 /* normal gapless playback. */
1181 codec_gapless_track_change();
1184 static bool codec_load_next_track(void)
1186 intptr_t result = Q_CODEC_REQUEST_FAILED;
1188 prev_track_elapsed = thistrack_id3->elapsed;
1190 #ifdef AB_REPEAT_ENABLE
1191 ab_end_of_track_report();
1192 #endif
1194 logf("Request new track");
1196 if (ci.new_track == 0)
1198 ci.new_track++;
1199 automatic_skip = true;
1202 if (!ci.stop_codec)
1204 trigger_cpu_boost();
1205 LOGFQUEUE("codec >| audio Q_AUDIO_CHECK_NEW_TRACK");
1206 result = queue_send(&audio_queue, Q_AUDIO_CHECK_NEW_TRACK, 0);
1209 switch (result)
1211 case Q_CODEC_REQUEST_COMPLETE:
1212 LOGFQUEUE("codec |< Q_CODEC_REQUEST_COMPLETE");
1213 codec_track_skip_done(!automatic_skip);
1214 return true;
1216 case Q_CODEC_REQUEST_FAILED:
1217 LOGFQUEUE("codec |< Q_CODEC_REQUEST_FAILED");
1218 ci.new_track = 0;
1219 ci.stop_codec = true;
1220 codec_requested_stop = true;
1221 return false;
1223 default:
1224 LOGFQUEUE("codec |< default");
1225 ci.stop_codec = true;
1226 codec_requested_stop = true;
1227 return false;
1231 static bool codec_request_next_track_callback(void)
1233 int prev_codectype;
1235 if (ci.stop_codec || !playing)
1236 return false;
1238 prev_codectype = get_codec_base_type(thistrack_id3->codectype);
1239 if (!codec_load_next_track())
1240 return false;
1242 /* Seek to the beginning of the new track because if the struct
1243 mp3entry was buffered, "elapsed" might not be zero (if the track has
1244 been played already but not unbuffered) */
1245 codec_seek_buffer_callback(thistrack_id3->first_frame_offset);
1246 /* Check if the next codec is the same file. */
1247 if (prev_codectype == get_codec_base_type(thistrack_id3->codectype))
1249 logf("New track loaded");
1250 codec_discard_codec_callback();
1251 return true;
1253 else
1255 logf("New codec:%d/%d", thistrack_id3->codectype, prev_codectype);
1256 return false;
1260 static void codec_thread(void)
1262 struct queue_event ev;
1263 int status;
1265 while (1) {
1266 status = 0;
1268 if (!pcmbuf_is_crossfade_active()) {
1269 cancel_cpu_boost();
1272 queue_wait(&codec_queue, &ev);
1273 codec_requested_stop = false;
1275 switch (ev.id) {
1276 case Q_CODEC_LOAD_DISK:
1277 LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
1278 queue_reply(&codec_queue, 1);
1279 audio_codec_loaded = true;
1280 ci.stop_codec = false;
1281 status = codec_load_file((const char *)ev.data, &ci);
1282 LOGFQUEUE("codec_load_file %s %d\n", (const char *)ev.data, status);
1283 break;
1285 case Q_CODEC_LOAD:
1286 LOGFQUEUE("codec < Q_CODEC_LOAD");
1287 if (CUR_TI->codec_hid < 0) {
1288 logf("Codec slot is empty!");
1289 /* Wait for the pcm buffer to go empty */
1290 while (pcm_is_playing())
1291 yield();
1292 /* This must be set to prevent an infinite loop */
1293 ci.stop_codec = true;
1294 LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
1295 queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
1296 break;
1299 audio_codec_loaded = true;
1300 ci.stop_codec = false;
1301 status = codec_load_buf(CUR_TI->codec_hid, &ci);
1302 LOGFQUEUE("codec_load_buf %d\n", status);
1303 break;
1305 case Q_CODEC_DO_CALLBACK:
1306 LOGFQUEUE("codec < Q_CODEC_DO_CALLBACK");
1307 queue_reply(&codec_queue, 1);
1308 if ((void*)ev.data != NULL)
1310 cpucache_invalidate();
1311 ((void (*)(void))ev.data)();
1312 cpucache_flush();
1314 break;
1316 #ifdef AUDIO_HAVE_RECORDING
1317 case Q_ENCODER_LOAD_DISK:
1318 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1319 audio_codec_loaded = false; /* Not audio codec! */
1320 logf("loading encoder");
1321 ci.stop_encoder = false;
1322 status = codec_load_file((const char *)ev.data, &ci);
1323 logf("encoder stopped");
1324 break;
1325 #endif /* AUDIO_HAVE_RECORDING */
1327 default:
1328 LOGFQUEUE("codec < default");
1331 if (audio_codec_loaded)
1333 if (ci.stop_codec)
1335 status = CODEC_OK;
1336 if (!playing)
1337 pcmbuf_play_stop();
1340 audio_codec_loaded = false;
1343 switch (ev.id) {
1344 case Q_CODEC_LOAD_DISK:
1345 case Q_CODEC_LOAD:
1346 LOGFQUEUE("codec < Q_CODEC_LOAD");
1347 if (playing)
1349 if (ci.new_track || status != CODEC_OK)
1351 if (!ci.new_track)
1353 logf("Codec failure, %d %d", ci.new_track, status);
1354 splash(HZ*2, "Codec failure");
1357 if (!codec_load_next_track())
1359 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1360 /* End of playlist */
1361 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1362 break;
1365 else
1367 logf("Codec finished");
1368 if (ci.stop_codec)
1370 /* Wait for the audio to stop playing before
1371 * triggering the WPS exit */
1372 while(pcm_is_playing())
1374 /* There has been one too many struct pointer swaps by now
1375 * so even though it says othertrack_id3, its the correct one! */
1376 othertrack_id3->elapsed =
1377 othertrack_id3->length - pcmbuf_get_latency();
1378 sleep(1);
1381 if (codec_requested_stop)
1383 LOGFQUEUE("codec > audio Q_AUDIO_STOP");
1384 queue_post(&audio_queue, Q_AUDIO_STOP, 0);
1386 break;
1390 if (CUR_TI->codec_hid >= 0)
1392 LOGFQUEUE("codec > codec Q_CODEC_LOAD");
1393 queue_post(&codec_queue, Q_CODEC_LOAD, 0);
1395 else
1397 const char *codec_fn =
1398 get_codec_filename(thistrack_id3->codectype);
1399 if (codec_fn)
1401 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1402 queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
1403 (intptr_t)codec_fn);
1407 break;
1409 #ifdef AUDIO_HAVE_RECORDING
1410 case Q_ENCODER_LOAD_DISK:
1411 LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
1413 if (status == CODEC_OK)
1414 break;
1416 logf("Encoder failure");
1417 splash(HZ*2, "Encoder failure");
1419 if (ci.enc_codec_loaded < 0)
1420 break;
1422 logf("Encoder failed to load");
1423 ci.enc_codec_loaded = -1;
1424 break;
1425 #endif /* AUDIO_HAVE_RECORDING */
1427 default:
1428 LOGFQUEUE("codec < default");
1430 } /* end switch */
1434 /* Borrow the codec thread and return the ID */
1435 void codec_thread_do_callback(void (*fn)(void), unsigned int *id)
1437 /* Set id before telling thread to call something; it may be
1438 * needed before this function returns. */
1439 if (id != NULL)
1440 *id = codec_thread_id;
1442 /* Codec thread will signal just before entering callback */
1443 LOGFQUEUE("codec >| Q_CODEC_DO_CALLBACK");
1444 queue_send(&codec_queue, Q_CODEC_DO_CALLBACK, (intptr_t)fn);
1447 /* --- Buffering callbacks --- */
1449 static void buffering_low_buffer_callback(void *data)
1451 (void)data;
1452 logf("low buffer callback");
1454 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) {
1455 /* force a refill */
1456 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
1457 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1461 static void buffering_handle_rebuffer_callback(void *data)
1463 (void)data;
1464 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
1465 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
1468 static void buffering_handle_finished_callback(int *data)
1470 logf("handle %d finished buffering", *data);
1472 if (*data == tracks[track_widx].id3_hid)
1474 int offset = ci.new_track + wps_offset;
1475 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
1476 /* The metadata handle for the last loaded track has been buffered.
1477 We can ask the audio thread to load the rest of the track's data. */
1478 LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
1479 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
1480 if (tracks[next_idx].id3_hid == *data)
1481 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
1483 else
1485 /* This is most likely an audio handle, so we strip the useless
1486 trailing tags that are left. */
1487 strip_tags(*data);
1489 if (*data == tracks[track_widx-1].audio_hid
1490 && filling == STATE_END_OF_PLAYLIST)
1492 /* This was the last track in the playlist.
1493 We now have all the data we need. */
1494 logf("last track finished buffering");
1495 filling = STATE_FINISHED;
1501 /* --- Audio thread --- */
1503 static bool audio_have_tracks(void)
1505 return (audio_track_count() != 0);
1508 static int audio_free_track_count(void)
1510 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
1511 return MAX_TRACK - 1 - audio_track_count();
1514 int audio_track_count(void)
1516 /* Calculate difference from track_ridx to track_widx
1517 * taking into account a possible wrap-around. */
1518 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK;
1521 long audio_filebufused(void)
1523 return (long) buf_used();
1526 /* Update track info after successful a codec track change */
1527 static void audio_update_trackinfo(void)
1529 /* Load the curent track's metadata into curtrack_id3 */
1530 if (CUR_TI->id3_hid >= 0)
1531 copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid));
1533 /* Reset current position */
1534 thistrack_id3->elapsed = 0;
1535 thistrack_id3->offset = 0;
1537 /* Update the codec API */
1538 ci.filesize = CUR_TI->filesize;
1539 ci.id3 = thistrack_id3;
1540 ci.curpos = 0;
1541 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1544 /* Clear tracks between write and read, non inclusive */
1545 static void audio_clear_track_entries(void)
1547 int cur_idx = track_widx;
1549 logf("Clearing tracks:%d/%d", track_ridx, track_widx);
1551 /* Loop over all tracks from write-to-read */
1552 while (1)
1554 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1556 if (cur_idx == track_ridx)
1557 break;
1559 clear_track_info(&tracks[cur_idx]);
1563 /* Clear all tracks */
1564 static bool audio_release_tracks(void)
1566 int i, cur_idx;
1568 logf("releasing all tracks");
1570 for(i = 0; i < MAX_TRACK; i++)
1572 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
1573 if (!clear_track_info(&tracks[cur_idx]))
1574 return false;
1577 return true;
1580 static bool audio_loadcodec(bool start_play)
1582 int prev_track;
1583 char codec_path[MAX_PATH]; /* Full path to codec */
1584 const struct mp3entry *id3, *prev_id3;
1586 if (tracks[track_widx].id3_hid < 0) {
1587 return false;
1590 id3 = bufgetid3(tracks[track_widx].id3_hid);
1591 if (!id3)
1592 return false;
1594 const char *codec_fn = get_codec_filename(id3->codectype);
1595 if (codec_fn == NULL)
1596 return false;
1598 tracks[track_widx].codec_hid = -1;
1600 if (start_play)
1602 /* Load the codec directly from disk and save some memory. */
1603 track_ridx = track_widx;
1604 ci.filesize = CUR_TI->filesize;
1605 ci.id3 = thistrack_id3;
1606 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1607 ci.curpos = 0;
1608 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1609 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
1610 return true;
1612 else
1614 /* If we already have another track than this one buffered */
1615 if (track_widx != track_ridx)
1617 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1619 id3 = bufgetid3(tracks[track_widx].id3_hid);
1620 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1622 /* If the previous codec is the same as this one, there is no need
1623 * to put another copy of it on the file buffer */
1624 if (id3 && prev_id3 &&
1625 get_codec_base_type(id3->codectype) ==
1626 get_codec_base_type(prev_id3->codectype)
1627 && audio_codec_loaded)
1629 logf("Reusing prev. codec");
1630 return true;
1635 codec_get_full_path(codec_path, codec_fn);
1637 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC);
1638 if (tracks[track_widx].codec_hid < 0)
1639 return false;
1641 logf("Loaded codec");
1643 return true;
1646 /* Load metadata for the next track (with bufopen). The rest of the track
1647 loading will be handled by audio_finish_load_track once the metadata has been
1648 actually loaded by the buffering thread. */
1649 static bool audio_load_track(size_t offset, bool start_play)
1651 const char *trackname;
1652 int fd = -1;
1654 if (track_load_started) {
1655 /* There is already a track load in progress, so track_widx hasn't been
1656 incremented yet. Loading another track would overwrite the one that
1657 hasn't finished loading. */
1658 logf("audio_load_track(): a track load is already in progress");
1659 return false;
1662 start_play_g = start_play; /* will be read by audio_finish_load_track */
1664 /* Stop buffer filling if there is no free track entries.
1665 Don't fill up the last track entry (we wan't to store next track
1666 metadata there). */
1667 if (!audio_free_track_count())
1669 logf("No free tracks");
1670 return false;
1673 last_peek_offset++;
1674 tracks[track_widx].taginfo_ready = false;
1676 logf("Buffering track:%d/%d", track_widx, track_ridx);
1677 /* Get track name from current playlist read position. */
1678 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
1680 /* Handle broken playlists. */
1681 fd = open(trackname, O_RDONLY);
1682 if (fd < 0)
1684 logf("Open failed");
1685 /* Skip invalid entry from playlist. */
1686 playlist_skip_entry(NULL, last_peek_offset);
1688 else
1689 break;
1692 if (!trackname)
1694 logf("End-of-playlist");
1695 memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
1696 filling = STATE_END_OF_PLAYLIST;
1698 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
1700 /* Stop playback if no valid track was found. */
1701 audio_stop_playback();
1704 return false;
1707 tracks[track_widx].filesize = filesize(fd);
1709 if (offset > tracks[track_widx].filesize)
1710 offset = 0;
1712 /* Set default values */
1713 if (start_play)
1715 buf_set_watermark(filebuflen/2);
1716 dsp_configure(ci.dsp, DSP_RESET, 0);
1717 playlist_update_resume_info(audio_current_track());
1720 /* Get track metadata if we don't already have it. */
1721 if (tracks[track_widx].id3_hid < 0)
1723 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3);
1725 if (tracks[track_widx].id3_hid < 0)
1727 /* Buffer is full. */
1728 get_metadata(&unbuffered_id3, fd, trackname);
1729 last_peek_offset--;
1730 close(fd);
1731 logf("buffer is full for now");
1732 filling = STATE_FULL;
1733 return false;
1736 if (track_widx == track_ridx)
1738 /* TODO: Superfluos buffering call? */
1739 buf_request_buffer_handle(tracks[track_widx].id3_hid);
1740 struct mp3entry *id3 = bufgetid3(tracks[track_widx].id3_hid);
1741 if (id3)
1743 copy_mp3entry(thistrack_id3, id3);
1744 thistrack_id3->offset = offset;
1746 else
1747 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1750 if (start_play)
1752 playlist_update_resume_info(audio_current_track());
1756 close(fd);
1757 track_load_started = true; /* Remember that we've started loading a track */
1758 return true;
1761 /* Second part of the track loading: We now have the metadata available, so we
1762 can load the codec, the album art and finally the audio data.
1763 This is called on the audio thread after the buffering thread calls the
1764 buffering_handle_finished_callback callback. */
1765 static void audio_finish_load_track(void)
1767 size_t file_offset = 0;
1768 size_t offset = 0;
1769 bool start_play = start_play_g;
1771 track_load_started = false;
1773 if (tracks[track_widx].id3_hid < 0) {
1774 logf("no metatdata");
1775 return;
1778 struct mp3entry *track_id3;
1780 if (track_widx == track_ridx)
1781 track_id3 = thistrack_id3;
1782 else
1783 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
1785 if (track_id3->length == 0 && track_id3->filesize == 0)
1787 logf("audio_finish_load_track: invalid metadata");
1789 /* Invalid metadata */
1790 bufclose(tracks[track_widx].id3_hid);
1791 tracks[track_widx].id3_hid = -1;
1793 /* Skip invalid entry from playlist. */
1794 playlist_skip_entry(NULL, last_peek_offset--);
1796 /* load next track */
1797 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play);
1798 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1800 return;
1803 #ifdef HAVE_ALBUMART
1804 if (tracks[track_widx].aa_hid < 0 && gui_sync_wps_uses_albumart())
1806 char aa_path[MAX_PATH];
1807 if (find_albumart(track_id3, aa_path, sizeof(aa_path)))
1809 tracks[track_widx].aa_hid = bufopen(aa_path, 0, TYPE_BITMAP);
1811 if(tracks[track_widx].aa_hid == ERR_BUFFER_FULL)
1813 filling = STATE_FULL;
1814 logf("buffer is full for now");
1815 return; /* No space for track's album art, not an error */
1817 else if (tracks[track_widx].aa_hid < 0)
1819 /* another error, ignore AlbumArt */
1820 logf("Album art loading failed");
1824 #endif
1826 /* Load the codec. */
1827 if (!audio_loadcodec(start_play))
1829 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1831 /* No space for codec on buffer, not an error */
1832 filling = STATE_FULL;
1833 return;
1836 /* This is an error condition, either no codec was found, or reading
1837 * the codec file failed part way through, either way, skip the track */
1838 /* FIXME: We should not use splashf from audio thread! */
1839 splashf(HZ*2, "No codec for: %s", track_id3->path);
1840 /* Skip invalid entry from playlist. */
1841 playlist_skip_entry(NULL, last_peek_offset);
1842 return;
1845 track_id3->elapsed = 0;
1846 offset = track_id3->offset;
1848 enum data_type type = TYPE_PACKET_AUDIO;
1850 switch (track_id3->codectype) {
1851 case AFMT_MPA_L1:
1852 case AFMT_MPA_L2:
1853 case AFMT_MPA_L3:
1854 if (offset > 0) {
1855 file_offset = offset;
1856 track_id3->offset = offset;
1858 break;
1860 case AFMT_WAVPACK:
1861 if (offset > 0) {
1862 file_offset = offset;
1863 track_id3->offset = offset;
1864 track_id3->elapsed = track_id3->length / 2;
1866 break;
1868 case AFMT_OGG_VORBIS:
1869 case AFMT_SPEEX:
1870 case AFMT_FLAC:
1871 case AFMT_PCM_WAV:
1872 case AFMT_A52:
1873 case AFMT_AAC:
1874 case AFMT_MPC:
1875 case AFMT_APE:
1876 case AFMT_WMA:
1877 if (offset > 0)
1878 track_id3->offset = offset;
1879 break;
1881 case AFMT_NSF:
1882 case AFMT_SPC:
1883 case AFMT_SID:
1884 logf("Loading atomic %d",track_id3->codectype);
1885 type = TYPE_ATOMIC_AUDIO;
1886 break;
1889 logf("alt:%s", track_id3->path);
1891 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1892 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1893 else if (track_id3->first_frame_offset)
1894 file_offset = track_id3->first_frame_offset;
1895 else
1896 file_offset = 0;
1898 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type);
1900 /* No space left, not an error */
1901 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1903 filling = STATE_FULL;
1904 logf("buffer is full for now");
1905 return;
1907 else if (tracks[track_widx].audio_hid < 0)
1909 /* another error, do not continue either */
1910 logf("Could not add audio data handle");
1911 return;
1914 /* All required data is now available for the codec. */
1915 tracks[track_widx].taginfo_ready = true;
1917 if (start_play)
1919 ci.curpos=file_offset;
1920 buf_request_buffer_handle(tracks[track_widx].audio_hid);
1923 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1925 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
1927 /* load next track */
1928 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1929 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1931 return;
1934 static void audio_fill_file_buffer(bool start_play, size_t offset)
1936 filling = STATE_FILLING;
1937 trigger_cpu_boost();
1939 /* No need to rebuffer if there are track skips pending. */
1940 if (ci.new_track != 0)
1941 return;
1943 /* Must reset the buffer before use if trashed or voice only - voice
1944 file size shouldn't have changed so we can go straight from
1945 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1946 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1947 audio_reset_buffer();
1949 logf("Starting buffer fill");
1951 if (!start_play)
1952 audio_clear_track_entries();
1954 /* Save the current resume position once. */
1955 playlist_update_resume_info(audio_current_track());
1957 audio_load_track(offset, start_play);
1960 static void audio_rebuffer(void)
1962 logf("Forcing rebuffer");
1964 clear_track_info(CUR_TI);
1966 /* Reset track pointers */
1967 track_widx = track_ridx;
1968 audio_clear_track_entries();
1970 /* Reset a possibly interrupted track load */
1971 track_load_started = false;
1973 /* Fill the buffer */
1974 last_peek_offset = -1;
1975 ci.curpos = 0;
1977 if (!CUR_TI->taginfo_ready)
1978 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1980 audio_fill_file_buffer(false, 0);
1983 /* Called on request from the codec to get a new track. This is the codec part
1984 of the track transition. */
1985 static int audio_check_new_track(void)
1987 int track_count = audio_track_count();
1988 int old_track_ridx = track_ridx;
1989 int i, idx;
1990 bool forward;
1991 struct mp3entry *temp = thistrack_id3;
1993 /* Now it's good time to send track finish events. */
1994 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1995 /* swap the mp3entry pointers */
1996 thistrack_id3 = othertrack_id3;
1997 othertrack_id3 = temp;
1998 ci.id3 = thistrack_id3;
1999 memset(thistrack_id3, 0, sizeof(struct mp3entry));
2001 if (dir_skip)
2003 dir_skip = false;
2004 /* regardless of the return value we need to rebuffer.
2005 if it fails the old playlist will resume, else the
2006 next dir will start playing */
2007 playlist_next_dir(ci.new_track);
2008 ci.new_track = 0;
2009 audio_rebuffer();
2010 goto skip_done;
2013 if (new_playlist)
2014 ci.new_track = 0;
2016 /* If the playlist isn't that big */
2017 if (automatic_skip)
2019 while (!playlist_check(ci.new_track))
2021 if (ci.new_track >= 0)
2023 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2024 return Q_CODEC_REQUEST_FAILED;
2026 ci.new_track++;
2030 /* Update the playlist */
2031 last_peek_offset -= ci.new_track;
2033 if (playlist_next(ci.new_track) < 0)
2035 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
2036 return Q_CODEC_REQUEST_FAILED;
2039 if (new_playlist)
2041 ci.new_track = 1;
2042 new_playlist = false;
2045 /* Save a pointer to the old track to allow later clearing */
2046 prev_ti = CUR_TI;
2048 for (i = 0; i < ci.new_track; i++)
2050 idx = (track_ridx + i) & MAX_TRACK_MASK;
2051 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid);
2052 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid);
2053 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset)
2055 /* We don't have all the audio data for that track, so clear it,
2056 but keep the metadata. */
2057 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
2059 tracks[idx].audio_hid = -1;
2060 tracks[idx].filesize = 0;
2065 /* Move to the new track */
2066 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
2068 buf_set_base_handle(CUR_TI->audio_hid);
2070 if (automatic_skip)
2072 wps_offset = -ci.new_track;
2075 /* If it is not safe to even skip this many track entries */
2076 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
2078 ci.new_track = 0;
2079 audio_rebuffer();
2080 goto skip_done;
2083 forward = ci.new_track > 0;
2084 ci.new_track = 0;
2086 /* If the target track is clearly not in memory */
2087 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
2089 audio_rebuffer();
2090 goto skip_done;
2093 /* When skipping backwards, it is possible that we've found a track that's
2094 * buffered, but which is around the track-wrap and therefore not the track
2095 * we are looking for */
2096 if (!forward)
2098 int cur_idx = track_ridx;
2099 bool taginfo_ready = true;
2100 /* We've wrapped the buffer backwards if new > old */
2101 bool wrap = track_ridx > old_track_ridx;
2103 while (1)
2105 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
2107 /* if we've advanced past the wrap when cur_idx is zeroed */
2108 if (!cur_idx)
2109 wrap = false;
2111 /* if we aren't still on the wrap and we've caught the old track */
2112 if (!(wrap || cur_idx < old_track_ridx))
2113 break;
2115 /* If we hit a track in between without valid tag info, bail */
2116 if (!tracks[cur_idx].taginfo_ready)
2118 taginfo_ready = false;
2119 break;
2122 if (!taginfo_ready)
2124 audio_rebuffer();
2128 skip_done:
2129 audio_update_trackinfo();
2130 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
2131 return Q_CODEC_REQUEST_COMPLETE;
2134 unsigned long audio_prev_elapsed(void)
2136 return prev_track_elapsed;
2139 static void audio_stop_codec_flush(void)
2141 ci.stop_codec = true;
2142 pcmbuf_pause(true);
2144 while (audio_codec_loaded)
2145 yield();
2147 /* If the audio codec is not loaded any more, and the audio is still
2148 * playing, it is now and _only_ now safe to call this function from the
2149 * audio thread */
2150 if (pcm_is_playing())
2152 pcmbuf_play_stop();
2153 pcmbuf_queue_clear();
2155 pcmbuf_pause(paused);
2158 static void audio_stop_playback(void)
2160 /* If we were playing, save resume information */
2161 if (playing)
2163 struct mp3entry *id3 = NULL;
2165 if (!ci.stop_codec)
2167 /* Set this early, the outside code yields and may allow the codec
2168 to try to wait for a reply on a buffer wait */
2169 ci.stop_codec = true;
2170 id3 = audio_current_track();
2173 /* Save the current playing spot, or NULL if the playlist has ended */
2174 playlist_update_resume_info(id3);
2176 /* TODO: Create auto bookmark too? */
2178 prev_track_elapsed = othertrack_id3->elapsed;
2180 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
2183 audio_stop_codec_flush();
2184 paused = false;
2185 playing = false;
2186 track_load_started = false;
2188 filling = STATE_IDLE;
2190 /* Mark all entries null. */
2191 audio_clear_track_entries();
2193 /* Close all tracks */
2194 audio_release_tracks();
2197 static void audio_play_start(size_t offset)
2199 int i;
2201 #if INPUT_SRC_CAPS != 0
2202 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
2203 audio_set_output_source(AUDIO_SRC_PLAYBACK);
2204 #endif
2206 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
2207 paused = false;
2208 audio_stop_codec_flush();
2210 playing = true;
2211 track_load_started = false;
2213 ci.new_track = 0;
2214 ci.seek_time = 0;
2215 wps_offset = 0;
2217 sound_set_volume(global_settings.volume);
2218 track_widx = track_ridx = 0;
2220 /* Clear all track entries. */
2221 for (i = 0; i < MAX_TRACK; i++) {
2222 clear_track_info(&tracks[i]);
2225 last_peek_offset = -1;
2227 /* Officially playing */
2228 queue_reply(&audio_queue, 1);
2230 audio_fill_file_buffer(true, offset);
2232 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
2234 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
2235 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
2239 /* Invalidates all but currently playing track. */
2240 static void audio_invalidate_tracks(void)
2242 if (audio_have_tracks())
2244 last_peek_offset = 0;
2245 track_widx = track_ridx;
2247 /* Mark all other entries null (also buffered wrong metadata). */
2248 audio_clear_track_entries();
2250 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
2252 audio_fill_file_buffer(false, 0);
2256 static void audio_new_playlist(void)
2258 /* Prepare to start a new fill from the beginning of the playlist */
2259 last_peek_offset = -1;
2260 if (audio_have_tracks())
2262 if (paused)
2263 skipped_during_pause = true;
2264 track_widx = track_ridx;
2265 audio_clear_track_entries();
2267 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
2269 /* Mark the current track as invalid to prevent skipping back to it */
2270 CUR_TI->taginfo_ready = false;
2273 /* Signal the codec to initiate a track change forward */
2274 new_playlist = true;
2275 ci.new_track = 1;
2277 /* Officially playing */
2278 queue_reply(&audio_queue, 1);
2280 audio_fill_file_buffer(false, 0);
2283 /* Called on manual track skip */
2284 static void audio_initiate_track_change(long direction)
2286 logf("audio_initiate_track_change(%ld)", direction);
2288 ci.new_track += direction;
2289 wps_offset -= direction;
2290 if (paused)
2291 skipped_during_pause = true;
2294 /* Called on manual dir skip */
2295 static void audio_initiate_dir_change(long direction)
2297 dir_skip = true;
2298 ci.new_track = direction;
2299 if (paused)
2300 skipped_during_pause = true;
2303 /* Called when PCM track change is complete */
2304 static void audio_finalise_track_change(void)
2306 logf("audio_finalise_track_change");
2308 if (automatic_skip)
2310 wps_offset = 0;
2311 automatic_skip = false;
2313 /* Invalidate prevtrack_id3 */
2314 memset(othertrack_id3, 0, sizeof(struct mp3entry));
2316 if (prev_ti && prev_ti->audio_hid < 0)
2318 /* No audio left so we clear all the track info. */
2319 clear_track_info(prev_ti);
2322 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
2323 playlist_update_resume_info(audio_current_track());
2327 * Layout audio buffer as follows - iram buffer depends on target:
2328 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
2330 static void audio_reset_buffer(void)
2332 /* see audio_get_recording_buffer if this is modified */
2333 logf("audio_reset_buffer");
2335 /* If the setup of anything allocated before the file buffer is
2336 changed, do check the adjustments after the buffer_alloc call
2337 as it will likely be affected and need sliding over */
2339 /* Initially set up file buffer as all space available */
2340 malloc_buf = audiobuf + talk_get_bufsize();
2341 /* Align the malloc buf to line size. Especially important to cf
2342 targets that do line reads/writes. */
2343 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
2344 filebuf = malloc_buf; /* filebuf line align implied */
2345 filebuflen = audiobufend - filebuf;
2347 filebuflen &= ~15;
2349 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
2350 const size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) +GUARD_BUFSIZE;
2352 #ifdef DEBUG
2353 if(pcmbuf_size > filebuflen)
2354 panicf("Not enough memory for pcmbuf_init() : %d > %d",
2355 (int)pcmbuf_size, (int)filebuflen);
2356 #endif
2358 filebuflen -= pcmbuf_size;
2360 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
2361 will already be line aligned */
2362 filebuflen &= ~3;
2364 buffering_reset(filebuf, filebuflen);
2366 /* Clear any references to the file buffer */
2367 buffer_state = AUDIOBUF_STATE_INITIALIZED;
2369 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
2370 /* Make sure everything adds up - yes, some info is a bit redundant but
2371 aids viewing and the sumation of certain variables should add up to
2372 the location of others. */
2374 size_t pcmbufsize;
2375 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
2376 logf("mabuf: %08X", (unsigned)malloc_buf);
2377 logf("fbuf: %08X", (unsigned)filebuf);
2378 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
2379 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
2380 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
2381 logf("pcmb: %08X", (unsigned)pcmbuf);
2382 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
2384 #endif
2387 static void audio_thread(void)
2389 struct queue_event ev;
2391 pcm_postinit();
2393 audio_thread_ready = true;
2395 while (1)
2397 if (filling != STATE_FILLING) {
2398 /* End of buffering, let's calculate the watermark and unboost */
2399 set_filebuf_watermark();
2400 cancel_cpu_boost();
2403 if (!pcmbuf_queue_scan(&ev))
2404 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
2406 switch (ev.id) {
2408 case Q_AUDIO_FILL_BUFFER:
2409 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
2410 audio_fill_file_buffer((bool)ev.data, 0);
2411 break;
2413 case Q_AUDIO_FINISH_LOAD:
2414 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
2415 audio_finish_load_track();
2416 break;
2418 case Q_AUDIO_PLAY:
2419 LOGFQUEUE("audio < Q_AUDIO_PLAY");
2420 if (playing && ev.data <= 0)
2421 audio_new_playlist();
2422 else
2424 audio_stop_playback();
2425 audio_play_start((size_t)ev.data);
2427 break;
2429 case Q_AUDIO_STOP:
2430 LOGFQUEUE("audio < Q_AUDIO_STOP");
2431 if (playing)
2432 audio_stop_playback();
2433 if (ev.data != 0)
2434 queue_clear(&audio_queue);
2435 break;
2437 case Q_AUDIO_PAUSE:
2438 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
2439 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
2440 pcmbuf_play_stop(); /* Flush old track on resume after skip */
2441 skipped_during_pause = false;
2442 if (!playing)
2443 break;
2444 pcmbuf_pause((bool)ev.data);
2445 paused = (bool)ev.data;
2446 break;
2448 case Q_AUDIO_SKIP:
2449 LOGFQUEUE("audio < Q_AUDIO_SKIP");
2450 audio_initiate_track_change((long)ev.data);
2451 break;
2453 case Q_AUDIO_PRE_FF_REWIND:
2454 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
2455 if (!playing)
2456 break;
2457 pcmbuf_pause(true);
2458 break;
2460 case Q_AUDIO_FF_REWIND:
2461 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
2462 if (!playing)
2463 break;
2464 if (automatic_skip)
2466 /* An automatic track skip is in progress. Finalize it,
2467 then go back to the previous track */
2468 audio_finalise_track_change();
2469 ci.new_track = -1;
2471 ci.seek_time = (long)ev.data+1;
2472 break;
2474 case Q_AUDIO_CHECK_NEW_TRACK:
2475 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
2476 queue_reply(&audio_queue, audio_check_new_track());
2477 break;
2479 case Q_AUDIO_DIR_SKIP:
2480 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
2481 audio_initiate_dir_change(ev.data);
2482 break;
2484 case Q_AUDIO_FLUSH:
2485 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
2486 audio_invalidate_tracks();
2487 break;
2489 case Q_AUDIO_TRACK_CHANGED:
2490 /* PCM track change done */
2491 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
2492 audio_finalise_track_change();
2493 break;
2495 #ifndef SIMULATOR
2496 case SYS_USB_CONNECTED:
2497 LOGFQUEUE("audio < SYS_USB_CONNECTED");
2498 if (playing)
2499 audio_stop_playback();
2500 #ifdef PLAYBACK_VOICE
2501 voice_stop();
2502 #endif
2503 usb_acknowledge(SYS_USB_CONNECTED_ACK);
2504 usb_wait_for_disconnect(&audio_queue);
2506 /* Mark all entries null. */
2507 audio_clear_track_entries();
2509 /* release tracks to make sure all handles are closed */
2510 audio_release_tracks();
2511 break;
2512 #endif
2514 case SYS_TIMEOUT:
2515 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
2516 break;
2518 default:
2519 LOGFQUEUE("audio < default");
2520 break;
2521 } /* end switch */
2522 } /* end while */
2525 /* Initialize the audio system - called from init() in main.c.
2526 * Last function because of all the references to internal symbols
2528 void audio_init(void)
2530 unsigned int audio_thread_id;
2532 /* Can never do this twice */
2533 if (audio_is_initialized)
2535 logf("audio: already initialized");
2536 return;
2539 logf("audio: initializing");
2541 /* Initialize queues before giving control elsewhere in case it likes
2542 to send messages. Thread creation will be delayed however so nothing
2543 starts running until ready if something yields such as talk_init. */
2544 queue_init(&audio_queue, true);
2545 queue_init(&codec_queue, false);
2546 queue_init(&pcmbuf_queue, false);
2548 pcm_init();
2550 /* Initialize codec api. */
2551 ci.read_filebuf = codec_filebuf_callback;
2552 ci.pcmbuf_insert = codec_pcmbuf_insert_callback;
2553 ci.codec_get_buffer = codec_get_buffer;
2554 ci.request_buffer = codec_request_buffer_callback;
2555 ci.advance_buffer = codec_advance_buffer_callback;
2556 ci.advance_buffer_loc = codec_advance_buffer_loc_callback;
2557 ci.request_next_track = codec_request_next_track_callback;
2558 ci.seek_buffer = codec_seek_buffer_callback;
2559 ci.seek_complete = codec_seek_complete_callback;
2560 ci.set_elapsed = codec_set_elapsed_callback;
2561 ci.set_offset = codec_set_offset_callback;
2562 ci.configure = codec_configure_callback;
2563 ci.discard_codec = codec_discard_codec_callback;
2564 ci.dsp = (struct dsp_config *)dsp_configure(NULL, DSP_MYDSP,
2565 CODEC_IDX_AUDIO);
2567 thistrack_id3 = &mp3entry_buf[0];
2568 othertrack_id3 = &mp3entry_buf[1];
2570 /* initialize the buffer */
2571 filebuf = audiobuf;
2573 /* audio_reset_buffer must to know the size of voice buffer so init
2574 talk first */
2575 talk_init();
2577 codec_thread_id = create_thread(
2578 codec_thread, codec_stack, sizeof(codec_stack),
2579 CREATE_THREAD_FROZEN,
2580 codec_thread_name IF_PRIO(, PRIORITY_PLAYBACK)
2581 IF_COP(, CPU));
2583 queue_enable_queue_send(&codec_queue, &codec_queue_sender_list,
2584 codec_thread_id);
2586 audio_thread_id = create_thread(audio_thread, audio_stack,
2587 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2588 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
2589 IF_COP(, CPU));
2591 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
2592 audio_thread_id);
2594 #ifdef PLAYBACK_VOICE
2595 voice_thread_init();
2596 #endif
2598 /* Set crossfade setting for next buffer init which should be about... */
2599 pcmbuf_crossfade_enable(global_settings.crossfade);
2601 /* initialize the buffering system */
2603 buffering_init();
2604 /* ...now! Set up the buffers */
2605 audio_reset_buffer();
2607 int i;
2608 for(i = 0; i < MAX_TRACK; i++)
2610 tracks[i].audio_hid = -1;
2611 tracks[i].id3_hid = -1;
2612 tracks[i].codec_hid = -1;
2613 #ifdef HAVE_ALBUMART
2614 tracks[i].aa_hid = -1;
2615 #endif
2618 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2619 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2621 /* Probably safe to say */
2622 audio_is_initialized = true;
2624 sound_settings_apply();
2625 #ifdef HAVE_DISK_STORAGE
2626 audio_set_buffer_margin(global_settings.buffer_margin);
2627 #endif
2629 /* it's safe to let the threads run now */
2630 #ifdef PLAYBACK_VOICE
2631 voice_thread_resume();
2632 #endif
2633 thread_thaw(codec_thread_id);
2634 thread_thaw(audio_thread_id);
2636 } /* audio_init */
2638 bool audio_is_thread_ready(void)
2640 return audio_thread_ready;