Next/previous album action

This commit is contained in:
Christopher Eby 2011-11-26 20:32:24 -06:00
parent 731b7afed3
commit 61b1d9c5fa
7 changed files with 117 additions and 80 deletions

View File

@ -194,6 +194,8 @@ THE SOFTWARE.
<string name="play_pause">Play/Pause</string>
<string name="next_song">Next song</string>
<string name="previous_song">Previous song</string>
<string name="next_album">Next album</string>
<string name="previous_album">Previous album</string>
<string name="cycle_repeat_mode">Cycle repeat mode</string>
<string name="cycle_shuffle_mode">Cycle shuffle mode</string>
<string name="enqueue_current_album">Enqueue current album</string>

View File

@ -55,6 +55,8 @@ THE SOFTWARE.
<item>PlayPause</item>
<item>NextSong</item>
<item>PreviousSong</item>
<item>NextAlbum</item>
<item>PreviousAlbum</item>
<item>Repeat</item>
<item>Shuffle</item>
<item>EnqueueAlbum</item>
@ -70,6 +72,8 @@ THE SOFTWARE.
<item>@string/play_pause</item>
<item>@string/next_song</item>
<item>@string/previous_song</item>
<item>@string/next_album</item>
<item>@string/previous_album</item>
<item>@string/cycle_repeat_mode</item>
<item>@string/cycle_shuffle_mode</item>
<item>@string/enqueue_current_album</item>

View File

