diff options
| author | Purdea Andrei <andrei@purdea.ro> | 2012-06-18 12:37:22 +0300 |
|---|---|---|
| committer | Thomas Martitz <kugel@rockbox.org> | 2012-07-19 00:00:41 +0200 |
| commit | 323282f22dc1b510ae4a7c5e1a6de192f7df73d0 (patch) | |
| tree | 72515b78ceb323f212590821aa6b9a477f1e2fc6 | |
| parent | b7937a729f948c41f6582d74dd275aed2aa4fa25 (diff) | |
| download | rockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.zip rockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.tar.gz rockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.tar.bz2 rockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.tar.xz | |
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 <kugel@rockbox.org>
Tested-by: Thomas Martitz <kugel@rockbox.org>
| -rw-r--r-- | apps/playlist_viewer.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/apps/playlist_viewer.c b/apps/playlist_viewer.c index 68732ad..5479ba4 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); } |