summaryrefslogtreecommitdiffstats
path: root/apps/playlist_viewer.c
diff options
context:
space:
mode:
authorPurdea Andrei <andrei@purdea.ro>2012-06-18 12:37:22 +0300
committerThomas Martitz <kugel@rockbox.org>2012-07-19 00:00:41 +0200
commit323282f22dc1b510ae4a7c5e1a6de192f7df73d0 (patch)
tree72515b78ceb323f212590821aa6b9a477f1e2fc6 /apps/playlist_viewer.c
parentb7937a729f948c41f6582d74dd275aed2aa4fa25 (diff)
downloadrockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.tar.gz
rockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.tar.bz2
rockbox-323282f22dc1b510ae4a7c5e1a6de192f7df73d0.zip
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>
Diffstat (limited to 'apps/playlist_viewer.c')
-rw-r--r--apps/playlist_viewer.c46
1 files 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);
}