Next/previous album action
This commit is contained in:
parent
731b7afed3
commit
61b1d9c5fa
@ -194,6 +194,8 @@ THE SOFTWARE.
|
|||||||
<string name="play_pause">Play/Pause</string>
|
<string name="play_pause">Play/Pause</string>
|
||||||
<string name="next_song">Next song</string>
|
<string name="next_song">Next song</string>
|
||||||
<string name="previous_song">Previous 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_repeat_mode">Cycle repeat mode</string>
|
||||||
<string name="cycle_shuffle_mode">Cycle shuffle mode</string>
|
<string name="cycle_shuffle_mode">Cycle shuffle mode</string>
|
||||||
<string name="enqueue_current_album">Enqueue current album</string>
|
<string name="enqueue_current_album">Enqueue current album</string>
|
||||||
|
@ -55,6 +55,8 @@ THE SOFTWARE.
|
|||||||
<item>PlayPause</item>
|
<item>PlayPause</item>
|
||||||
<item>NextSong</item>
|
<item>NextSong</item>
|
||||||
<item>PreviousSong</item>
|
<item>PreviousSong</item>
|
||||||
|
<item>NextAlbum</item>
|
||||||
|
<item>PreviousAlbum</item>
|
||||||
<item>Repeat</item>
|
<item>Repeat</item>
|
||||||
<item>Shuffle</item>
|
<item>Shuffle</item>
|
||||||
<item>EnqueueAlbum</item>
|
<item>EnqueueAlbum</item>
|
||||||
@ -70,6 +72,8 @@ THE SOFTWARE.
|
|||||||
<item>@string/play_pause</item>
|
<item>@string/play_pause</item>
|
||||||
<item>@string/next_song</item>
|
<item>@string/next_song</item>
|
||||||
<item>@string/previous_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_repeat_mode</item>
|
||||||
<item>@string/cycle_shuffle_mode</item>
|
<item>@string/cycle_shuffle_mode</item>
|
||||||
<item>@string/enqueue_current_album</item>
|
<item>@string/enqueue_current_album</item>
|
||||||
|
@ -65,13 +65,11 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
*/
|
*/
|
||||||
public interface 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();
|
public void shiftCurrentSong(int delta);
|
||||||
/**
|
|
||||||
* Called after the view has scrolled to the previous (left) cover.
|
|
||||||
*/
|
|
||||||
public void previousSong();
|
|
||||||
/**
|
/**
|
||||||
* Called when the user has swiped up on the view.
|
* 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;
|
private static final int MSG_SCROLL = 3;
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean handleMessage(Message message)
|
public boolean handleMessage(Message message)
|
||||||
{
|
{
|
||||||
switch (message.what) {
|
switch (message.what) {
|
||||||
@ -446,12 +445,8 @@ public final class CoverView extends View implements Handler.Callback {
|
|||||||
invalidateCovers();
|
invalidateCovers();
|
||||||
mUiHandler.sendEmptyMessage(MSG_SCROLL);
|
mUiHandler.sendEmptyMessage(MSG_SCROLL);
|
||||||
} else if (mTentativeCover != -1) {
|
} else if (mTentativeCover != -1) {
|
||||||
int delta = mTentativeCover - 1;
|
mCallback.shiftCurrentSong(mTentativeCover - 1);
|
||||||
mTentativeCover = -1;
|
mTentativeCover = -1;
|
||||||
if (delta == 1)
|
|
||||||
mCallback.nextSong();
|
|
||||||
else
|
|
||||||
mCallback.previousSong();
|
|
||||||
resetScroll();
|
resetScroll();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -314,11 +314,11 @@ public class FullPlaybackActivity extends PlaybackActivity
|
|||||||
{
|
{
|
||||||
switch (keyCode) {
|
switch (keyCode) {
|
||||||
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
case KeyEvent.KEYCODE_DPAD_RIGHT:
|
||||||
nextSong();
|
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
|
||||||
findViewById(R.id.next).requestFocus();
|
findViewById(R.id.next).requestFocus();
|
||||||
return true;
|
return true;
|
||||||
case KeyEvent.KEYCODE_DPAD_LEFT:
|
case KeyEvent.KEYCODE_DPAD_LEFT:
|
||||||
previousSong();
|
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
|
||||||
findViewById(R.id.previous).requestFocus();
|
findViewById(R.id.previous).requestFocus();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ public class PlaybackActivity extends Activity
|
|||||||
PlayPause,
|
PlayPause,
|
||||||
NextSong,
|
NextSong,
|
||||||
PreviousSong,
|
PreviousSong,
|
||||||
|
NextAlbum,
|
||||||
|
PreviousAlbum,
|
||||||
Repeat,
|
Repeat,
|
||||||
Shuffle,
|
Shuffle,
|
||||||
EnqueueAlbum,
|
EnqueueAlbum,
|
||||||
@ -199,15 +201,9 @@ public class PlaybackActivity extends Activity
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nextSong()
|
public void shiftCurrentSong(int delta)
|
||||||
{
|
{
|
||||||
setSong(PlaybackService.get(this).nextSong());
|
setSong(PlaybackService.get(this).shiftCurrentSong(delta));
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void previousSong()
|
|
||||||
{
|
|
||||||
setSong(PlaybackService.get(this).previousSong());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playPause()
|
public void playPause()
|
||||||
@ -224,13 +220,13 @@ public class PlaybackActivity extends Activity
|
|||||||
{
|
{
|
||||||
switch (view.getId()) {
|
switch (view.getId()) {
|
||||||
case R.id.next:
|
case R.id.next:
|
||||||
nextSong();
|
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
|
||||||
break;
|
break;
|
||||||
case R.id.play_pause:
|
case R.id.play_pause:
|
||||||
playPause();
|
playPause();
|
||||||
break;
|
break;
|
||||||
case R.id.previous:
|
case R.id.previous:
|
||||||
previousSong();
|
shiftCurrentSong(SongTimeline.SHIFT_PREVIOUS_SONG);
|
||||||
break;
|
break;
|
||||||
case R.id.end_action:
|
case R.id.end_action:
|
||||||
cycleFinishAction();
|
cycleFinishAction();
|
||||||
@ -427,10 +423,16 @@ public class PlaybackActivity extends Activity
|
|||||||
playPause();
|
playPause();
|
||||||
break;
|
break;
|
||||||
case NextSong:
|
case NextSong:
|
||||||
nextSong();
|
shiftCurrentSong(SongTimeline.SHIFT_NEXT_SONG);
|
||||||
break;
|
break;
|
||||||
case PreviousSong:
|
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;
|
break;
|
||||||
case Repeat:
|
case Repeat:
|
||||||
cycleFinishAction();
|
cycleFinishAction();
|
||||||
|
@ -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
|
* @return The new current song
|
||||||
*/
|
*/
|
||||||
private Song setCurrentSong(int delta)
|
private Song setCurrentSong(int delta)
|
||||||
@ -760,7 +763,11 @@ public final class PlaybackService extends Service
|
|||||||
if (mMediaPlayer.isPlaying())
|
if (mMediaPlayer.isPlaying())
|
||||||
mMediaPlayer.stop();
|
mMediaPlayer.stop();
|
||||||
|
|
||||||
Song song = mTimeline.shiftCurrentSong(delta);
|
Song song;
|
||||||
|
if (delta == 0)
|
||||||
|
song = mTimeline.getSong(0);
|
||||||
|
else
|
||||||
|
song = mTimeline.shiftCurrentSong(delta);
|
||||||
mCurrentSong = song;
|
mCurrentSong = song;
|
||||||
if (song == null || song.id == -1 || song.path == null) {
|
if (song == null || song.id == -1 || song.path == null) {
|
||||||
if (MediaUtils.isSongAvailable(getContentResolver())) {
|
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);
|
Song song = setCurrentSong(delta);
|
||||||
userActionTriggered();
|
|
||||||
return song;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Move to the previous song in the queue.
|
|
||||||
*/
|
|
||||||
public Song previousSong()
|
|
||||||
{
|
|
||||||
Song song = setCurrentSong(-1);
|
|
||||||
userActionTriggered();
|
userActionTriggered();
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
@ -176,6 +176,30 @@ public final class SongTimeline {
|
|||||||
public static final int[] SHUFFLE_ICONS =
|
public static final int[] SHUFFLE_ICONS =
|
||||||
{ R.drawable.shuffle_inactive, R.drawable.shuffle_active, R.drawable.shuffle_album_active };
|
{ 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;
|
private final Context mContext;
|
||||||
/**
|
/**
|
||||||
@ -473,11 +497,12 @@ public final class SongTimeline {
|
|||||||
} else if (pos > size) {
|
} else if (pos > size) {
|
||||||
return null;
|
return null;
|
||||||
} else if (pos == size) {
|
} else if (pos == size) {
|
||||||
switch (mFinishAction) {
|
if (mFinishAction == FINISH_RANDOM) {
|
||||||
case FINISH_STOP:
|
song = MediaUtils.randomSong(mContext.getContentResolver());
|
||||||
case FINISH_REPEAT:
|
if (song == null)
|
||||||
case FINISH_REPEAT_CURRENT:
|
return null;
|
||||||
case FINISH_STOP_CURRENT:
|
timeline.add(song);
|
||||||
|
} else {
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
// empty queue
|
// empty queue
|
||||||
return null;
|
return null;
|
||||||
@ -485,15 +510,6 @@ public final class SongTimeline {
|
|||||||
song = shuffleAll();
|
song = shuffleAll();
|
||||||
else
|
else
|
||||||
song = timeline.get(0);
|
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 {
|
} else {
|
||||||
song = timeline.get(pos);
|
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
|
* @return The Song at the new position
|
||||||
*/
|
*/
|
||||||
public Song shiftCurrentSong(int delta)
|
public Song shiftCurrentSong(int delta)
|
||||||
{
|
{
|
||||||
Assert.assertTrue(delta >= -1 && delta <= 1);
|
|
||||||
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
int pos = mCurrentPos + delta;
|
if (delta == SHIFT_PREVIOUS_SONG || delta == SHIFT_NEXT_SONG) {
|
||||||
|
shiftCurrentSongInternal(delta);
|
||||||
if (mFinishAction != FINISH_RANDOM && pos == mSongs.size()) {
|
} else {
|
||||||
if (mShuffleMode != SHUFFLE_NONE && !mSongs.isEmpty()) {
|
Song song = getSong(0);
|
||||||
if (mShuffledSongs == null)
|
long currentAlbum = song.albumId;
|
||||||
shuffleAll();
|
long currentSong = song.id;
|
||||||
mSongs = mShuffledSongs;
|
delta = delta > 0 ? 1 : -1;
|
||||||
}
|
do {
|
||||||
|
shiftCurrentSongInternal(delta);
|
||||||
pos = 0;
|
song = getSong(0);
|
||||||
} else if (pos < 0) {
|
} while (currentAlbum == song.albumId && currentSong != song.id);
|
||||||
if (mFinishAction == FINISH_RANDOM)
|
|
||||||
pos = 0;
|
|
||||||
else
|
|
||||||
pos = Math.max(0, mSongs.size() - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentPos = pos;
|
|
||||||
mShuffledSongs = null;
|
|
||||||
}
|
}
|
||||||
|
changed();
|
||||||
if (delta != 0)
|
|
||||||
changed();
|
|
||||||
|
|
||||||
return getSong(0);
|
return getSong(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user