Fix bad rebuffering bug, and kill the track_count variable
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9571 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
2ee282396f
commit
72232bdc66
3 changed files with 168 additions and 156 deletions
|
@ -211,7 +211,6 @@ bool dbg_audio_thread(void)
|
|||
extern size_t audiobuffer_free;
|
||||
extern int filebuflen;
|
||||
extern int filebufused;
|
||||
extern int track_count;
|
||||
|
||||
static unsigned int ticks, boost_ticks;
|
||||
|
||||
|
@ -276,7 +275,7 @@ bool dbg_audio_thread(void)
|
|||
filebufused, HORIZONTAL);
|
||||
line++;
|
||||
|
||||
snprintf(buf, sizeof(buf), "track count: %2d", track_count);
|
||||
snprintf(buf, sizeof(buf), "track count: %2d", audio_track_count());
|
||||
lcd_puts(0, line++, buf);
|
||||
|
||||
snprintf(buf, sizeof(buf), "cpu freq: %3dMHz",
|
||||
|
|
298
apps/playback.c
298
apps/playback.c
|
@ -88,6 +88,7 @@ static volatile bool paused;
|
|||
#define AUDIO_DEFAULT_WATERMARK (1024*512)
|
||||
#define AUDIO_DEFAULT_FILECHUNK (1024*32)
|
||||
#define AUDIO_FILEBUF_CRITICAL (1024*128)
|
||||
#define AUDIO_REBUFFER_GUESS_SIZE (1024*128)
|
||||
|
||||
enum {
|
||||
Q_AUDIO_PLAY = 1,
|
||||
|
@ -96,6 +97,7 @@ enum {
|
|||
Q_AUDIO_SKIP,
|
||||
Q_AUDIO_PRE_FF_REWIND,
|
||||
Q_AUDIO_FF_REWIND,
|
||||
Q_AUDIO_REBUFFER_SEEK,
|
||||
Q_AUDIO_FLUSH_RELOAD,
|
||||
Q_AUDIO_CODEC_DONE,
|
||||
Q_AUDIO_FLUSH,
|
||||
|
@ -138,8 +140,8 @@ static struct event_queue voice_codec_queue;
|
|||
static long voice_codec_stack[(DEFAULT_STACK_SIZE + 0x2000)/sizeof(long)] IBSS_ATTR;
|
||||
static const char voice_codec_thread_name[] = "voice codec";
|
||||
|
||||
static struct mutex mutex_bufferfill;
|
||||
static struct mutex mutex_codecthread;
|
||||
static struct mutex mutex_rebuffer;
|
||||
|
||||
static struct mp3entry id3_voice;
|
||||
|
||||
|
@ -178,7 +180,6 @@ static int last_peek_offset;
|
|||
|
||||
/* Track information (count in file buffer, read/write indexes for
|
||||
track ring structure. */
|
||||
int track_count;
|
||||
static volatile int track_ridx;
|
||||
static volatile int track_widx;
|
||||
static bool track_changed;
|
||||
|
@ -451,6 +452,38 @@ static bool filebuf_is_lowdata(void)
|
|||
return filebufused < AUDIO_FILEBUF_CRITICAL;
|
||||
}
|
||||
|
||||
static bool have_tracks(void)
|
||||
{
|
||||
return track_ridx != track_widx || tracks[track_ridx].filesize;
|
||||
}
|
||||
|
||||
static bool have_free_tracks(void)
|
||||
{
|
||||
if (track_widx < track_ridx)
|
||||
return track_widx + 1 < track_ridx;
|
||||
else if (track_ridx == 0)
|
||||
return track_widx < MAX_TRACK - 1;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
int audio_track_count(void)
|
||||
{
|
||||
int track_count = 0;
|
||||
if (have_tracks())
|
||||
{
|
||||
int cur_idx = track_ridx;
|
||||
track_count++;
|
||||
while (cur_idx != track_widx)
|
||||
{
|
||||
track_count++;
|
||||
if (++cur_idx > MAX_TRACK)
|
||||
cur_idx -= MAX_TRACK;
|
||||
}
|
||||
}
|
||||
return track_count;
|
||||
}
|
||||
|
||||
static void advance_buffer_counters(size_t amount) {
|
||||
buf_ridx += amount;
|
||||
if (buf_ridx >= filebuflen)
|
||||
|
@ -597,19 +630,23 @@ void* codec_request_buffer_callback(size_t *realsize, size_t reqsize)
|
|||
return (char *)&filebuf[buf_ridx];
|
||||
}
|
||||
|
||||
static bool rebuffer_and_seek(size_t newpos)
|
||||
static void rebuffer_and_seek(size_t newpos)
|
||||
{
|
||||
int fd;
|
||||
size_t filepos;
|
||||
|
||||
logf("Re-buffering song");
|
||||
mutex_lock(&mutex_bufferfill);
|
||||
/* Prevent multiple rebuffer calls on codecs that 'hunt' when seeking */
|
||||
if (newpos > AUDIO_REBUFFER_GUESS_SIZE)
|
||||
filepos = newpos - AUDIO_REBUFFER_GUESS_SIZE;
|
||||
else
|
||||
filepos = 0;
|
||||
|
||||
/* (Re-)open current track's file handle. */
|
||||
fd = open(playlist_peek(0), O_RDONLY);
|
||||
if (fd < 0) {
|
||||
logf("Open failed!");
|
||||
mutex_unlock(&mutex_bufferfill);
|
||||
return false;
|
||||
mutex_unlock(&mutex_rebuffer);
|
||||
return;
|
||||
}
|
||||
if (current_fd >= 0)
|
||||
close(current_fd);
|
||||
|
@ -620,18 +657,15 @@ static bool rebuffer_and_seek(size_t newpos)
|
|||
filebufused = 0;
|
||||
playlist_end = false;
|
||||
buf_ridx = buf_widx = 0;
|
||||
cur_ti->filerem = cur_ti->filesize - newpos;
|
||||
cur_ti->filepos = newpos;
|
||||
cur_ti->start_pos = newpos;
|
||||
cur_ti->filerem = cur_ti->filesize - filepos;
|
||||
cur_ti->filepos = filepos;
|
||||
cur_ti->start_pos = filepos;
|
||||
ci.curpos = newpos;
|
||||
cur_ti->available = 0;
|
||||
lseek(current_fd, newpos, SEEK_SET);
|
||||
|
||||
mutex_unlock(&mutex_bufferfill);
|
||||
lseek(current_fd, filepos, SEEK_SET);
|
||||
|
||||
queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER, 0);
|
||||
|
||||
return true;
|
||||
mutex_unlock(&mutex_rebuffer);
|
||||
}
|
||||
|
||||
void codec_advance_buffer_callback(size_t amount)
|
||||
|
@ -653,8 +687,11 @@ void codec_advance_buffer_callback(size_t amount)
|
|||
|
||||
/* This should not happen */
|
||||
if (amount > cur_ti->available) {
|
||||
if (!rebuffer_and_seek(ci.curpos + amount))
|
||||
ci.stop_codec = true;
|
||||
mutex_lock(&mutex_rebuffer);
|
||||
queue_post(&audio_queue,
|
||||
Q_AUDIO_REBUFFER_SEEK, (void *)(ci.curpos + amount));
|
||||
mutex_lock(&mutex_rebuffer);
|
||||
mutex_unlock(&mutex_rebuffer);
|
||||
return ;
|
||||
}
|
||||
|
||||
|
@ -722,7 +759,10 @@ bool codec_seek_buffer_callback(size_t newpos)
|
|||
|
||||
/* We need to reload the song. */
|
||||
if (newpos < cur_ti->start_pos)
|
||||
return rebuffer_and_seek(newpos);
|
||||
{
|
||||
queue_post(&audio_queue, Q_AUDIO_REBUFFER_SEEK, (void *)newpos);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Seeking inside buffer space. */
|
||||
logf("seek: -%d", difference);
|
||||
|
@ -878,8 +918,6 @@ static void audio_read_file(void)
|
|||
return ;
|
||||
}
|
||||
|
||||
mutex_lock(&mutex_bufferfill);
|
||||
|
||||
/* Throw away buffered codec. */
|
||||
if (tracks[track_widx].start_pos != 0)
|
||||
tracks[track_widx].codecsize = 0;
|
||||
|
@ -931,8 +969,6 @@ static void audio_read_file(void)
|
|||
} else {
|
||||
logf("Partially buf:%d", tracks[track_widx].available);
|
||||
}
|
||||
|
||||
mutex_unlock(&mutex_bufferfill);
|
||||
}
|
||||
|
||||
static int get_codec_base_type(int type)
|
||||
|
@ -1032,7 +1068,7 @@ static bool loadcodec(bool start_play)
|
|||
prev_track = track_widx - 1;
|
||||
if (prev_track < 0)
|
||||
prev_track = MAX_TRACK-1;
|
||||
if (track_count > 0 &&
|
||||
if (have_tracks() &&
|
||||
get_codec_base_type(tracks[track_widx].id3.codectype) ==
|
||||
get_codec_base_type(tracks[prev_track].id3.codectype))
|
||||
{
|
||||
|
@ -1059,7 +1095,6 @@ static bool loadcodec(bool start_play)
|
|||
return false;
|
||||
}
|
||||
|
||||
mutex_lock(&mutex_bufferfill);
|
||||
i = 0;
|
||||
while (i < size) {
|
||||
copy_n = MIN(conf_filechunk, filebuflen - buf_widx);
|
||||
|
@ -1078,7 +1113,6 @@ static bool loadcodec(bool start_play)
|
|||
* queue during this loop */
|
||||
yield_codecs();
|
||||
}
|
||||
mutex_unlock(&mutex_bufferfill);
|
||||
|
||||
close(fd);
|
||||
logf("Done: %dB", i);
|
||||
|
@ -1142,9 +1176,8 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
|
|||
/* Stop buffer filling if there is no free track entries.
|
||||
Don't fill up the last track entry (we wan't to store next track
|
||||
metadata there). */
|
||||
if (track_count >= MAX_TRACK - 1) {
|
||||
if (!have_free_tracks())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (current_fd >= 0)
|
||||
{
|
||||
|
@ -1268,52 +1301,49 @@ static bool audio_load_track(int offset, bool start_play, int peek_offset)
|
|||
}
|
||||
|
||||
if (start_play) {
|
||||
track_count++;
|
||||
codec_track_changed();
|
||||
}
|
||||
|
||||
audio_read_file();
|
||||
|
||||
if (!start_play)
|
||||
track_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void audio_clear_track_entries(bool buffered_only)
|
||||
{
|
||||
int cur_idx, event_count;
|
||||
int i;
|
||||
int cur_idx;
|
||||
int last_idx = 0;
|
||||
|
||||
/* Loop over all tracks from write index to read index. */
|
||||
cur_idx = track_widx;
|
||||
event_count = 0;
|
||||
for (i = 0; i < MAX_TRACK - track_count; i++) {
|
||||
while (1) {
|
||||
if (++cur_idx >= MAX_TRACK)
|
||||
cur_idx = 0;
|
||||
if (cur_idx == track_ridx)
|
||||
break;
|
||||
|
||||
if (tracks[cur_idx].event_sent)
|
||||
event_count++;
|
||||
|
||||
if (!track_unbuffer_callback)
|
||||
memset(&tracks[cur_idx], 0, sizeof(struct track_info));
|
||||
}
|
||||
|
||||
if (!track_unbuffer_callback)
|
||||
return ;
|
||||
|
||||
cur_idx = track_widx;
|
||||
for (i = 0; i < MAX_TRACK - track_count; i++) {
|
||||
if (++cur_idx >= MAX_TRACK)
|
||||
cur_idx = 0;
|
||||
|
||||
/* Send an event to notify that track has finished. */
|
||||
/* If the track is buffered, conditionally clear/notify,
|
||||
* otherwise clear the track if that option is selected */
|
||||
if (tracks[cur_idx].event_sent) {
|
||||
event_count--;
|
||||
track_unbuffer_callback(&tracks[cur_idx].id3, event_count == 0);
|
||||
/* If there is an unbuffer callback, call it, otherwise, just
|
||||
* clear the track */
|
||||
if (track_unbuffer_callback)
|
||||
track_unbuffer_callback(&tracks[last_idx].id3, false);
|
||||
|
||||
memset(&tracks[last_idx], 0, sizeof(struct track_info));
|
||||
last_idx = cur_idx;
|
||||
} else if (!buffered_only)
|
||||
memset(&tracks[cur_idx], 0, sizeof(struct track_info));
|
||||
}
|
||||
|
||||
if (tracks[cur_idx].event_sent || !buffered_only)
|
||||
memset(&tracks[cur_idx], 0, sizeof(struct track_info));
|
||||
/* We clear the previous instance of a buffered track throughout
|
||||
* the above loop to facilitate 'last' detection. Clear/notify
|
||||
* the last track here */
|
||||
if (last_idx)
|
||||
{
|
||||
if (track_unbuffer_callback)
|
||||
track_unbuffer_callback(&tracks[last_idx].id3, true);
|
||||
memset(&tracks[last_idx], 0, sizeof(struct track_info));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1339,7 +1369,6 @@ static void audio_stop_playback(bool resume)
|
|||
current_fd = -1;
|
||||
}
|
||||
|
||||
track_count = 0;
|
||||
/* Mark all entries null. */
|
||||
audio_clear_track_entries(false);
|
||||
}
|
||||
|
@ -1353,15 +1382,13 @@ static void audio_play_start(size_t offset)
|
|||
current_fd = -1;
|
||||
}
|
||||
|
||||
memset(&tracks, 0, sizeof(struct track_info) * MAX_TRACK);
|
||||
sound_set_volume(global_settings.volume);
|
||||
track_count = 0;
|
||||
track_widx = 0;
|
||||
track_ridx = 0;
|
||||
buf_ridx = 0;
|
||||
buf_widx = 0;
|
||||
track_widx = track_ridx = 0;
|
||||
buf_ridx = buf_widx = 0;
|
||||
filebufused = 0;
|
||||
|
||||
memset(&tracks[0], 0, sizeof(struct track_info));
|
||||
|
||||
last_peek_offset = -1;
|
||||
|
||||
if (offset == 0) parameter = -1;
|
||||
|
@ -1373,81 +1400,69 @@ static void audio_play_start(size_t offset)
|
|||
/* Send callback events to notify about new tracks. */
|
||||
static void generate_postbuffer_events(void)
|
||||
{
|
||||
int i;
|
||||
int cur_ridx, event_count;
|
||||
int cur_idx;
|
||||
int last_idx = 0;
|
||||
|
||||
/* At first determine how many unsent events we have. */
|
||||
cur_ridx = track_ridx;
|
||||
event_count = 0;
|
||||
for (i = 0; i < track_count; i++) {
|
||||
if (!tracks[cur_ridx].event_sent)
|
||||
event_count++;
|
||||
if (++cur_ridx >= MAX_TRACK)
|
||||
cur_ridx -= MAX_TRACK;
|
||||
}
|
||||
|
||||
/* Now sent these events. */
|
||||
cur_ridx = track_ridx;
|
||||
for (i = 0; i < track_count; i++) {
|
||||
if (!tracks[cur_ridx].event_sent) {
|
||||
tracks[cur_ridx].event_sent = true;
|
||||
event_count--;
|
||||
/* We still want to set event_sent flags even if not using
|
||||
event callbacks. */
|
||||
if (have_tracks()) {
|
||||
cur_idx = track_ridx;
|
||||
while (1) {
|
||||
if (!tracks[cur_idx].event_sent) {
|
||||
if (last_idx) {
|
||||
/* Mark the event 'sent' even if we don't really send one */
|
||||
tracks[last_idx].event_sent = true;
|
||||
if (track_buffer_callback)
|
||||
track_buffer_callback(&tracks[cur_ridx].id3, event_count == 0);
|
||||
track_buffer_callback(&tracks[last_idx].id3, false);
|
||||
}
|
||||
last_idx = cur_idx;
|
||||
}
|
||||
if (cur_idx == track_widx)
|
||||
break;
|
||||
if (++cur_idx >= MAX_TRACK)
|
||||
cur_idx -= MAX_TRACK;
|
||||
}
|
||||
|
||||
if (last_idx) {
|
||||
tracks[last_idx].event_sent = true;
|
||||
if (track_buffer_callback)
|
||||
track_buffer_callback(&tracks[last_idx].id3, true);
|
||||
}
|
||||
if (++cur_ridx >= MAX_TRACK)
|
||||
cur_ridx -= MAX_TRACK;
|
||||
}
|
||||
}
|
||||
|
||||
static void initialize_buffer_fill(bool start_play)
|
||||
{
|
||||
int cur_idx, i;
|
||||
|
||||
if (!filling_initial && !start_play)
|
||||
if (start_play) {
|
||||
filling_initial = true;
|
||||
fill_bytesleft = filebuflen >> 2;
|
||||
}
|
||||
else if (!filling_initial)
|
||||
{
|
||||
fill_bytesleft = filebuflen - filebufused;
|
||||
cur_ti->start_pos = ci.curpos;
|
||||
/* Recalculate remaining bytes to buffer, but always leave extra
|
||||
* data for the currently playing codec to seek back into */
|
||||
size_t buf_bytesleft = filebuflen - filebufused;
|
||||
|
||||
if (buf_bytesleft > AUDIO_REBUFFER_GUESS_SIZE)
|
||||
fill_bytesleft = buf_bytesleft - AUDIO_REBUFFER_GUESS_SIZE;
|
||||
else
|
||||
fill_bytesleft = 0;
|
||||
|
||||
if (ci.curpos > AUDIO_REBUFFER_GUESS_SIZE)
|
||||
cur_ti->start_pos = ci.curpos - AUDIO_REBUFFER_GUESS_SIZE;
|
||||
else
|
||||
cur_ti->start_pos = 0;
|
||||
}
|
||||
|
||||
/* Initialize only once; do not truncate the tracks. */
|
||||
if (filling)
|
||||
return ;
|
||||
|
||||
/* Save the current resume position once. */
|
||||
playlist_update_resume_info(audio_current_track());
|
||||
|
||||
pcmbuf_set_boost_mode(true);
|
||||
|
||||
if (!start_play) {
|
||||
/* Calculate real track count after throwing away old tracks. */
|
||||
cur_idx = track_ridx;
|
||||
for (i = 0; i < track_count; i++) {
|
||||
if (cur_idx == track_widx)
|
||||
break ;
|
||||
|
||||
if (++cur_idx >= MAX_TRACK)
|
||||
cur_idx = 0;
|
||||
}
|
||||
|
||||
track_count = i;
|
||||
if (tracks[track_widx].filesize == 0) {
|
||||
if (--track_widx < 0)
|
||||
track_widx = MAX_TRACK - 1;
|
||||
} else {
|
||||
track_count++;
|
||||
}
|
||||
|
||||
/* Mark all buffered entries null (not metadata for next track). */
|
||||
audio_clear_track_entries(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
filling_initial = true;
|
||||
fill_bytesleft = filebuflen >> 2;
|
||||
}
|
||||
audio_clear_track_entries(!start_play);
|
||||
|
||||
/* Save the current resume position once. */
|
||||
playlist_update_resume_info(audio_current_track());
|
||||
|
||||
filling = true;
|
||||
|
||||
|
@ -1459,9 +1474,7 @@ static void audio_fill_file_buffer(bool start_play, size_t offset)
|
|||
if (ci.stop_codec || ci.reload_codec || playlist_end)
|
||||
return;
|
||||
|
||||
mutex_lock(&mutex_bufferfill);
|
||||
initialize_buffer_fill(start_play);
|
||||
mutex_unlock(&mutex_bufferfill);
|
||||
|
||||
/* If we have a partially buffered track, continue loading, otherwise
|
||||
* load a new track */
|
||||
|
@ -1602,7 +1615,7 @@ static int skip_previous_track(bool inside_codec_thread)
|
|||
track_ridx += MAX_TRACK;
|
||||
|
||||
if (tracks[track_ridx].filesize == 0 ||
|
||||
filebufused+ci.curpos + tracks[track_ridx].filesize > filebuflen)
|
||||
filebufused + ci.curpos + tracks[track_ridx].filesize > filebuflen)
|
||||
{
|
||||
logf("Loading from disk...");
|
||||
ci.reload_codec = true;
|
||||
|
@ -1729,24 +1742,27 @@ bool codec_request_next_track_callback(void)
|
|||
/* Invalidates all but currently playing track. */
|
||||
void audio_invalidate_tracks(void)
|
||||
{
|
||||
if (track_count == 0) {
|
||||
/* This call doesn't seem necessary anymore. Uncomment it
|
||||
if things break */
|
||||
/* queue_post(&audio_queue, Q_AUDIO_PLAY, 0); */
|
||||
return ;
|
||||
}
|
||||
|
||||
if (have_tracks()) {
|
||||
playlist_end = false;
|
||||
track_count = 1;
|
||||
last_peek_offset = 0;
|
||||
|
||||
track_widx = track_ridx;
|
||||
/* Mark all other entries null (also buffered wrong metadata). */
|
||||
|
||||
audio_clear_track_entries(false);
|
||||
|
||||
/* If the current track is fully buffered, advance the write pointer */
|
||||
if (tracks[track_ridx].filerem == 0)
|
||||
if (++track_widx >= MAX_TRACK)
|
||||
track_widx -= MAX_TRACK;
|
||||
|
||||
/* Mark all other entries null (also buffered wrong metadata). */
|
||||
filebufused = cur_ti->available;
|
||||
buf_widx = buf_ridx + cur_ti->available;
|
||||
if (buf_widx >= filebuflen)
|
||||
buf_widx -= filebuflen;
|
||||
|
||||
read_next_metadata();
|
||||
}
|
||||
}
|
||||
|
||||
static void initiate_track_change(long peek_index)
|
||||
|
@ -1816,7 +1832,6 @@ void audio_thread(void)
|
|||
case Q_AUDIO_PLAY:
|
||||
/* Don't start playing immediately if user is skipping tracks
|
||||
* fast to prevent UI lag. */
|
||||
track_count = 0;
|
||||
last_peek_offset = 0;
|
||||
track_changed = true;
|
||||
playlist_end = false;
|
||||
|
@ -1881,6 +1896,11 @@ void audio_thread(void)
|
|||
ci.seek_time = (long)ev.data+1;
|
||||
break ;
|
||||
|
||||
case Q_AUDIO_REBUFFER_SEEK:
|
||||
logf("Re-buffering song");
|
||||
rebuffer_and_seek((size_t)ev.data);
|
||||
break;
|
||||
|
||||
case Q_AUDIO_DIR_SKIP:
|
||||
logf("audio_dir_skip");
|
||||
playlist_end = false;
|
||||
|
@ -2095,7 +2115,7 @@ struct mp3entry* audio_current_track(void)
|
|||
const char *p;
|
||||
static struct mp3entry temp_id3;
|
||||
|
||||
if (track_count > 0 && cur_ti->taginfo_ready)
|
||||
if (have_tracks() && cur_ti->taginfo_ready)
|
||||
return (struct mp3entry *)&cur_ti->id3;
|
||||
|
||||
memset(&temp_id3, 0, sizeof(struct mp3entry));
|
||||
|
@ -2125,7 +2145,7 @@ struct mp3entry* audio_next_track(void)
|
|||
{
|
||||
int next_idx = track_ridx + 1;
|
||||
|
||||
if (track_count == 0)
|
||||
if (!have_tracks())
|
||||
return NULL;
|
||||
|
||||
if (next_idx >= MAX_TRACK)
|
||||
|
@ -2198,10 +2218,6 @@ void audio_next(void)
|
|||
playlist_next(1);
|
||||
track_changed = true;
|
||||
|
||||
/* Force WPS to update even if audio thread is blocked spinning. */
|
||||
if (mutex_bufferfill.locked)
|
||||
cur_ti->taginfo_ready = false;
|
||||
|
||||
queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)1);
|
||||
}
|
||||
|
||||
|
@ -2216,10 +2232,6 @@ void audio_prev(void)
|
|||
playlist_next(-1);
|
||||
track_changed = true;
|
||||
|
||||
/* Force WPS to update even if audio thread is blocked spinning. */
|
||||
if (mutex_bufferfill.locked)
|
||||
cur_ti->taginfo_ready = false;
|
||||
|
||||
queue_post(&audio_queue, Q_AUDIO_SKIP, (void *)-1);
|
||||
}
|
||||
|
||||
|
@ -2573,8 +2585,8 @@ void audio_preinit(void)
|
|||
/* Just to prevent cur_ti never be anything random. */
|
||||
cur_ti = &tracks[0];
|
||||
|
||||
mutex_init(&mutex_bufferfill);
|
||||
mutex_init(&mutex_codecthread);
|
||||
mutex_init(&mutex_rebuffer);
|
||||
|
||||
queue_init(&audio_queue);
|
||||
queue_init(&codec_queue);
|
||||
|
|
|
@ -70,6 +70,7 @@ void audio_resume(void);
|
|||
void audio_next(void);
|
||||
void audio_prev(void);
|
||||
int audio_status(void);
|
||||
int audio_track_count(void); /* SWCODEC only */
|
||||
void audio_pre_ff_rewind(void); /* SWCODEC only */
|
||||
void audio_ff_rewind(long newtime);
|
||||
void audio_flush_and_reload_tracks(void);
|
||||
|
|
Loading…
Reference in a new issue