diff --git a/src/org/kreed/vanilla/Song.java b/src/org/kreed/vanilla/Song.java index 03e7a07c..061861a5 100644 --- a/src/org/kreed/vanilla/Song.java +++ b/src/org/kreed/vanilla/Song.java @@ -50,6 +50,11 @@ public class Song implements Parcelable { */ private static final Cache mCoverCache = new Cache(10); + /** + * A cache of randomly selected songs. + */ + private static final Song[] mRandomSongs = new Song[5]; + private static final String[] FILLED_PROJECTION = { MediaStore.Audio.Media._ID, MediaStore.Audio.Media.DATA, @@ -92,12 +97,44 @@ public class Song implements Parcelable { public int flags; /** - * Initialize the song with a randomly selected id. Call populate to fill - * fields in the song. + * Returns a song randomly selected from all the songs in the Android + * MediaStore. */ - public Song() + public static Song randomSong() { - randomize(); + Song[] songs = mRandomSongs; + // Checked for previously retrieved random songs. + for (int i = songs.length; --i != -1; ) { + if (songs[i] != null) { + Song song = songs[i]; + songs[i] = null; + return song; + } + } + + // We need to fetch more + ContentResolver resolver = ContextApplication.getContext().getContentResolver(); + Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"; + Cursor cursor = resolver.query(media, FILLED_PROJECTION, selection, null, null); + + if (cursor != null) { + int count = cursor.getCount(); + if (count > 0) { + for (int i = songs.length; --i != -1; ) { + if (cursor.moveToPosition(ContextApplication.getRandom().nextInt(count))) { + songs[i] = new Song(-1); + songs[i].populate(cursor); + songs[i].flags |= FLAG_RANDOM; + } + } + } + cursor.close(); + } + + Song song = songs[0]; + songs[0] = null; + return song; } /** @@ -163,28 +200,6 @@ public class Song implements Parcelable { return id != -1; } - /** - * Fill the fields with data from a random Song in the MediaStore - */ - public void randomize() - { - id = -1; - - ContentResolver resolver = ContextApplication.getContext().getContentResolver(); - Uri media = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - String selection = MediaStore.Audio.Media.IS_MUSIC + "!=0"; - Cursor cursor = resolver.query(media, FILLED_PROJECTION, selection, null, null); - - if (cursor != null) { - int count = cursor.getCount(); - if (count > 0 && cursor.moveToPosition(ContextApplication.getRandom().nextInt(count))) { - populate(cursor); - flags |= FLAG_RANDOM; - } - cursor.close(); - } - } - /** * Get the id of the given song. * diff --git a/src/org/kreed/vanilla/SongTimeline.java b/src/org/kreed/vanilla/SongTimeline.java index a9eb2fd9..9d8bcbb7 100644 --- a/src/org/kreed/vanilla/SongTimeline.java +++ b/src/org/kreed/vanilla/SongTimeline.java @@ -285,13 +285,13 @@ public final class SongTimeline { return null; if (pos == size) { - song = new Song(); + song = Song.randomSong(); timeline.add(song); } else { song = timeline.get(pos); } - if (mRepeatStart != -1 && (song.flags & Song.FLAG_RANDOM) != 0) { + if (song != null && mRepeatStart != -1 && (song.flags & Song.FLAG_RANDOM) != 0) { if (delta == 1 && mRepeatStart < mCurrentPos + 1) { // We have reached a non-user-selected song; this song will // repeated in shiftCurrentSong so take alternative @@ -320,9 +320,9 @@ public final class SongTimeline { } } - if (!song.query(false)) { - song.randomize(); - if (!song.query(false)) + if (song == null || !song.query(false)) { + song = Song.randomSong(); + if (song == null || !song.query(false)) return null; }