fix typo in manual. thanks to mc2739 for noticing.
[kugel-rb.git] / apps / playback.c
blobfbaaa5c974a29d3fd0dcd5e7808dc74e08681c8d
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 <string.h>
27 #include "playback.h"
28 #include "codec_thread.h"
29 #include "kernel.h"
30 #include "codecs.h"
31 #include "buffering.h"
32 #include "voice_thread.h"
33 #include "usb.h"
34 #include "ata.h"
35 #include "playlist.h"
36 #include "pcmbuf.h"
37 #include "buffer.h"
38 #include "cuesheet.h"
39 #ifdef HAVE_TAGCACHE
40 #include "tagcache.h"
41 #endif
42 #ifdef HAVE_LCD_BITMAP
43 #ifdef HAVE_ALBUMART
44 #include "albumart.h"
45 #endif
46 #endif
47 #include "sound.h"
48 #include "metadata.h"
49 #include "splash.h"
50 #include "talk.h"
52 #ifdef HAVE_RECORDING
53 #include "pcm_record.h"
54 #endif
56 #define PLAYBACK_VOICE
58 /* amount of guess-space to allow for codecs that must hunt and peck
59 * for their correct seeek target, 32k seems a good size */
60 #define AUDIO_REBUFFER_GUESS_SIZE (1024*32)
62 /* Define LOGF_ENABLE to enable logf output in this file */
63 /*#define LOGF_ENABLE*/
64 #include "logf.h"
66 /* macros to enable logf for queues
67 logging on SYS_TIMEOUT can be disabled */
68 #ifdef SIMULATOR
69 /* Define this for logf output of all queuing except SYS_TIMEOUT */
70 #define PLAYBACK_LOGQUEUES
71 /* Define this to logf SYS_TIMEOUT messages */
72 /*#define PLAYBACK_LOGQUEUES_SYS_TIMEOUT*/
73 #endif
75 #ifdef PLAYBACK_LOGQUEUES
76 #define LOGFQUEUE logf
77 #else
78 #define LOGFQUEUE(...)
79 #endif
81 #ifdef PLAYBACK_LOGQUEUES_SYS_TIMEOUT
82 #define LOGFQUEUE_SYS_TIMEOUT logf
83 #else
84 #define LOGFQUEUE_SYS_TIMEOUT(...)
85 #endif
88 static enum filling_state {
89 STATE_IDLE, /* audio is stopped: nothing to do */
90 STATE_FILLING, /* adding tracks to the buffer */
91 STATE_FULL, /* can't add any more tracks */
92 STATE_END_OF_PLAYLIST, /* all remaining tracks have been added */
93 STATE_FINISHED, /* all remaining tracks are fully buffered */
94 } filling;
96 /* As defined in plugins/lib/xxx2wav.h */
97 #define GUARD_BUFSIZE (32*1024)
99 bool audio_is_initialized = false;
100 static bool audio_thread_ready SHAREDBSS_ATTR = false;
102 /* Variables are commented with the threads that use them: *
103 * A=audio, C=codec, V=voice. A suffix of - indicates that *
104 * the variable is read but not updated on that thread. */
105 /* TBD: Split out "audio" and "playback" (ie. calling) threads */
107 /* Main state control */
108 static volatile bool playing SHAREDBSS_ATTR = false;/* Is audio playing? (A) */
109 static volatile bool paused SHAREDBSS_ATTR = false; /* Is audio paused? (A/C-) */
110 extern volatile bool audio_codec_loaded; /* Codec loaded? (C/A-) */
112 /* Ring buffer where compressed audio and codecs are loaded */
113 static unsigned char *filebuf = NULL; /* Start of buffer (A/C-) */
114 static unsigned char *malloc_buf = NULL; /* Start of malloc buffer (A/C-) */
115 static size_t filebuflen = 0; /* Size of buffer (A/C-) */
116 /* FIXME: make buf_ridx (C/A-) */
118 /* Possible arrangements of the buffer */
119 static int buffer_state = AUDIOBUF_STATE_TRASHED; /* Buffer state */
121 /* These are used to store the current and next (or prev if the current is the last)
122 * mp3entry's in a round-robin system. This guarentees that the pointer returned
123 * by audio_current/next_track will be valid for the full duration of the
124 * currently playing track */
125 static struct mp3entry mp3entry_buf[2];
126 struct mp3entry *thistrack_id3, /* the currently playing track */
127 *othertrack_id3; /* prev track during track-change-transition, or end of playlist,
128 * next track otherwise */
129 static struct mp3entry unbuffered_id3; /* the id3 for the first unbuffered track */
131 /* for cuesheet support */
132 static struct cuesheet *curr_cue = NULL;
135 #define MAX_MULTIPLE_AA 2
137 #ifdef HAVE_ALBUMART
138 static struct albumart_slot {
139 struct dim dim; /* holds width, height of the albumart */
140 int used; /* counter, increments if something uses it */
141 } albumart_slots[MAX_MULTIPLE_AA];
143 #define FOREACH_ALBUMART(i) for(i = 0;i < MAX_MULTIPLE_AA; i++)
144 #endif
147 #define MAX_TRACK 128
148 #define MAX_TRACK_MASK (MAX_TRACK-1)
150 /* Track info structure about songs in the file buffer (A/C-) */
151 static struct track_info {
152 int audio_hid; /* The ID for the track's buffer handle */
153 int id3_hid; /* The ID for the track's metadata handle */
154 int codec_hid; /* The ID for the track's codec handle */
155 #ifdef HAVE_ALBUMART
156 int aa_hid[MAX_MULTIPLE_AA];/* The ID for the track's album art handle */
157 #endif
158 int cuesheet_hid; /* The ID for the track's parsed cueesheet handle */
160 size_t filesize; /* File total length */
162 bool taginfo_ready; /* Is metadata read */
164 } tracks[MAX_TRACK];
166 static volatile int track_ridx = 0; /* Track being decoded (A/C-) */
167 static int track_widx = 0; /* Track being buffered (A) */
168 #define CUR_TI (&tracks[track_ridx]) /* Playing track info pointer (A/C-) */
170 static struct track_info *prev_ti = NULL; /* Pointer to the previously played
171 track */
173 /* Information used only for filling the buffer */
174 /* Playlist steps from playing track to next track to be buffered (A) */
175 static int last_peek_offset = 0;
177 /* Scrobbler support */
178 static unsigned long prev_track_elapsed = 0; /* Previous track elapsed time (C/A-)*/
180 /* Track change controls */
181 bool automatic_skip = false; /* Who initiated in-progress skip? (C/A-) */
182 extern bool track_transition; /* Are we in a track transition? */
183 static bool dir_skip = false; /* Is a directory skip pending? (A) */
184 static bool new_playlist = false; /* Are we starting a new playlist? (A) */
185 static int wps_offset = 0; /* Pending track change offset, to keep WPS responsive (A) */
186 static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer when playback resumes (A) */
188 static bool start_play_g = false; /* Used by audio_load_track to notify
189 audio_finish_load_track about start_play */
191 /* True when a track load is in progress, i.e. audio_load_track() has returned
192 * but audio_finish_load_track() hasn't been called yet. Used to avoid allowing
193 * audio_load_track() to get called twice in a row, which would cause problems.
195 static bool track_load_started = false;
197 #ifdef HAVE_DISK_STORAGE
198 static size_t buffer_margin = 5; /* Buffer margin aka anti-skip buffer (A/C-) */
199 #endif
201 /* Event queues */
202 struct event_queue audio_queue SHAREDBSS_ATTR;
203 struct event_queue codec_queue SHAREDBSS_ATTR;
204 static struct event_queue pcmbuf_queue SHAREDBSS_ATTR;
206 extern struct codec_api ci;
207 extern unsigned int codec_thread_id;
209 /* Multiple threads */
210 /* Set the watermark to trigger buffer fill (A/C) */
211 static void set_filebuf_watermark(void);
213 /* Audio thread */
214 static struct queue_sender_list audio_queue_sender_list SHAREDBSS_ATTR;
215 static long audio_stack[(DEFAULT_STACK_SIZE + 0x1000)/sizeof(long)];
216 static const char audio_thread_name[] = "audio";
218 static void audio_thread(void);
219 static void audio_initiate_track_change(long direction);
220 static bool audio_have_tracks(void);
221 static void audio_reset_buffer(void);
222 static void audio_stop_playback(void);
225 /**************************************/
227 /* Between the codec and PCM track change, we need to keep updating the
228 "elapsed" value of the previous (to the codec, but current to the
229 user/PCM/WPS) track, so that the progressbar reaches the end.
230 During that transition, the WPS will display othertrack_id3. */
231 void audio_pcmbuf_position_callback(size_t size)
233 /* This is called from an ISR, so be quick */
234 unsigned int time = size * 1000 / 4 / NATIVE_FREQUENCY +
235 othertrack_id3->elapsed;
237 if (time >= othertrack_id3->length)
239 if(track_transition){logf("playback: (callback) track transition false");}
240 track_transition = false;
241 othertrack_id3->elapsed = othertrack_id3->length;
243 else
244 othertrack_id3->elapsed = time;
247 /* Post message from pcmbuf that the end of the previous track
248 * has just been played. */
249 void audio_post_track_change(bool pcmbuf)
251 if (pcmbuf)
253 LOGFQUEUE("pcmbuf > pcmbuf Q_AUDIO_TRACK_CHANGED");
254 queue_post(&pcmbuf_queue, Q_AUDIO_TRACK_CHANGED, 0);
256 else
258 LOGFQUEUE("pcmbuf > audio Q_AUDIO_TRACK_CHANGED");
259 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
263 /* Scan the pcmbuf queue and return true if a message pulled.
264 * Permissible Context(s): Thread
266 static bool pcmbuf_queue_scan(struct queue_event *ev)
268 if (!queue_empty(&pcmbuf_queue))
270 /* Transfer message to audio queue */
271 pcm_play_lock();
272 /* Pull message - never, ever any blocking call! */
273 queue_wait_w_tmo(&pcmbuf_queue, ev, 0);
274 pcm_play_unlock();
275 return true;
278 return false;
281 /* --- Helper functions --- */
283 static struct mp3entry *bufgetid3(int handle_id)
285 if (handle_id < 0)
286 return NULL;
288 struct mp3entry *id3;
289 ssize_t ret = bufgetdata(handle_id, 0, (void *)&id3);
291 if (ret < 0 || ret != sizeof(struct mp3entry))
292 return NULL;
294 return id3;
297 static bool clear_track_info(struct track_info *track)
299 /* bufclose returns true if the handle is not found, or if it is closed
300 * successfully, so these checks are safe on non-existant handles */
301 if (!track)
302 return false;
304 if (track->codec_hid >= 0) {
305 if (bufclose(track->codec_hid))
306 track->codec_hid = -1;
307 else
308 return false;
311 if (track->id3_hid >= 0) {
312 if (bufclose(track->id3_hid))
313 track->id3_hid = -1;
314 else
315 return false;
318 if (track->audio_hid >= 0) {
319 if (bufclose(track->audio_hid))
320 track->audio_hid = -1;
321 else
322 return false;
325 #ifdef HAVE_ALBUMART
327 int i;
328 FOREACH_ALBUMART(i)
330 if (track->aa_hid[i] >= 0) {
331 if (bufclose(track->aa_hid[i]))
332 track->aa_hid[i] = -1;
333 else
334 return false;
338 #endif
340 if (track->cuesheet_hid >= 0) {
341 if (bufclose(track->cuesheet_hid))
342 track->cuesheet_hid = -1;
343 else
344 return false;
347 track->filesize = 0;
348 track->taginfo_ready = false;
350 return true;
353 /* --- External interfaces --- */
355 /* This sends a stop message and the audio thread will dump all it's
356 subsequenct messages */
357 void audio_hard_stop(void)
359 /* Stop playback */
360 LOGFQUEUE("audio >| audio Q_AUDIO_STOP: 1");
361 queue_send(&audio_queue, Q_AUDIO_STOP, 1);
362 #ifdef PLAYBACK_VOICE
363 voice_stop();
364 #endif
367 bool audio_restore_playback(int type)
369 switch (type)
371 case AUDIO_WANT_PLAYBACK:
372 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
373 audio_reset_buffer();
374 return true;
375 case AUDIO_WANT_VOICE:
376 if (buffer_state == AUDIOBUF_STATE_TRASHED)
377 audio_reset_buffer();
378 return true;
379 default:
380 return false;
384 unsigned char *audio_get_buffer(bool talk_buf, size_t *buffer_size)
386 unsigned char *buf, *end;
388 if (audio_is_initialized)
390 audio_hard_stop();
392 /* else buffer_state will be AUDIOBUF_STATE_TRASHED at this point */
394 /* Reset the buffering thread so that it doesn't try to use the data */
395 buffering_reset(filebuf, filebuflen);
397 if (buffer_size == NULL)
399 /* Special case for talk_init to use since it already knows it's
400 trashed */
401 buffer_state = AUDIOBUF_STATE_TRASHED;
402 return NULL;
405 if (talk_buf || buffer_state == AUDIOBUF_STATE_TRASHED
406 || !talk_voice_required())
408 logf("get buffer: talk, audio");
409 /* Ok to use everything from audiobuf to audiobufend - voice is loaded,
410 the talk buffer is not needed because voice isn't being used, or
411 could be AUDIOBUF_STATE_TRASHED already. If state is
412 AUDIOBUF_STATE_VOICED_ONLY, no problem as long as memory isn't written
413 without the caller knowing what's going on. Changing certain settings
414 may move it to a worse condition but the memory in use by something
415 else will remain undisturbed.
417 if (buffer_state != AUDIOBUF_STATE_TRASHED)
419 talk_buffer_steal();
420 buffer_state = AUDIOBUF_STATE_TRASHED;
423 buf = audiobuf;
424 end = audiobufend;
426 else
428 /* Safe to just return this if already AUDIOBUF_STATE_VOICED_ONLY or
429 still AUDIOBUF_STATE_INITIALIZED */
430 /* Skip talk buffer and move pcm buffer to end to maximize available
431 contiguous memory - no audio running means voice will not need the
432 swap space */
433 logf("get buffer: audio");
434 buf = audiobuf + talk_get_bufsize();
435 end = audiobufend - pcmbuf_init(audiobufend);
436 buffer_state = AUDIOBUF_STATE_VOICED_ONLY;
439 *buffer_size = end - buf;
441 return buf;
444 int audio_buffer_state(void)
446 return buffer_state;
449 #ifdef HAVE_RECORDING
450 unsigned char *audio_get_recording_buffer(size_t *buffer_size)
452 /* Stop audio, voice and obtain all available buffer space */
453 audio_hard_stop();
454 talk_buffer_steal();
456 unsigned char *end = audiobufend;
457 buffer_state = AUDIOBUF_STATE_TRASHED;
458 *buffer_size = end - audiobuf;
460 return (unsigned char *)audiobuf;
463 bool audio_load_encoder(int afmt)
465 #ifndef SIMULATOR
466 const char *enc_fn = get_codec_filename(afmt | CODEC_TYPE_ENCODER);
467 if (!enc_fn)
468 return false;
470 audio_remove_encoder();
471 ci.enc_codec_loaded = 0; /* clear any previous error condition */
473 LOGFQUEUE("codec > Q_ENCODER_LOAD_DISK");
474 queue_post(&codec_queue, Q_ENCODER_LOAD_DISK, (intptr_t)enc_fn);
476 while (ci.enc_codec_loaded == 0)
477 yield();
479 logf("codec loaded: %d", ci.enc_codec_loaded);
481 return ci.enc_codec_loaded > 0;
482 #else
483 (void)afmt;
484 return true;
485 #endif
486 } /* audio_load_encoder */
488 void audio_remove_encoder(void)
490 #ifndef SIMULATOR
491 /* force encoder codec unload (if currently loaded) */
492 if (ci.enc_codec_loaded <= 0)
493 return;
495 ci.stop_encoder = true;
496 while (ci.enc_codec_loaded > 0)
497 yield();
498 #endif
499 } /* audio_remove_encoder */
501 #endif /* HAVE_RECORDING */
504 struct mp3entry* audio_current_track(void)
506 const char *filename;
507 struct playlist_track_info trackinfo;
508 int cur_idx;
509 int offset = ci.new_track + wps_offset;
510 struct mp3entry *write_id3;
512 cur_idx = (track_ridx + offset) & MAX_TRACK_MASK;
514 if (cur_idx == track_ridx && *thistrack_id3->path)
516 /* The usual case */
517 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
519 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
520 thistrack_id3->cuesheet = curr_cue;
521 cue_spoof_id3(thistrack_id3->cuesheet, thistrack_id3);
523 return thistrack_id3;
525 else if (automatic_skip && offset == -1 && *othertrack_id3->path)
527 /* We're in a track transition. The codec has moved on to the next track,
528 but the audio being played is still the same (now previous) track.
529 othertrack_id3.elapsed is being updated in an ISR by
530 codec_pcmbuf_position_callback */
531 if (tracks[cur_idx].cuesheet_hid >= 0 && !thistrack_id3->cuesheet)
533 bufread(tracks[cur_idx].cuesheet_hid, sizeof(struct cuesheet), curr_cue);
534 othertrack_id3->cuesheet = curr_cue;
535 cue_spoof_id3(othertrack_id3->cuesheet, othertrack_id3);
537 return othertrack_id3;
540 if (offset != 0)
542 /* Codec may be using thistrack_id3, so it must not be overwritten.
543 If this is a manual skip, othertrack_id3 will become
544 thistrack_id3 in audio_check_new_track().
545 FIXME: If this is an automatic skip, it probably means multiple
546 short tracks fit in the PCM buffer. Overwriting othertrack_id3
547 can lead to an incorrect value later.
548 Note that othertrack_id3 may also be used for next track.
550 write_id3 = othertrack_id3;
552 else
554 write_id3 = thistrack_id3;
557 if (tracks[cur_idx].id3_hid >= 0)
559 /* The current track's info has been buffered but not read yet, so get it */
560 if (bufread(tracks[cur_idx].id3_hid, sizeof(struct mp3entry), write_id3)
561 == sizeof(struct mp3entry))
562 return write_id3;
565 /* We didn't find the ID3 metadata, so we fill temp_id3 with the little info
566 we have and return that. */
568 memset(write_id3, 0, sizeof(struct mp3entry));
570 playlist_get_track_info(NULL, playlist_next(0)+wps_offset, &trackinfo);
571 filename = trackinfo.filename;
572 if (!filename)
573 filename = "No file!";
575 #if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
576 if (tagcache_fill_tags(write_id3, filename))
577 return write_id3;
578 #endif
580 strlcpy(write_id3->path, filename, sizeof(write_id3->path));
581 write_id3->title = strrchr(write_id3->path, '/');
582 if (!write_id3->title)
583 write_id3->title = &write_id3->path[0];
584 else
585 write_id3->title++;
587 return write_id3;
590 struct mp3entry* audio_next_track(void)
592 int next_idx;
593 int offset = ci.new_track + wps_offset;
595 if (!audio_have_tracks())
596 return NULL;
598 if (wps_offset == -1 && *thistrack_id3->path)
600 /* We're in a track transition. The next track for the WPS is the one
601 currently being decoded. */
602 return thistrack_id3;
605 next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
607 if (tracks[next_idx].id3_hid >= 0)
609 if (bufread(tracks[next_idx].id3_hid, sizeof(struct mp3entry), othertrack_id3)
610 == sizeof(struct mp3entry))
611 return othertrack_id3;
612 else
613 return NULL;
616 if (next_idx == track_widx)
618 /* The next track hasn't been buffered yet, so we return the static
619 version of its metadata. */
620 return &unbuffered_id3;
623 return NULL;
626 #ifdef HAVE_ALBUMART
627 int playback_current_aa_hid(int slot)
629 if (slot < 0)
630 return -1;
631 int cur_idx;
632 int offset = ci.new_track + wps_offset;
634 cur_idx = track_ridx + offset;
635 cur_idx &= MAX_TRACK_MASK;
637 return tracks[cur_idx].aa_hid[slot];
640 int playback_claim_aa_slot(struct dim *dim)
642 int i;
643 /* first try to find a slot already having the size to reuse it
644 * since we don't want albumart of the same size buffered multiple times */
645 FOREACH_ALBUMART(i)
647 struct albumart_slot *slot = &albumart_slots[i];
648 if (slot->dim.width == dim->width
649 && slot->dim.height == dim->height)
651 slot->used++;
652 return i;
655 /* size is new, find a free slot */
656 FOREACH_ALBUMART(i)
658 if (!albumart_slots[i].used)
660 albumart_slots[i].used++;
661 albumart_slots[i].dim = *dim;
662 return i;
665 /* sorry, no free slot */
666 return -1;
669 void playback_release_aa_slot(int slot)
671 /* invalidate the albumart_slot */
672 struct albumart_slot *aa_slot = &albumart_slots[slot];
673 if (aa_slot->used > 0)
674 aa_slot->used--;
677 #endif
678 void audio_play(long offset)
680 logf("audio_play");
682 #ifdef PLAYBACK_VOICE
683 /* Truncate any existing voice output so we don't have spelling
684 * etc. over the first part of the played track */
685 talk_force_shutup();
686 #endif
688 /* Start playback */
689 LOGFQUEUE("audio >| audio Q_AUDIO_PLAY: %ld", offset);
690 /* Don't return until playback has actually started */
691 queue_send(&audio_queue, Q_AUDIO_PLAY, offset);
694 void audio_stop(void)
696 /* Stop playback */
697 LOGFQUEUE("audio >| audio Q_AUDIO_STOP");
698 /* Don't return until playback has actually stopped */
699 queue_send(&audio_queue, Q_AUDIO_STOP, 0);
702 void audio_pause(void)
704 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
705 /* Don't return until playback has actually paused */
706 queue_send(&audio_queue, Q_AUDIO_PAUSE, true);
709 void audio_resume(void)
711 LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE resume");
712 /* Don't return until playback has actually resumed */
713 queue_send(&audio_queue, Q_AUDIO_PAUSE, false);
716 void audio_skip(int direction)
718 if (playlist_check(ci.new_track + wps_offset + direction))
720 if (global_settings.beep)
721 pcmbuf_beep(2000, 100, 2500*global_settings.beep);
723 LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", direction);
724 queue_post(&audio_queue, Q_AUDIO_SKIP, direction);
725 /* Update wps while our message travels inside deep playback queues. */
726 wps_offset += direction;
728 else
730 /* No more tracks. */
731 if (global_settings.beep)
732 pcmbuf_beep(1000, 100, 1500*global_settings.beep);
736 void audio_next(void)
738 audio_skip(1);
741 void audio_prev(void)
743 audio_skip(-1);
746 void audio_next_dir(void)
748 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP 1");
749 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, 1);
752 void audio_prev_dir(void)
754 LOGFQUEUE("audio > audio Q_AUDIO_DIR_SKIP -1");
755 queue_post(&audio_queue, Q_AUDIO_DIR_SKIP, -1);
758 void audio_pre_ff_rewind(void)
760 LOGFQUEUE("audio > audio Q_AUDIO_PRE_FF_REWIND");
761 queue_post(&audio_queue, Q_AUDIO_PRE_FF_REWIND, 0);
764 void audio_ff_rewind(long newpos)
766 LOGFQUEUE("audio > audio Q_AUDIO_FF_REWIND");
767 queue_post(&audio_queue, Q_AUDIO_FF_REWIND, newpos);
770 void audio_flush_and_reload_tracks(void)
772 LOGFQUEUE("audio > audio Q_AUDIO_FLUSH");
773 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
776 void audio_error_clear(void)
778 #ifdef AUDIO_HAVE_RECORDING
779 pcm_rec_error_clear();
780 #endif
783 int audio_status(void)
785 int ret = 0;
787 if (playing)
788 ret |= AUDIO_STATUS_PLAY;
790 if (paused)
791 ret |= AUDIO_STATUS_PAUSE;
793 #ifdef HAVE_RECORDING
794 /* Do this here for constitency with mpeg.c version */
795 /* FIXME: pcm_rec_status() is deprecated */
796 ret |= pcm_rec_status();
797 #endif
799 return ret;
802 int audio_get_file_pos(void)
804 return 0;
807 #ifdef HAVE_DISK_STORAGE
808 void audio_set_buffer_margin(int setting)
810 static const unsigned short lookup[] = {5, 15, 30, 60, 120, 180, 300, 600};
811 buffer_margin = lookup[setting];
812 logf("buffer margin: %ld", (long)buffer_margin);
813 set_filebuf_watermark();
815 #endif
817 /* Take necessary steps to enable or disable the crossfade setting */
818 void audio_set_crossfade(int enable)
820 size_t offset;
821 bool was_playing;
822 size_t size;
824 /* Tell it the next setting to use */
825 pcmbuf_request_crossfade_enable(enable);
827 /* Return if size hasn't changed or this is too early to determine
828 which in the second case there's no way we could be playing
829 anything at all */
830 if (pcmbuf_is_same_size()) return;
832 offset = 0;
833 was_playing = playing;
835 /* Playback has to be stopped before changing the buffer size */
836 if (was_playing)
838 /* Store the track resume position */
839 offset = thistrack_id3->offset;
842 /* Blast it - audio buffer will have to be setup again next time
843 something plays */
844 audio_get_buffer(true, &size);
846 /* Restart playback if audio was running previously */
847 if (was_playing)
848 audio_play(offset);
851 /* --- Routines called from multiple threads --- */
853 static void set_filebuf_watermark(void)
855 if (!filebuf)
856 return; /* Audio buffers not yet set up */
858 #ifdef HAVE_DISK_STORAGE
859 int seconds;
860 int spinup = ata_spinup_time();
861 if (spinup)
862 seconds = (spinup / HZ) + 1;
863 else
864 seconds = 5;
866 seconds += buffer_margin;
867 #else
868 /* flash storage */
869 int seconds = 1;
870 #endif
872 /* bitrate of last track in buffer dictates watermark */
873 struct mp3entry* id3 = NULL;
874 if (tracks[track_widx].taginfo_ready)
875 id3 = bufgetid3(tracks[track_widx].id3_hid);
876 else
877 id3 = bufgetid3(tracks[track_widx-1].id3_hid);
878 if (!id3) {
879 logf("fwmark: No id3 for last track (r%d/w%d), aborting!", track_ridx, track_widx);
880 return;
882 size_t bytes = id3->bitrate * (1000/8) * seconds;
883 buf_set_watermark(bytes);
884 logf("fwmark: %d", bytes);
887 /* --- Buffering callbacks --- */
889 static void buffering_low_buffer_callback(void *data)
891 (void)data;
892 logf("low buffer callback");
894 if (filling == STATE_FULL || filling == STATE_END_OF_PLAYLIST) {
895 /* force a refill */
896 LOGFQUEUE("buffering > audio Q_AUDIO_FILL_BUFFER");
897 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
901 static void buffering_handle_rebuffer_callback(void *data)
903 (void)data;
904 LOGFQUEUE("audio >| audio Q_AUDIO_FLUSH");
905 queue_post(&audio_queue, Q_AUDIO_FLUSH, 0);
908 static void buffering_handle_finished_callback(void *data)
910 logf("handle %d finished buffering", *(int*)data);
911 int hid = (*(int*)data);
913 if (hid == tracks[track_widx].id3_hid)
915 int offset = ci.new_track + wps_offset;
916 int next_idx = (track_ridx + offset + 1) & MAX_TRACK_MASK;
917 /* The metadata handle for the last loaded track has been buffered.
918 We can ask the audio thread to load the rest of the track's data. */
919 LOGFQUEUE("audio >| audio Q_AUDIO_FINISH_LOAD");
920 queue_post(&audio_queue, Q_AUDIO_FINISH_LOAD, 0);
921 if (tracks[next_idx].id3_hid == hid)
922 send_event(PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE, NULL);
924 else
926 /* This is most likely an audio handle, so we strip the useless
927 trailing tags that are left. */
928 strip_tags(hid);
930 if (hid == tracks[track_widx-1].audio_hid
931 && filling == STATE_END_OF_PLAYLIST)
933 /* This was the last track in the playlist.
934 We now have all the data we need. */
935 logf("last track finished buffering");
936 filling = STATE_FINISHED;
942 /* --- Audio thread --- */
944 static bool audio_have_tracks(void)
946 return (audio_track_count() != 0);
949 static int audio_free_track_count(void)
951 /* Used tracks + free tracks adds up to MAX_TRACK - 1 */
952 return MAX_TRACK - 1 - audio_track_count();
955 int audio_track_count(void)
957 /* Calculate difference from track_ridx to track_widx
958 * taking into account a possible wrap-around. */
959 return (MAX_TRACK + track_widx - track_ridx) & MAX_TRACK_MASK;
962 long audio_filebufused(void)
964 return (long) buf_used();
967 /* Update track info after successful a codec track change */
968 static void audio_update_trackinfo(void)
970 /* Load the curent track's metadata into curtrack_id3 */
971 if (CUR_TI->id3_hid >= 0)
972 copy_mp3entry(thistrack_id3, bufgetid3(CUR_TI->id3_hid));
974 /* Reset current position */
975 thistrack_id3->elapsed = 0;
976 thistrack_id3->offset = 0;
978 /* Update the codec API */
979 ci.filesize = CUR_TI->filesize;
980 ci.id3 = thistrack_id3;
981 ci.curpos = 0;
982 ci.taginfo_ready = &CUR_TI->taginfo_ready;
985 /* Clear tracks between write and read, non inclusive */
986 static void audio_clear_track_entries(void)
988 int cur_idx = track_widx;
990 logf("Clearing tracks: r%d/w%d", track_ridx, track_widx);
992 /* Loop over all tracks from write-to-read */
993 while (1)
995 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
997 if (cur_idx == track_ridx)
998 break;
1000 clear_track_info(&tracks[cur_idx]);
1004 /* Clear all tracks */
1005 static bool audio_release_tracks(void)
1007 int i, cur_idx;
1009 logf("releasing all tracks");
1011 for(i = 0; i < MAX_TRACK; i++)
1013 cur_idx = (track_ridx + i) & MAX_TRACK_MASK;
1014 if (!clear_track_info(&tracks[cur_idx]))
1015 return false;
1018 return true;
1021 static bool audio_loadcodec(bool start_play)
1023 int prev_track;
1024 char codec_path[MAX_PATH]; /* Full path to codec */
1025 const struct mp3entry *id3, *prev_id3;
1027 if (tracks[track_widx].id3_hid < 0) {
1028 return false;
1031 id3 = bufgetid3(tracks[track_widx].id3_hid);
1032 if (!id3)
1033 return false;
1035 const char *codec_fn = get_codec_filename(id3->codectype);
1036 if (codec_fn == NULL)
1037 return false;
1039 tracks[track_widx].codec_hid = -1;
1041 if (start_play)
1043 /* Load the codec directly from disk and save some memory. */
1044 track_ridx = track_widx;
1045 ci.filesize = CUR_TI->filesize;
1046 ci.id3 = thistrack_id3;
1047 ci.taginfo_ready = &CUR_TI->taginfo_ready;
1048 ci.curpos = 0;
1049 LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
1050 queue_post(&codec_queue, Q_CODEC_LOAD_DISK, (intptr_t)codec_fn);
1051 return true;
1053 else
1055 /* If we already have another track than this one buffered */
1056 if (track_widx != track_ridx)
1058 prev_track = (track_widx - 1) & MAX_TRACK_MASK;
1060 id3 = bufgetid3(tracks[track_widx].id3_hid);
1061 prev_id3 = bufgetid3(tracks[prev_track].id3_hid);
1063 /* If the previous codec is the same as this one, there is no need
1064 * to put another copy of it on the file buffer */
1065 if (id3 && prev_id3 &&
1066 get_codec_base_type(id3->codectype) ==
1067 get_codec_base_type(prev_id3->codectype)
1068 && audio_codec_loaded)
1070 logf("Reusing prev. codec");
1071 return true;
1076 codec_get_full_path(codec_path, codec_fn);
1078 tracks[track_widx].codec_hid = bufopen(codec_path, 0, TYPE_CODEC, NULL);
1079 if (tracks[track_widx].codec_hid < 0)
1080 return false;
1082 logf("Loaded codec");
1084 return true;
1087 /* Load metadata for the next track (with bufopen). The rest of the track
1088 loading will be handled by audio_finish_load_track once the metadata has been
1089 actually loaded by the buffering thread. */
1090 static bool audio_load_track(size_t offset, bool start_play)
1092 const char *trackname;
1093 int fd = -1;
1095 if (track_load_started) {
1096 /* There is already a track load in progress, so track_widx hasn't been
1097 incremented yet. Loading another track would overwrite the one that
1098 hasn't finished loading. */
1099 logf("audio_load_track(): a track load is already in progress");
1100 return false;
1103 start_play_g = start_play; /* will be read by audio_finish_load_track */
1105 /* Stop buffer filling if there is no free track entries.
1106 Don't fill up the last track entry (we wan't to store next track
1107 metadata there). */
1108 if (!audio_free_track_count())
1110 logf("No free tracks");
1111 return false;
1114 last_peek_offset++;
1115 tracks[track_widx].taginfo_ready = false;
1117 logf("Buffering track: r%d/w%d", track_ridx, track_widx);
1118 /* Get track name from current playlist read position. */
1119 while ((trackname = playlist_peek(last_peek_offset)) != NULL)
1121 /* Handle broken playlists. */
1122 fd = open(trackname, O_RDONLY);
1123 if (fd < 0)
1125 logf("Open failed");
1126 /* Skip invalid entry from playlist. */
1127 playlist_skip_entry(NULL, last_peek_offset);
1129 else
1130 break;
1133 if (!trackname)
1135 logf("End-of-playlist");
1136 memset(&unbuffered_id3, 0, sizeof(struct mp3entry));
1137 filling = STATE_END_OF_PLAYLIST;
1139 if (thistrack_id3->length == 0 && thistrack_id3->filesize == 0)
1141 /* Stop playback if no valid track was found. */
1142 audio_stop_playback();
1145 return false;
1148 tracks[track_widx].filesize = filesize(fd);
1150 if (offset > tracks[track_widx].filesize)
1151 offset = 0;
1153 /* Set default values */
1154 if (start_play)
1156 buf_set_watermark(filebuflen/2);
1157 dsp_configure(ci.dsp, DSP_RESET, 0);
1158 playlist_update_resume_info(audio_current_track());
1161 /* Get track metadata if we don't already have it. */
1162 if (tracks[track_widx].id3_hid < 0)
1164 tracks[track_widx].id3_hid = bufopen(trackname, 0, TYPE_ID3, NULL);
1166 if (tracks[track_widx].id3_hid < 0)
1168 /* Buffer is full. */
1169 get_metadata(&unbuffered_id3, fd, trackname);
1170 last_peek_offset--;
1171 close(fd);
1172 logf("buffer is full for now (get metadata)");
1173 filling = STATE_FULL;
1174 return false;
1177 if (track_widx == track_ridx)
1179 /* TODO: Superfluos buffering call? */
1180 buf_request_buffer_handle(tracks[track_widx].id3_hid);
1181 struct mp3entry *id3 = bufgetid3(tracks[track_widx].id3_hid);
1182 if (id3)
1184 copy_mp3entry(thistrack_id3, id3);
1185 thistrack_id3->offset = offset;
1187 else
1188 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1191 if (start_play)
1193 playlist_update_resume_info(audio_current_track());
1197 close(fd);
1198 track_load_started = true; /* Remember that we've started loading a track */
1199 return true;
1202 /* Second part of the track loading: We now have the metadata available, so we
1203 can load the codec, the album art and finally the audio data.
1204 This is called on the audio thread after the buffering thread calls the
1205 buffering_handle_finished_callback callback. */
1206 static void audio_finish_load_track(void)
1208 size_t file_offset = 0;
1209 size_t offset = 0;
1210 bool start_play = start_play_g;
1212 track_load_started = false;
1214 if (tracks[track_widx].id3_hid < 0) {
1215 logf("No metadata");
1216 return;
1219 struct mp3entry *track_id3;
1221 if (track_widx == track_ridx)
1222 track_id3 = thistrack_id3;
1223 else
1224 track_id3 = bufgetid3(tracks[track_widx].id3_hid);
1226 if (track_id3->length == 0 && track_id3->filesize == 0)
1228 logf("audio_finish_load_track: invalid metadata");
1230 /* Invalid metadata */
1231 bufclose(tracks[track_widx].id3_hid);
1232 tracks[track_widx].id3_hid = -1;
1234 /* Skip invalid entry from playlist. */
1235 playlist_skip_entry(NULL, last_peek_offset--);
1237 /* load next track */
1238 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER %d", (int)start_play);
1239 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, start_play);
1241 return;
1243 /* Try to load a cuesheet for the track */
1244 if (curr_cue)
1246 char cuepath[MAX_PATH];
1247 if (look_for_cuesheet_file(track_id3->path, cuepath))
1249 void *temp;
1250 tracks[track_widx].cuesheet_hid =
1251 bufalloc(NULL, sizeof(struct cuesheet), TYPE_CUESHEET);
1252 if (tracks[track_widx].cuesheet_hid >= 0)
1254 bufgetdata(tracks[track_widx].cuesheet_hid,
1255 sizeof(struct cuesheet), &temp);
1256 struct cuesheet *cuesheet = (struct cuesheet*)temp;
1257 if (!parse_cuesheet(cuepath, cuesheet))
1259 bufclose(tracks[track_widx].cuesheet_hid);
1260 track_id3->cuesheet = NULL;
1265 #ifdef HAVE_ALBUMART
1267 int i;
1268 char aa_path[MAX_PATH];
1269 FOREACH_ALBUMART(i)
1271 /* albumart_slots may change during a yield of bufopen,
1272 * but that's no problem */
1273 if (tracks[track_widx].aa_hid[i] >= 0 || !albumart_slots[i].used)
1274 continue;
1275 /* find_albumart will error out if the wps doesn't have AA */
1276 if (find_albumart(track_id3, aa_path, sizeof(aa_path),
1277 &(albumart_slots[i].dim)))
1279 int aa_hid = bufopen(aa_path, 0, TYPE_BITMAP,
1280 &(albumart_slots[i].dim));
1282 if(aa_hid == ERR_BUFFER_FULL)
1284 filling = STATE_FULL;
1285 logf("buffer is full for now (get album art)");
1286 return; /* No space for track's album art, not an error */
1288 else if (aa_hid < 0)
1290 /* another error, ignore AlbumArt */
1291 logf("Album art loading failed");
1293 tracks[track_widx].aa_hid[i] = aa_hid;
1298 #endif
1300 /* Load the codec. */
1301 if (!audio_loadcodec(start_play))
1303 if (tracks[track_widx].codec_hid == ERR_BUFFER_FULL)
1305 /* No space for codec on buffer, not an error */
1306 filling = STATE_FULL;
1307 return;
1310 /* This is an error condition, either no codec was found, or reading
1311 * the codec file failed part way through, either way, skip the track */
1312 /* FIXME: We should not use splashf from audio thread! */
1313 splashf(HZ*2, "No codec for: %s", track_id3->path);
1314 /* Skip invalid entry from playlist. */
1315 playlist_skip_entry(NULL, last_peek_offset);
1316 return;
1319 track_id3->elapsed = 0;
1320 offset = track_id3->offset;
1322 enum data_type type = TYPE_PACKET_AUDIO;
1324 switch (track_id3->codectype) {
1325 case AFMT_MPA_L1:
1326 case AFMT_MPA_L2:
1327 case AFMT_MPA_L3:
1328 if (offset > 0) {
1329 file_offset = offset;
1330 track_id3->offset = offset;
1332 break;
1334 case AFMT_WAVPACK:
1335 if (offset > 0) {
1336 file_offset = offset;
1337 track_id3->offset = offset;
1338 track_id3->elapsed = track_id3->length / 2;
1340 break;
1342 case AFMT_OGG_VORBIS:
1343 case AFMT_SPEEX:
1344 case AFMT_FLAC:
1345 case AFMT_PCM_WAV:
1346 case AFMT_A52:
1347 case AFMT_MP4_AAC:
1348 case AFMT_MPC:
1349 case AFMT_APE:
1350 case AFMT_WMA:
1351 if (offset > 0)
1352 track_id3->offset = offset;
1353 break;
1355 case AFMT_NSF:
1356 case AFMT_SPC:
1357 case AFMT_SID:
1358 logf("Loading atomic %d",track_id3->codectype);
1359 type = TYPE_ATOMIC_AUDIO;
1360 break;
1363 logf("load track: %s", track_id3->path);
1365 if (file_offset > AUDIO_REBUFFER_GUESS_SIZE)
1366 file_offset -= AUDIO_REBUFFER_GUESS_SIZE;
1367 else if (track_id3->first_frame_offset)
1368 file_offset = track_id3->first_frame_offset;
1369 else
1370 file_offset = 0;
1372 tracks[track_widx].audio_hid = bufopen(track_id3->path, file_offset, type,
1373 NULL);
1375 /* No space left, not an error */
1376 if (tracks[track_widx].audio_hid == ERR_BUFFER_FULL)
1378 filling = STATE_FULL;
1379 logf("buffer is full for now (load audio)");
1380 return;
1382 else if (tracks[track_widx].audio_hid < 0)
1384 /* another error, do not continue either */
1385 logf("Could not add audio data handle");
1386 return;
1389 /* All required data is now available for the codec. */
1390 tracks[track_widx].taginfo_ready = true;
1392 if (start_play)
1394 ci.curpos=file_offset;
1395 buf_request_buffer_handle(tracks[track_widx].audio_hid);
1398 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1400 send_event(PLAYBACK_EVENT_TRACK_BUFFER, track_id3);
1402 /* load next track */
1403 LOGFQUEUE("audio > audio Q_AUDIO_FILL_BUFFER");
1404 queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
1406 return;
1409 static void audio_fill_file_buffer(bool start_play, size_t offset)
1411 trigger_cpu_boost();
1413 /* No need to rebuffer if there are track skips pending,
1414 * however don't cancel buffering on skipping while filling. */
1415 if (ci.new_track != 0 && filling != STATE_FILLING)
1416 return;
1417 filling = STATE_FILLING;
1419 /* Must reset the buffer before use if trashed or voice only - voice
1420 file size shouldn't have changed so we can go straight from
1421 AUDIOBUF_STATE_VOICED_ONLY to AUDIOBUF_STATE_INITIALIZED */
1422 if (buffer_state != AUDIOBUF_STATE_INITIALIZED)
1423 audio_reset_buffer();
1425 logf("Starting buffer fill");
1427 if (!start_play)
1428 audio_clear_track_entries();
1430 /* Save the current resume position once. */
1431 playlist_update_resume_info(audio_current_track());
1433 audio_load_track(offset, start_play);
1436 static void audio_rebuffer(void)
1438 logf("Forcing rebuffer");
1440 clear_track_info(CUR_TI);
1442 /* Reset track pointers */
1443 track_widx = track_ridx;
1444 audio_clear_track_entries();
1446 /* Reset a possibly interrupted track load */
1447 track_load_started = false;
1449 /* Fill the buffer */
1450 last_peek_offset = -1;
1451 ci.curpos = 0;
1453 if (!CUR_TI->taginfo_ready)
1454 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1456 audio_fill_file_buffer(false, 0);
1459 /* Called on request from the codec to get a new track. This is the codec part
1460 of the track transition. */
1461 static int audio_check_new_track(void)
1463 int track_count = audio_track_count();
1464 int old_track_ridx = track_ridx;
1465 int i, idx;
1466 bool forward;
1467 struct mp3entry *temp = thistrack_id3;
1469 /* Now it's good time to send track finish events. */
1470 send_event(PLAYBACK_EVENT_TRACK_FINISH, thistrack_id3);
1471 /* swap the mp3entry pointers */
1472 thistrack_id3 = othertrack_id3;
1473 othertrack_id3 = temp;
1474 ci.id3 = thistrack_id3;
1475 memset(thistrack_id3, 0, sizeof(struct mp3entry));
1477 if (dir_skip)
1479 dir_skip = false;
1480 /* regardless of the return value we need to rebuffer.
1481 if it fails the old playlist will resume, else the
1482 next dir will start playing */
1483 playlist_next_dir(ci.new_track);
1484 ci.new_track = 0;
1485 audio_rebuffer();
1486 goto skip_done;
1489 if (new_playlist)
1490 ci.new_track = 0;
1492 /* If the playlist isn't that big */
1493 if (automatic_skip)
1495 while (!playlist_check(ci.new_track))
1497 if (ci.new_track >= 0)
1499 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1500 return Q_CODEC_REQUEST_FAILED;
1502 ci.new_track++;
1506 /* Update the playlist */
1507 last_peek_offset -= ci.new_track;
1509 if (playlist_next(ci.new_track) < 0)
1511 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_FAILED");
1512 return Q_CODEC_REQUEST_FAILED;
1515 if (new_playlist)
1517 ci.new_track = 1;
1518 new_playlist = false;
1521 /* Save a pointer to the old track to allow later clearing */
1522 prev_ti = CUR_TI;
1524 for (i = 0; i < ci.new_track; i++)
1526 idx = (track_ridx + i) & MAX_TRACK_MASK;
1527 struct mp3entry *id3 = bufgetid3(tracks[idx].id3_hid);
1528 ssize_t offset = buf_handle_offset(tracks[idx].audio_hid);
1529 if (!id3 || offset < 0 || (unsigned)offset > id3->first_frame_offset)
1531 /* We don't have all the audio data for that track, so clear it,
1532 but keep the metadata. */
1533 if (tracks[idx].audio_hid >= 0 && bufclose(tracks[idx].audio_hid))
1535 tracks[idx].audio_hid = -1;
1536 tracks[idx].filesize = 0;
1541 /* Move to the new track */
1542 track_ridx = (track_ridx + ci.new_track) & MAX_TRACK_MASK;
1544 buf_set_base_handle(CUR_TI->audio_hid);
1546 if (automatic_skip)
1548 wps_offset = -ci.new_track;
1551 /* If it is not safe to even skip this many track entries */
1552 if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK)
1554 ci.new_track = 0;
1555 audio_rebuffer();
1556 goto skip_done;
1559 forward = ci.new_track > 0;
1560 ci.new_track = 0;
1562 /* If the target track is clearly not in memory */
1563 if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready)
1565 audio_rebuffer();
1566 goto skip_done;
1569 /* When skipping backwards, it is possible that we've found a track that's
1570 * buffered, but which is around the track-wrap and therefore not the track
1571 * we are looking for */
1572 if (!forward)
1574 int cur_idx = track_ridx;
1575 bool taginfo_ready = true;
1576 /* We've wrapped the buffer backwards if new > old */
1577 bool wrap = track_ridx > old_track_ridx;
1579 while (1)
1581 cur_idx = (cur_idx + 1) & MAX_TRACK_MASK;
1583 /* if we've advanced past the wrap when cur_idx is zeroed */
1584 if (!cur_idx)
1585 wrap = false;
1587 /* if we aren't still on the wrap and we've caught the old track */
1588 if (!(wrap || cur_idx < old_track_ridx))
1589 break;
1591 /* If we hit a track in between without valid tag info, bail */
1592 if (!tracks[cur_idx].taginfo_ready)
1594 taginfo_ready = false;
1595 break;
1598 if (!taginfo_ready)
1600 audio_rebuffer();
1604 skip_done:
1605 audio_update_trackinfo();
1606 LOGFQUEUE("audio >|= codec Q_CODEC_REQUEST_COMPLETE");
1607 return Q_CODEC_REQUEST_COMPLETE;
1610 unsigned long audio_prev_elapsed(void)
1612 return prev_track_elapsed;
1615 void audio_set_prev_elapsed(unsigned long setting)
1617 prev_track_elapsed = setting;
1620 static void audio_stop_codec_flush(void)
1622 ci.stop_codec = true;
1623 pcmbuf_pause(true);
1625 while (audio_codec_loaded)
1626 yield();
1628 /* If the audio codec is not loaded any more, and the audio is still
1629 * playing, it is now and _only_ now safe to call this function from the
1630 * audio thread */
1631 if (pcm_is_playing())
1633 pcmbuf_play_stop();
1634 pcm_play_lock();
1635 queue_clear(&pcmbuf_queue);
1636 pcm_play_unlock();
1638 pcmbuf_pause(paused);
1641 static void audio_stop_playback(void)
1643 if (playing)
1645 /* If we were playing, save resume information */
1646 struct mp3entry *id3 = NULL;
1648 if (!ci.stop_codec)
1650 /* Set this early, the outside code yields and may allow the codec
1651 to try to wait for a reply on a buffer wait */
1652 ci.stop_codec = true;
1653 id3 = audio_current_track();
1656 /* Save the current playing spot, or NULL if the playlist has ended */
1657 playlist_update_resume_info(id3);
1659 /* TODO: Create auto bookmark too? */
1661 prev_track_elapsed = othertrack_id3->elapsed;
1663 remove_event(BUFFER_EVENT_BUFFER_LOW, buffering_low_buffer_callback);
1666 audio_stop_codec_flush();
1667 paused = false;
1668 playing = false;
1669 track_load_started = false;
1671 filling = STATE_IDLE;
1673 /* Mark all entries null. */
1674 audio_clear_track_entries();
1676 /* Close all tracks */
1677 audio_release_tracks();
1680 static void audio_play_start(size_t offset)
1682 int i;
1684 #if INPUT_SRC_CAPS != 0
1685 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1686 audio_set_output_source(AUDIO_SRC_PLAYBACK);
1687 #endif
1689 /* Wait for any previously playing audio to flush - TODO: Not necessary? */
1690 paused = false;
1691 audio_stop_codec_flush();
1693 playing = true;
1694 track_load_started = false;
1696 ci.new_track = 0;
1697 ci.seek_time = 0;
1698 wps_offset = 0;
1700 sound_set_volume(global_settings.volume);
1701 track_widx = track_ridx = 0;
1703 /* Clear all track entries. */
1704 for (i = 0; i < MAX_TRACK; i++) {
1705 clear_track_info(&tracks[i]);
1708 last_peek_offset = -1;
1710 /* Officially playing */
1711 queue_reply(&audio_queue, 1);
1713 audio_fill_file_buffer(true, offset);
1715 add_event(BUFFER_EVENT_BUFFER_LOW, false, buffering_low_buffer_callback);
1717 LOGFQUEUE("audio > audio Q_AUDIO_TRACK_CHANGED");
1718 queue_post(&audio_queue, Q_AUDIO_TRACK_CHANGED, 0);
1722 /* Invalidates all but currently playing track. */
1723 static void audio_invalidate_tracks(void)
1725 if (audio_have_tracks())
1727 last_peek_offset = 0;
1728 track_widx = track_ridx;
1730 /* Mark all other entries null (also buffered wrong metadata). */
1731 audio_clear_track_entries();
1733 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1735 audio_fill_file_buffer(false, 0);
1739 static void audio_new_playlist(void)
1741 /* Prepare to start a new fill from the beginning of the playlist */
1742 last_peek_offset = -1;
1743 if (audio_have_tracks())
1745 if (paused)
1746 skipped_during_pause = true;
1747 track_widx = track_ridx;
1748 audio_clear_track_entries();
1750 track_widx = (track_widx + 1) & MAX_TRACK_MASK;
1752 /* Mark the current track as invalid to prevent skipping back to it */
1753 CUR_TI->taginfo_ready = false;
1756 /* Signal the codec to initiate a track change forward */
1757 new_playlist = true;
1758 ci.new_track = 1;
1760 /* Officially playing */
1761 queue_reply(&audio_queue, 1);
1763 audio_fill_file_buffer(false, 0);
1766 /* Called on manual track skip */
1767 static void audio_initiate_track_change(long direction)
1769 logf("audio_initiate_track_change(%ld)", direction);
1771 ci.new_track += direction;
1772 wps_offset -= direction;
1773 if (paused)
1774 skipped_during_pause = true;
1777 /* Called on manual dir skip */
1778 static void audio_initiate_dir_change(long direction)
1780 dir_skip = true;
1781 ci.new_track = direction;
1782 if (paused)
1783 skipped_during_pause = true;
1786 /* Called when PCM track change is complete */
1787 static void audio_finalise_track_change(void)
1789 logf("audio_finalise_track_change");
1791 if (automatic_skip)
1793 wps_offset = 0;
1794 automatic_skip = false;
1796 /* Invalidate prevtrack_id3 */
1797 memset(othertrack_id3, 0, sizeof(struct mp3entry));
1799 if (prev_ti && prev_ti->audio_hid < 0)
1801 /* No audio left so we clear all the track info. */
1802 clear_track_info(prev_ti);
1805 send_event(PLAYBACK_EVENT_TRACK_CHANGE, thistrack_id3);
1806 playlist_update_resume_info(audio_current_track());
1810 * Layout audio buffer as follows - iram buffer depends on target:
1811 * [|SWAP:iram][|TALK]|FILE|GUARD|PCM|[SWAP:dram[|iram]|]
1813 static void audio_reset_buffer(void)
1815 /* see audio_get_recording_buffer if this is modified */
1816 logf("audio_reset_buffer");
1818 /* If the setup of anything allocated before the file buffer is
1819 changed, do check the adjustments after the buffer_alloc call
1820 as it will likely be affected and need sliding over */
1822 /* Initially set up file buffer as all space available */
1823 malloc_buf = audiobuf + talk_get_bufsize();
1824 /* Align the malloc buf to line size. Especially important to cf
1825 targets that do line reads/writes. */
1826 malloc_buf = (unsigned char *)(((uintptr_t)malloc_buf + 15) & ~15);
1827 filebuf = malloc_buf; /* filebuf line align implied */
1828 filebuflen = audiobufend - filebuf;
1830 filebuflen &= ~15;
1832 /* Subtract whatever the pcm buffer says it used plus the guard buffer */
1833 const size_t pcmbuf_size = pcmbuf_init(filebuf + filebuflen) +GUARD_BUFSIZE;
1835 #ifdef DEBUG
1836 if(pcmbuf_size > filebuflen)
1837 panicf("Not enough memory for pcmbuf_init() : %d > %d",
1838 (int)pcmbuf_size, (int)filebuflen);
1839 #endif
1841 filebuflen -= pcmbuf_size;
1843 /* Make sure filebuflen is a longword multiple after adjustment - filebuf
1844 will already be line aligned */
1845 filebuflen &= ~3;
1847 buffering_reset(filebuf, filebuflen);
1849 /* Clear any references to the file buffer */
1850 buffer_state = AUDIOBUF_STATE_INITIALIZED;
1852 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1853 /* Make sure everything adds up - yes, some info is a bit redundant but
1854 aids viewing and the sumation of certain variables should add up to
1855 the location of others. */
1857 size_t pcmbufsize;
1858 const unsigned char *pcmbuf = pcmbuf_get_meminfo(&pcmbufsize);
1859 logf("mabuf: %08X", (unsigned)malloc_buf);
1860 logf("fbuf: %08X", (unsigned)filebuf);
1861 logf("fbufe: %08X", (unsigned)(filebuf + filebuflen));
1862 logf("gbuf: %08X", (unsigned)(filebuf + filebuflen));
1863 logf("gbufe: %08X", (unsigned)(filebuf + filebuflen + GUARD_BUFSIZE));
1864 logf("pcmb: %08X", (unsigned)pcmbuf);
1865 logf("pcmbe: %08X", (unsigned)(pcmbuf + pcmbufsize));
1867 #endif
1870 static void audio_thread(void)
1872 struct queue_event ev;
1874 pcm_postinit();
1876 audio_thread_ready = true;
1878 while (1)
1880 if (filling != STATE_FILLING && filling != STATE_IDLE) {
1881 /* End of buffering, let's calculate the watermark and unboost */
1882 set_filebuf_watermark();
1883 cancel_cpu_boost();
1886 if (!pcmbuf_queue_scan(&ev))
1887 queue_wait_w_tmo(&audio_queue, &ev, HZ/2);
1889 switch (ev.id) {
1891 case Q_AUDIO_FILL_BUFFER:
1892 LOGFQUEUE("audio < Q_AUDIO_FILL_BUFFER %d", (int)ev.data);
1893 audio_fill_file_buffer((bool)ev.data, 0);
1894 break;
1896 case Q_AUDIO_FINISH_LOAD:
1897 LOGFQUEUE("audio < Q_AUDIO_FINISH_LOAD");
1898 audio_finish_load_track();
1899 break;
1901 case Q_AUDIO_PLAY:
1902 LOGFQUEUE("audio < Q_AUDIO_PLAY");
1903 if (playing && ev.data <= 0)
1904 audio_new_playlist();
1905 else
1907 audio_stop_playback();
1908 audio_play_start((size_t)ev.data);
1910 break;
1912 case Q_AUDIO_STOP:
1913 LOGFQUEUE("audio < Q_AUDIO_STOP");
1914 if (playing)
1915 audio_stop_playback();
1916 if (ev.data != 0)
1917 queue_clear(&audio_queue);
1918 break;
1920 case Q_AUDIO_PAUSE:
1921 LOGFQUEUE("audio < Q_AUDIO_PAUSE");
1922 if (!(bool) ev.data && skipped_during_pause && !pcmbuf_is_crossfade_active())
1923 pcmbuf_play_stop(); /* Flush old track on resume after skip */
1924 skipped_during_pause = false;
1925 if (!playing)
1926 break;
1927 pcmbuf_pause((bool)ev.data);
1928 paused = (bool)ev.data;
1929 break;
1931 case Q_AUDIO_SKIP:
1932 LOGFQUEUE("audio < Q_AUDIO_SKIP");
1933 audio_initiate_track_change((long)ev.data);
1934 break;
1936 case Q_AUDIO_PRE_FF_REWIND:
1937 LOGFQUEUE("audio < Q_AUDIO_PRE_FF_REWIND");
1938 if (!playing)
1939 break;
1940 pcmbuf_pause(true);
1941 break;
1943 case Q_AUDIO_FF_REWIND:
1944 LOGFQUEUE("audio < Q_AUDIO_FF_REWIND");
1945 if (!playing)
1946 break;
1947 if (automatic_skip)
1949 /* An automatic track skip is in progress. Finalize it,
1950 then go back to the previous track */
1951 audio_finalise_track_change();
1952 ci.new_track = -1;
1954 ci.seek_time = (long)ev.data+1;
1955 break;
1957 case Q_AUDIO_CHECK_NEW_TRACK:
1958 LOGFQUEUE("audio < Q_AUDIO_CHECK_NEW_TRACK");
1959 queue_reply(&audio_queue, audio_check_new_track());
1960 break;
1962 case Q_AUDIO_DIR_SKIP:
1963 LOGFQUEUE("audio < Q_AUDIO_DIR_SKIP");
1964 audio_initiate_dir_change(ev.data);
1965 break;
1967 case Q_AUDIO_FLUSH:
1968 LOGFQUEUE("audio < Q_AUDIO_FLUSH");
1969 audio_invalidate_tracks();
1970 break;
1972 case Q_AUDIO_TRACK_CHANGED:
1973 /* PCM track change done */
1974 LOGFQUEUE("audio < Q_AUDIO_TRACK_CHANGED");
1975 audio_finalise_track_change();
1976 break;
1977 #ifndef SIMULATOR
1978 case SYS_USB_CONNECTED:
1979 LOGFQUEUE("audio < SYS_USB_CONNECTED");
1980 if (playing)
1981 audio_stop_playback();
1982 #ifdef PLAYBACK_VOICE
1983 voice_stop();
1984 #endif
1985 usb_acknowledge(SYS_USB_CONNECTED_ACK);
1986 usb_wait_for_disconnect(&audio_queue);
1988 /* Mark all entries null. */
1989 audio_clear_track_entries();
1991 /* release tracks to make sure all handles are closed */
1992 audio_release_tracks();
1993 break;
1994 #endif
1996 case SYS_TIMEOUT:
1997 LOGFQUEUE_SYS_TIMEOUT("audio < SYS_TIMEOUT");
1998 break;
2000 default:
2001 /* LOGFQUEUE("audio < default : %08lX", ev.id); */
2002 break;
2003 } /* end switch */
2004 } /* end while */
2007 /* Initialize the audio system - called from init() in main.c.
2008 * Last function because of all the references to internal symbols
2010 void audio_init(void)
2012 unsigned int audio_thread_id;
2014 /* Can never do this twice */
2015 if (audio_is_initialized)
2017 logf("audio: already initialized");
2018 return;
2021 logf("audio: initializing");
2023 /* Initialize queues before giving control elsewhere in case it likes
2024 to send messages. Thread creation will be delayed however so nothing
2025 starts running until ready if something yields such as talk_init. */
2026 queue_init(&audio_queue, true);
2027 queue_init(&codec_queue, false);
2028 queue_init(&pcmbuf_queue, false);
2030 pcm_init();
2032 codec_init_codec_api();
2034 thistrack_id3 = &mp3entry_buf[0];
2035 othertrack_id3 = &mp3entry_buf[1];
2037 /* cuesheet support */
2038 if (global_settings.cuesheet)
2039 curr_cue = (struct cuesheet*)buffer_alloc(sizeof(struct cuesheet));
2041 /* initialize the buffer */
2042 filebuf = audiobuf;
2044 /* audio_reset_buffer must to know the size of voice buffer so init
2045 talk first */
2046 talk_init();
2048 make_codec_thread();
2050 audio_thread_id = create_thread(audio_thread, audio_stack,
2051 sizeof(audio_stack), CREATE_THREAD_FROZEN,
2052 audio_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE)
2053 IF_COP(, CPU));
2055 queue_enable_queue_send(&audio_queue, &audio_queue_sender_list,
2056 audio_thread_id);
2058 #ifdef PLAYBACK_VOICE
2059 voice_thread_init();
2060 #endif
2062 /* Set crossfade setting for next buffer init which should be about... */
2063 pcmbuf_request_crossfade_enable(global_settings.crossfade);
2065 /* initialize the buffering system */
2067 buffering_init();
2068 /* ...now! Set up the buffers */
2069 audio_reset_buffer();
2071 int i;
2072 for(i = 0; i < MAX_TRACK; i++)
2074 tracks[i].audio_hid = -1;
2075 tracks[i].id3_hid = -1;
2076 tracks[i].codec_hid = -1;
2077 tracks[i].cuesheet_hid = -1;
2079 #ifdef HAVE_ALBUMART
2080 FOREACH_ALBUMART(i)
2082 int j;
2083 for (j = 0; j < MAX_TRACK; j++)
2085 tracks[j].aa_hid[i] = -1;
2088 #endif
2090 add_event(BUFFER_EVENT_REBUFFER, false, buffering_handle_rebuffer_callback);
2091 add_event(BUFFER_EVENT_FINISHED, false, buffering_handle_finished_callback);
2093 /* Probably safe to say */
2094 audio_is_initialized = true;
2096 sound_settings_apply();
2097 #ifdef HAVE_DISK_STORAGE
2098 audio_set_buffer_margin(global_settings.buffer_margin);
2099 #endif
2101 /* it's safe to let the threads run now */
2102 #ifdef PLAYBACK_VOICE
2103 voice_thread_resume();
2104 #endif
2105 thread_thaw(codec_thread_id);
2106 thread_thaw(audio_thread_id);
2108 } /* audio_init */
2110 bool audio_is_thread_ready(void)
2112 return audio_thread_ready;
2115 size_t audio_get_filebuflen(void)
2117 return filebuflen;
2120 int get_audio_hid()
2122 return CUR_TI->audio_hid;
2125 int *get_codec_hid()
2127 return &tracks[track_ridx].codec_hid;
2130 bool audio_is_playing(void)
2132 return playing;
2135 bool audio_is_paused(void)
2137 return paused;