summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2005-07-01 18:22:04 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2005-07-01 18:22:04 +0000
commitbbd42ad80b8627a8d5d74cbbe895e86164d5feda (patch)
treed5eee586d3434dfc8cbf4c155d0555344d0dcb8d
parent2722ba87d1d66d732227a67e304b2a21bd19c2aa (diff)
Fixed seeking in mp3 files (and with other codecs which supports
seeking currently). Even long seeks should be possible. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6973 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/playback.c103
-rw-r--r--apps/playback.h1
2 files changed, 66 insertions, 38 deletions
diff --git a/apps/playback.c b/apps/playback.c
index 76c8b29db1..e504ef5892 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -117,6 +117,8 @@ __attribute__ ((section(".idata")))
;
static const char codec_thread_name[] = "codec";
+static struct mutex mutex_bufferfill;
+
/* Is file buffer currently being refilled? */
static volatile bool filling;
@@ -436,27 +438,50 @@ void* codec_request_buffer_callback(long *realsize, long reqsize)
return (char *)&codecbuf[buf_ridx];
}
+static bool rebuffer_and_seek(int newpos)
+{
+ int fd;
+
+ logf("Re-buffering song");
+ mutex_lock(&mutex_bufferfill);
+
+ /* (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;
+ }
+ if (current_fd >= 0)
+ close(current_fd);
+ current_fd = fd;
+
+ /* Clear codec buffer. */
+ audio_invalidate_tracks();
+ codecbufused = 0;
+ buf_ridx = buf_widx = 0;
+ cur_ti->filerem = cur_ti->filesize - newpos;
+ cur_ti->filepos = newpos;
+ cur_ti->start_pos = newpos;
+ ci.curpos = newpos;
+ cur_ti->available = 0;
+ lseek(current_fd, newpos, SEEK_SET);
+ pcm_flush_audio();
+
+ mutex_unlock(&mutex_bufferfill);
+
+ return true;
+}
+
void codec_advance_buffer_callback(long amount)
{
- if ((int)amount > cur_ti->available + cur_ti->filerem)
+ if (amount > cur_ti->available + cur_ti->filerem)
amount = cur_ti->available + cur_ti->filerem;
- try_again:
- if ((int)amount > cur_ti->available) {
- if (filling) {
- while (filling)
- yield();
- goto try_again;
- }
- codecbufused = 0;
- buf_ridx = 0;
- buf_widx = 0;
- cur_ti->start_pos = ci.curpos + amount;
- amount -= cur_ti->available;
- ci.curpos += cur_ti->available;
- cur_ti->available = 0;
- while ((int)amount > cur_ti->available && !ci.stop_codec)
- yield();
+ if (amount > cur_ti->available) {
+ if (!rebuffer_and_seek(ci.curpos + amount))
+ ci.stop_codec = true;
+ return ;
}
buf_ridx += amount;
@@ -495,8 +520,9 @@ bool codec_seek_buffer_callback(off_t newpos)
if (newpos >= cur_ti->filesize)
newpos = cur_ti->filesize - 1;
-
+
difference = newpos - ci.curpos;
+ /* Seeking forward */
if (difference >= 0) {
logf("seek: +%d", difference);
codec_advance_buffer_callback(difference);
@@ -504,17 +530,17 @@ bool codec_seek_buffer_callback(off_t newpos)
pcm_play_stop();
return true;
}
-
+
+ /* Seeking backward */
difference = -difference;
if (ci.curpos - difference < 0)
difference = ci.curpos;
- if (ci.curpos - difference < cur_ti->start_pos) {
- logf("Seek failed (reload song)");
- /* We need to reload the song. FIX THIS! */
- return false;
- }
-
+ /* We need to reload the song. */
+ if (newpos < cur_ti->start_pos)
+ return rebuffer_and_seek(newpos);
+
+ /* Seeking inside buffer space. */
logf("seek: -%d", difference);
codecbufused += difference;
cur_ti->available += difference;
@@ -582,10 +608,14 @@ void audio_fill_file_buffer(void)
{
long i, size;
int rc;
-
+
if (current_fd < 0)
return ;
-
+
+ /* Throw away buffered codec. */
+ if (tracks[track_widx].start_pos != 0)
+ tracks[track_widx].codecsize = 0;
+
i = 0;
size = MIN(tracks[track_widx].filerem, AUDIO_FILL_CYCLE);
while (i < size) {
@@ -615,10 +645,6 @@ void audio_fill_file_buffer(void)
tracks[track_widx].filepos += i;
/*logf("Filled:%d/%d", tracks[track_widx].available,
tracks[track_widx].filerem);*/
- if (tracks[track_widx].filerem == 0) {
- close(current_fd);
- current_fd = -1;
- }
}
bool loadcodec(const char *trackname, bool start_play)
@@ -745,8 +771,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset)
int rc, i;
int copy_n;
- if (track_count >= MAX_TRACK || tracks[track_widx].filesize != 0
- || current_fd >= 0)
+ if (track_count >= MAX_TRACK || tracks[track_widx].filesize != 0)
return false;
logf("Buffering track:%d/%d", track_widx, track_ridx);
@@ -1026,6 +1051,7 @@ void audio_update_trackinfo(void)
ci.id3 = (struct mp3entry *)&cur_ti->id3;
ci.mp3data = (struct mp3info *)&cur_ti->mp3data;
ci.curpos = 0;
+ cur_ti->start_pos = 0;
ci.taginfo_ready = (bool *)&cur_ti->taginfo_ready;
audiobuffer_add_event(codec_track_changed);
}
@@ -1132,10 +1158,6 @@ void audio_invalidate_tracks(void)
track_count = 1;
last_peek_offset = 1;
- if (cur_ti->filerem == 0 && current_fd >= 0) {
- close(current_fd);
- current_fd = -1;
- }
track_widx = track_ridx;
audio_clear_track_entries();
codecbufused = cur_ti->available;
@@ -1150,7 +1172,11 @@ void audio_thread(void)
while (1) {
yield_codecs();
+
+ mutex_lock(&mutex_bufferfill);
audio_check_buffer();
+ mutex_unlock(&mutex_bufferfill);
+
queue_wait_w_tmo(&audio_queue, &ev, 0);
switch (ev.id) {
case AUDIO_PLAY:
@@ -1587,7 +1613,8 @@ void audio_init(void)
ci.seek_buffer = codec_seek_buffer_callback;
ci.set_elapsed = codec_set_elapsed_callback;
ci.configure = codec_configure_callback;
-
+
+ mutex_init(&mutex_bufferfill);
queue_init(&audio_queue);
queue_init(&codec_queue);
diff --git a/apps/playback.h b/apps/playback.h
index ac3765150d..5cebfa84b3 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -62,6 +62,7 @@ struct track_info {
/* Functions */
void audio_set_track_changed_event(void (*handler)(struct track_info *ti));
+void audio_invalidate_tracks(void);
#endif