Index: apps/playback.c =================================================================== --- apps/playback.c (revision 15465) +++ apps/playback.c (working copy) @@ -97,7 +97,7 @@ #define AUDIO_REBUFFER_GUESS_SIZE (1024*32) /* Define LOGF_ENABLE to enable logf output in this file */ -/*#define LOGF_ENABLE*/ +#define LOGF_ENABLE #include "logf.h" /* macros to enable logf for queues @@ -343,6 +343,9 @@ #endif /* PLAYBACK_VOICE */ +/* Definitions needed to keep the file ordering sane */ +static void audio_rebuffer(size_t offset); +static void audio_update_trackinfo(void); /* --- Helper functions --- */ @@ -1643,7 +1646,11 @@ logf("codec_seek_buffer_callback"); int ret = bufseek(CUR_TI->audio_hid, newpos); - if (ret == 0) { + if (ret == ERR_NEED_REBUFFER) { + audio_rebuffer(newpos); + audio_update_trackinfo(); + return true; + } else if (ret == 0) { ci.curpos = newpos; return true; } @@ -1663,10 +1670,6 @@ buf_set_conf(BUFFERING_SET_CHUNKSIZE, value); break; - case CODEC_SET_FILEBUF_PRESEEK: - buf_set_conf(BUFFERING_SET_PRESEEK, value); - break; - default: if (!dsp_configure(setting, value)) { logf("Illegal key:%d", setting); } } @@ -2295,7 +2298,6 @@ set_current_codec(CODEC_IDX_AUDIO); buf_set_conf(BUFFERING_SET_WATERMARK, AUDIO_DEFAULT_WATERMARK); buf_set_conf(BUFFERING_SET_CHUNKSIZE, AUDIO_DEFAULT_FILECHUNK); - buf_set_conf(BUFFERING_SET_PRESEEK, AUDIO_REBUFFER_GUESS_SIZE); dsp_configure(DSP_RESET, 0); set_current_codec(last_codec); @@ -2441,8 +2443,12 @@ logf("alt:%s", trackname); - if (!file_offset && track_id3->first_frame_offset) + if (file_offset > AUDIO_REBUFFER_GUESS_SIZE) + file_offset -= AUDIO_REBUFFER_GUESS_SIZE; + else if (track_id3->first_frame_offset) file_offset = track_id3->first_frame_offset; + else + file_offset = 0; tracks[track_widx].audio_hid = bufopen(trackname, file_offset, type); @@ -2533,7 +2539,7 @@ register_buffer_low_callback(low_buffer_callback); } -static void audio_rebuffer(void) +static void audio_rebuffer(size_t offset) { logf("Forcing rebuffer"); @@ -2545,12 +2551,12 @@ /* Fill the buffer */ last_peek_offset = -1; - ci.curpos = 0; + ci.curpos = offset; if (!CUR_TI->taginfo_ready) memset(&curtrack_id3, 0, sizeof(struct mp3entry)); - audio_fill_file_buffer(false, 0); + audio_fill_file_buffer(false, offset); } static int audio_check_new_track(void) @@ -2565,7 +2571,7 @@ if (playlist_next_dir(ci.new_track)) { ci.new_track = 0; - audio_rebuffer(); + audio_rebuffer(0); goto skip_done; } else @@ -2638,7 +2644,7 @@ if (ci.new_track >= track_count || ci.new_track <= track_count - MAX_TRACK) { ci.new_track = 0; - audio_rebuffer(); + audio_rebuffer(0); goto skip_done; } @@ -2648,7 +2654,7 @@ /* If the target track is clearly not in memory */ if (CUR_TI->filesize == 0 || !CUR_TI->taginfo_ready) { - audio_rebuffer(); + audio_rebuffer(0); goto skip_done; } @@ -2684,7 +2690,7 @@ } if (!taginfo_ready) { - audio_rebuffer(); + audio_rebuffer(0); } } Index: apps/buffering.c =================================================================== --- apps/buffering.c (revision 15465) +++ apps/buffering.c (working copy) @@ -60,7 +60,7 @@ #endif /* Define LOGF_ENABLE to enable logf output in this file */ -/*#define LOGF_ENABLE*/ +#define LOGF_ENABLE #include "logf.h" /* macros to enable logf for queues @@ -135,8 +135,6 @@ static size_t conf_watermark = 0; /* Level to trigger filebuf fill */ static size_t conf_filechunk = 0; /* Bytes-per-read for buffering (impacts responsiveness of buffering thread) */ -static size_t conf_preseek = 0; /* Distance a codec may look backwards after - seeking, to prevent double rebuffers */ #if MEM > 8 static size_t high_watermark = 0; /* High watermark for rebuffer */ #endif @@ -178,7 +176,6 @@ /* Configuration: */ Q_SET_WATERMARK, Q_SET_CHUNKSIZE, - Q_SET_PRESEEK, }; /* Buffering thread */ @@ -646,19 +643,21 @@ } /* Seek to a nonbuffered part of a handle by rebuffering the data. */ -static void rebuffer_handle(int handle_id, size_t newpos) +/* FIXME: This is entirely broken and needs to move the start position of + * this handle earlier if it moves the offset backwards */ +static void rebuffer_handle(struct memory_handle *h, size_t newpos) { - struct memory_handle *h = find_handle(handle_id); + if (!h) return; h->offset = newpos; LOGFQUEUE("buffering >| buffering Q_RESET_HANDLE"); - queue_send(&buffering_queue, Q_RESET_HANDLE, handle_id); + queue_send(&buffering_queue, Q_RESET_HANDLE, h->id); LOGFQUEUE("buffering >| buffering Q_BUFFER_HANDLE"); - queue_send(&buffering_queue, Q_BUFFER_HANDLE, handle_id); + queue_send(&buffering_queue, Q_BUFFER_HANDLE, h->id); h->ridx = h->data; } @@ -925,10 +924,18 @@ /* access beyond the end of the file */ return ERR_INVALID_VALUE; } - else if (newpos < h->offset || h->offset + h->available < newpos) { + else if (h->offset + h->available < newpos) { /* access before or after buffered data. A rebuffer is needed. */ - rebuffer_handle(handle_id, newpos); + rebuffer_handle(h, newpos); } + else if (h->offset > newpos) { + /* Can't go backwards if there is a handle both after and before us + * period. also can't go backwards safely if buffer is filling, and + * would need separate methods entirely for the indvidual cases of + * handle ahead and behind. Therefor don't even try it, just force a + * rebuffer. */ + return ERR_NEED_REBUFFER; + } else { h->ridx = RINGBUF_ADD(h->data, newpos - h->offset); } @@ -1112,10 +1119,6 @@ msg = Q_SET_CHUNKSIZE; break; - case BUFFERING_SET_PRESEEK: - msg = Q_SET_PRESEEK; - break; - default: return; } @@ -1238,11 +1241,6 @@ } break; - case Q_SET_PRESEEK: - LOGFQUEUE("buffering < Q_SET_PRESEEK"); - conf_preseek = (size_t)ev.data; - break; - #ifndef SIMULATOR case SYS_USB_CONNECTED: LOGFQUEUE("buffering < SYS_USB_CONNECTED"); Index: apps/buffering.h =================================================================== --- apps/buffering.h (revision 15446) +++ apps/buffering.h (working copy) @@ -40,6 +40,7 @@ #define ERR_BUFFER_FULL -2 #define ERR_INVALID_VALUE -3 #define ERR_FILE_ERROR -4 +#define ERR_NEED_REBUFFER -5 /* Initialise the buffering subsystem */ @@ -116,7 +117,6 @@ enum { BUFFERING_SET_WATERMARK = 1, BUFFERING_SET_CHUNKSIZE, - BUFFERING_SET_PRESEEK, }; void buf_set_conf(int setting, size_t value);