@ -65,13 +65,11 @@ public final class CoverView extends View implements Handler.Callback {
*/
public interface Callback {
/**
* Called after the view has scrolled to the next (right) cover.
* Called after the view has scrolled to the next or previous cover.
*
* @param delta -1 for the previous cover, 1 for the next.
*/
public void nextSong();
/**
* Called after the view has scrolled to the previous (left) cover.
*/
public void previousSong();
public void shiftCurrentSong(int delta);
/**
* Called when the user has swiped up on the view.
*/
@ -422,6 +420,7 @@ public final class CoverView extends View implements Handler.Callback {
*/
private static final int MSG_SCROLL = 3;
@Override
public boolean handleMessage(Message message)
{
switch (message.what) {
@ -446,12 +445,8 @@ public final class CoverView extends View implements Handler.Callback {
invalidateCovers();
mUiHandler.sendEmptyMessage(MSG_SCROLL);
} else if (mTentativeCover != -1) {
int delta = mTentativeCover - 1;
mCallback.shiftCurrentSong(mTentativeCover - 1);
mTentativeCover = -1;
if (delta == 1)
mCallback.nextSong();
else
mCallback.previousSong();
resetScroll();
}
break;

View File

@ -314,11 +314,11 @@ public class FullPlaybackActivity extends PlaybackActivity
{
switch (keyCode) {
case KeyEvent.KEYCODE_DPAD_RIGHT:
nextSong();
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
findViewById(R.id.next).requestFocus();
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
previousSong();
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
findViewById(R.id.previous).requestFocus();
return true;
}

View File

@ -58,6 +58,8 @@ public class PlaybackActivity extends Activity
PlayPause,
NextSong,
PreviousSong,
NextAlbum,
PreviousAlbum,
Repeat,
Shuffle,
EnqueueAlbum,
@ -199,15 +201,9 @@ public class PlaybackActivity extends Activity
}
@Override
public void nextSong()
public void shiftCurrentSong(int delta)
{
setSong(PlaybackService.get(this).nextSong());
}
@Override
public void previousSong()
{
setSong(PlaybackService.get(this).previousSong());
setSong(PlaybackService.get(this).shiftCurrentSong(delta));
}
public void playPause()
@ -224,13 +220,13 @@ public class PlaybackActivity extends Activity
{
switch (view.getId()) {
case R.id.next:
nextSong();
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
break;
case R.id.play_pause:
playPause();
break;
case R.id.previous:
previousSong();
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
break;
case R.id.end_action:
cycleFinishAction();
@ -427,10 +423,16 @@ public class PlaybackActivity extends Activity
playPause();
break;
case NextSong:
nextSong();
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
break;
case PreviousSong:
previousSong();
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
break;
case NextAlbum:
shiftCurrentSong(SongTimeline.SHIFT_NEXT_ALBUM);
break;
case PreviousAlbum:
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_ALBUM);
break;
case Repeat:
cycleFinishAction();

View File

@ -748,8 +748,11 @@ public final class PlaybackService extends Service
}
/**
* Move <code>delta</code> places away from the current song.
* Move to the next or previous song or album in the timeline.
*
* @param delta One of SongTimeline.SHIFT_*. 0 can also be passed to
* initialize the current song with media player, notification,
* broadcasts, etc.
* @return The new current song
*/
private Song setCurrentSong(int delta)
@ -760,7 +763,11 @@ public final class PlaybackService extends Service
if (mMediaPlayer.isPlaying())
mMediaPlayer.stop();
Song song = mTimeline.shiftCurrentSong(delta);
Song song;
if (delta == 0)
song = mTimeline.getSong(0);
else
song = mTimeline.shiftCurrentSong(delta);
mCurrentSong = song;
if (song == null || song.id == -1 || song.path == null) {
if (MediaUtils.isSongAvailable(getContentResolver())) {
@ -1115,21 +1122,14 @@ public final class PlaybackService extends Service
}
/**
* Move to the next song in the queue.
* Move to next or previous song or album in the queue.
*
* @param delta One of SongTimeline.SHIFT_*.
* @return The new current song.
*/
public Song nextSong()
public Song shiftCurrentSong(int delta)
{
Song song = setCurrentSong(+1);
userActionTriggered();
return song;
}
/**
* Move to the previous song in the queue.
*/
public Song previousSong()
{
Song song = setCurrentSong(-1);
Song song = setCurrentSong(delta);
userActionTriggered();
return song;
}

View File

@ -176,6 +176,30 @@ public final class SongTimeline {
public static final int[] SHUFFLE_ICONS =
{ R.drawable.shuffle_inactive, R.drawable.shuffle_active, R.drawable.shuffle_album_active };
/**
* Move current position to the previous album.
*
* @see SongTimeline#shiftCurrentSong(int)
*/
public static final int SHIFT_PREVIOUS_ALBUM = -2;
/**
* Move current position to the previous song.
*
* @see SongTimeline#shiftCurrentSong(int)
*/
public static final int SHIFT_PREVIOUS_SONG = -1;
/**
* Move current position to the next song.
*
* @see SongTimeline#shiftCurrentSong(int)
*/
public static final int SHIFT_NEXT_SONG = 1;
/**
* Move current position to the next album.
*
* @see SongTimeline#shiftCurrentSong(int)
*/
public static final int SHIFT_NEXT_ALBUM = 2;
private final Context mContext;
/**
@ -473,11 +497,12 @@ public final class SongTimeline {
} else if (pos > size) {
return null;
} else if (pos == size) {
switch (mFinishAction) {
case FINISH_STOP:
case FINISH_REPEAT:
case FINISH_REPEAT_CURRENT:
case FINISH_STOP_CURRENT:
if (mFinishAction == FINISH_RANDOM) {
song = MediaUtils.randomSong(mContext.getContentResolver());
if (song == null)
return null;
timeline.add(song);
} else {
if (size == 0)
// empty queue
return null;
@ -485,15 +510,6 @@ public final class SongTimeline {
song = shuffleAll();
else
song = timeline.get(0);
break;
case FINISH_RANDOM:
song = MediaUtils.randomSong(mContext.getContentResolver());
if (song == null)
return null;
timeline.add(song);
break;
default:
throw new IllegalStateException("Invalid finish action: " + mFinishAction);
}
} else {
song = timeline.get(pos);
@ -508,40 +524,58 @@ public final class SongTimeline {
}
/**
* Shift the current song by <code>delta</code> places.
* Internal implementation for shiftCurrentSong. Does all the work except
* broadcasting the timeline change: updates mCurrentPos and handles
* shuffling, repeating, and random mode.
*
* @param delta The delta. Must be -1, 0, 1.
* @param delta -1 to move to the previous song or 1 for the next.
*/
private void shiftCurrentSongInternal(int delta)
{
int pos = mCurrentPos + delta;
if (mFinishAction != FINISH_RANDOM && pos == mSongs.size()) {
if (mShuffleMode != SHUFFLE_NONE && !mSongs.isEmpty()) {
if (mShuffledSongs == null)
shuffleAll();
mSongs = mShuffledSongs;
}
pos = 0;
} else if (pos < 0) {
if (mFinishAction == FINISH_RANDOM)
pos = 0;
else
pos = Math.max(0, mSongs.size() - 1);
}
mCurrentPos = pos;
mShuffledSongs = null;
}
/**
* Move to the next or previous song or album.
*
* @param delta One of SongTimeline.SHIFT_*.
* @return The Song at the new position
*/
public Song shiftCurrentSong(int delta)
{
Assert.assertTrue(delta >= -1 && delta <= 1);
synchronized (this) {
int pos = mCurrentPos + delta;
if (mFinishAction != FINISH_RANDOM && pos == mSongs.size()) {
if (mShuffleMode != SHUFFLE_NONE && !mSongs.isEmpty()) {
if (mShuffledSongs == null)
shuffleAll();
mSongs = mShuffledSongs;
}
pos = 0;
} else if (pos < 0) {
if (mFinishAction == FINISH_RANDOM)
pos = 0;
else
pos = Math.max(0, mSongs.size() - 1);
if (delta == SHIFT_PREVIOUS_SONG || delta == SHIFT_NEXT_SONG) {
shiftCurrentSongInternal(delta);
} else {
Song song = getSong(0);
long currentAlbum = song.albumId;
long currentSong = song.id;
delta = delta > 0 ? 1 : -1;
do {
shiftCurrentSongInternal(delta);
song = getSong(0);
} while (currentAlbum == song.albumId && currentSong != song.id);
}
mCurrentPos = pos;
mShuffledSongs = null;
}
if (delta != 0)
changed();
changed();
return getSong(0);
}