From 323282f22dc1b510ae4a7c5e1a6de192f7df73d0 Mon Sep 17 00:00:00 2001 From: Purdea Andrei Date: Mon, 18 Jun 2012 12:37:22 +0300 Subject: Fixing data abort (pc in strchr). when scrolling a big playlist very fast. Change-Id: Ibe00a11592a18d320682cce755e48ce701ff5b4a Reviewed-on: http://gerrit.rockbox.org/281 Reviewed-by: Thomas Martitz Tested-by: Thomas Martitz --- apps/playlist_viewer.c | 46 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 68732adcbc..5479ba43ba 100644 --- a/apps/playlist_viewer.c +++ b/apps/playlist_viewer.c @@ -175,12 +175,21 @@ static void playlist_buffer_load_entries(struct playlist_buffer *pb, int index, pb->num_loaded = i; } +/* playlist_buffer_load_entries_screen() + * This function is called when the currently selected item gets too close + * to the start or the end of the loaded part of the playlis, or when + * the list callback requests a playlist item that has not been loaded yet + * + * reference_track is either the currently selected track, or the track that + * has been requested by the callback, and has not been loaded yet. + */ static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb, - enum direction direction) + enum direction direction, + int reference_track) { if (direction == FORWARD) { - int min_start = viewer.selected_track-2*screens[0].getnblines(); + int min_start = reference_track-2*screens[0].getnblines(); while (min_start < 0) min_start += viewer.num_tracks; min_start %= viewer.num_tracks; @@ -188,7 +197,7 @@ static void playlist_buffer_load_entries_screen(struct playlist_buffer * pb, } else { - int max_start = viewer.selected_track+2*screens[0].getnblines(); + int max_start = reference_track+2*screens[0].getnblines(); max_start %= viewer.num_tracks; playlist_buffer_load_entries(pb, max_start, BACKWARD); } @@ -266,6 +275,31 @@ static struct playlist_entry * playlist_buffer_get_track(struct playlist_buffer int index) { int buffer_index = playlist_buffer_get_index(pb, index); + /* Make sure that we are not returning an invalid pointer. + In some cases, when scrolling really fast, it could happen that a reqested track + has not been pre-loaded */ + if (buffer_index < 0) { + playlist_buffer_load_entries_screen(&viewer.buffer, + pb->direction == FORWARD ? BACKWARD : FORWARD, + index); + + } else if (buffer_index >= pb->num_loaded) { + playlist_buffer_load_entries_screen(&viewer.buffer, + pb->direction, + index); + } + buffer_index = playlist_buffer_get_index(pb, index); + if (buffer_index < 0 || buffer_index >= pb->num_loaded) { + /* This really shouldn't happen. If this happens, then + the name_buffer is probably too small to store enough + titles to fill the screen, and preload data in the short + direction. + + If this happens then scrolling performance will probably + be quite low, but it's better then having Data Abort errors */ + playlist_buffer_load_entries(pb, index, FORWARD); + buffer_index = playlist_buffer_get_index(pb, index); + } return &(pb->tracks[buffer_index]); } @@ -425,7 +459,8 @@ static bool update_playlist(bool force) global_status.resume_offset = -1; return false; } - playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD); + playlist_buffer_load_entries_screen(&viewer.buffer, FORWARD, + viewer.selected_track); if (viewer.buffer.num_loaded <= 0) { global_status.resume_index = -1; @@ -679,7 +714,8 @@ enum playlist_viewer_result playlist_viewer_ex(const char* filename) viewer.selected_track); if (reload) playlist_buffer_load_entries_screen(&viewer.buffer, - button == ACTION_STD_NEXT ? FORWARD : BACKWARD); + button == ACTION_STD_NEXT ? FORWARD : BACKWARD, + viewer.selected_track); if (reload || viewer.moving_track >= 0) gui_synclist_draw(&playlist_lists); } -- cgit v1.2.3