diff options
author | Rakesh Iyer <rni@google.com> | 2016-10-28 16:34:57 -0700 |
---|---|---|
committer | Rakesh Iyer <rni@google.com> | 2016-10-31 11:20:48 -0700 |
commit | d47e834a2872587d83e727d8001815476713e297 (patch) | |
tree | 09874d8451a8aa5634fa4dae46b2a8f32753ce68 | |
parent | 7e37ae05a9c7c9ecf8569a5bfe752a54f660a6ba (diff) | |
download | LocalMediaPlayer-d47e834a2872587d83e727d8001815476713e297.tar.gz |
Implement shuffle in local media player.
This change adds in a shuffle custom action for the local
media player. The shuffle algorithm itself is pretty naive
it just removes the current playing item from the list,
shuffles the rest and puts the current item back on front
of the list.
Bug: 398865
Test: Manual.
Change-Id: Idcdf2c00e508634de9bfff817d5a562a14cdc675
-rw-r--r-- | res/drawable/shuffle.xml | 15 | ||||
-rw-r--r-- | res/values/strings.xml | 2 | ||||
-rw-r--r-- | src/com/android/car/media/localmediaplayer/Player.java | 45 |
3 files changed, 59 insertions, 3 deletions
diff --git a/res/drawable/shuffle.xml b/res/drawable/shuffle.xml new file mode 100644 index 0000000..7f9fbff --- /dev/null +++ b/res/drawable/shuffle.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="48dp" + android:height="48dp" + android:viewportWidth="48" + android:viewportHeight="48"> + + <path + android:pathData="M0 0h48v48H0z" /> + <path + android:fillColor="#000000" + android:pathData="M21.17 18.34L10.83 8 8 10.83l10.34 10.34 2.83-2.83zM29 8l4.09 4.09L8 37.17 10.83 +40l25.09-25.09L40 19V8H29zm.66 18.83l-2.83 2.83 6.26 6.26L29 40h11V29l-4.09 +4.09-6.25-6.26z" /> +</vector> diff --git a/res/values/strings.xml b/res/values/strings.xml index 0f115f0..0abd1a8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -21,6 +21,6 @@ <string name="genres_title">Genres</string> <string name="albums_title">Albums</string> <string name="playback_error">Something went wrong.</string> - <string name="todo_permissions">TODO: Request sdcard permission here.</string> <string name="playlist">Now Playing</string> + <string name="shuffle">Shuffle</string> </resources> diff --git a/src/com/android/car/media/localmediaplayer/Player.java b/src/com/android/car/media/localmediaplayer/Player.java index 591524f..50ab5df 100644 --- a/src/com/android/car/media/localmediaplayer/Player.java +++ b/src/com/android/car/media/localmediaplayer/Player.java @@ -25,10 +25,12 @@ import android.media.MediaPlayer.OnCompletionListener; import android.media.session.MediaSession; import android.media.session.MediaSession.QueueItem; import android.media.session.PlaybackState; +import android.media.session.PlaybackState.CustomAction; import android.os.Bundle; import android.util.Log; import java.io.IOException; +import java.util.Collections; import java.util.List; /** @@ -54,11 +56,14 @@ public class Player extends MediaSession.Callback { | PlaybackState.ACTION_PLAY_FROM_MEDIA_ID | PlaybackState.ACTION_SKIP_TO_NEXT | PlaybackState.ACTION_SKIP_TO_PREVIOUS; + private static final String SHUFFLE = "android.car.media.localmediaplayer.shuffle"; + private final Context mContext; private final MediaSession mSession; private final AudioManager mAudioManager; private final PlaybackState mErrorState; private final DataModel mDataModel; + private final CustomAction mShuffle; private List<QueueItem> mQueue; private int mCurrentQueueIdx = 0; @@ -66,13 +71,15 @@ public class Player extends MediaSession.Callback { // TODO: Use multiple media players for gapless playback. private final MediaPlayer mMediaPlayer; - public Player(Context context, MediaSession session, DataModel dataModel) { mContext = context; mDataModel = dataModel; mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); mSession = session; + mShuffle = new CustomAction.Builder(SHUFFLE, context.getString(R.string.shuffle), + R.drawable.shuffle).build(); + mMediaPlayer = new MediaPlayer(); mMediaPlayer.reset(); mMediaPlayer.setOnCompletionListener(mOnCompletionListener); @@ -171,7 +178,8 @@ public class Player extends MediaSession.Callback { .setState(PlaybackState.STATE_PLAYING, mMediaPlayer.getCurrentPosition(), PLAYBACK_SPEED) .setActions(PLAYING_ACTIONS) - .setActiveQueueItemId(mCurrentQueueIdx) + .addCustomAction(mShuffle) + .setActiveQueueItemId(mQueue.get(mCurrentQueueIdx).getQueueId()) .build(); mSession.setPlaybackState(state); } @@ -190,6 +198,7 @@ public class Player extends MediaSession.Callback { PlaybackState state = new PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, currentPosition, PLAYBACK_SPEED_STOPPED) .setActions(PAUSED_ACTIONS) + .addCustomAction(mShuffle) .build(); mSession.setPlaybackState(state); } @@ -291,6 +300,25 @@ public class Player extends MediaSession.Callback { } } + /** + * This is a naive implementation of shuffle, previously played songs may repeat after the + * shuffle operation. Only call this from the main thread. + */ + private void shuffle() { + if (Log.isLoggable(TAG, Log.DEBUG)) { + Log.d(TAG, "Shuffling"); + } + + if (mQueue != null) { + QueueItem current = mQueue.remove(mCurrentQueueIdx); + Collections.shuffle(mQueue); + mQueue.add(0, current); + mCurrentQueueIdx = 0; + mSession.setQueue(mQueue); + updatePlaybackStatePlaying(); + } + } + @Override public void onPlayFromMediaId(String mediaId, Bundle extras) { super.onPlayFromMediaId(mediaId, extras); @@ -341,6 +369,17 @@ public class Player extends MediaSession.Callback { } } + @Override + public void onCustomAction(String action, Bundle extras) { + switch (action) { + case SHUFFLE: + shuffle(); + break; + default: + Log.e(TAG, "Unhandled custom action: " + action); + } + } + private OnAudioFocusChangeListener mAudioFocusListener = new OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focus) { @@ -353,6 +392,8 @@ public class Player extends MediaSession.Callback { case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK: pausePlayback(); break; + default: + Log.e(TAG, "Unhandled audio focus type: " + focus); } } }; |