Add ShuffleOrder.getShuffledIndex and .getUnshuffledIndex for ease of use.
- Dominant language
- Java
- Stars
- 21.9k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
Continuing from Issue #4915 i was able to come up with my own implementation of my Own Shuffle Order which is bare but works.
```public class UduxShuffleorder implements ShuffleOrder {
public static final String TAG = LogHelper.makeLogTag(UduxShuffleorder.class);
private final Random random;
private int[] shuffled;
private int[] indexInShuffled;
private int[] right;
/**
* Creates an instance with a specified length.
* @param length The length of the shuffle order.
*
* @param currentPosition The current position of the current
*
*/
public UduxShuffleorder(int length, int currentPosition, Random random) {
this.random = random;
createShuffledList(length, currentPosition, random);
}
private void createShuffledList(int length, int currentPosition , Random random){
shuffled = new int[length];
for (int i = 0; i < length; i++) {
int swapIndex = random.nextInt(i + 1);
shuffled[i] = shuffled[swapIndex];
shuffled[swapIndex] = i;
}
this.indexInShuffled = new int[shuffled.length];
for (int i = 0; i < shuffled.length; i++) {
indexInShuffled[shuffled[i]] = i;
}
if (currentPosition < shuffled.length){
int indexOfCurrentPositionInShuffle = indexInShuffled[currentPosition];
if(indexOfCurrentPositionInShuffle == 0){
return;
}else {
int[] middle = {currentPosition};
int amountToRight = shuffled.length - (indexOfCurrentPositionInShuffle + 1);
right = new int[amountToRight];
for (int i = 0 ; i < amountToRight; i++){
right[i] = shuffled[indexOfCurrentPositionInShuffle + i + 1];
LogHelper.e(TAG, "The value of " + (indexOfCurrentPositionInShuffle + i + 1) + " = " + right[i]);
}
int[] left = new int[indexOfCurrentPositionInShuffle];
for (int i = indexOfCurrentPositionInShuffle -1; i > -1; i--){
left[i] = shuffled[i];
LogHelper.e(TAG, "The value of " + indexOfCurrentPositionInShuffle + i + " = " + left[i]);
}
int newLength = middle.length + left.length + right.length;
int[] c = new int[newLength];
System.arraycopy(middle, 0, c, 0, middle.length);
System.arraycopy(left, 0, c, middle.length, left.length);
System.arraycopy(right, 0, c , middle.length+ left.length, right.length);
shuffled = c;
this.indexInShuffled = new int[shuffled.length];
for (int i = 0; i < shuffled.length; i++) {
indexInShuffled[shuffled[i]] = i;
}
}
}
}
@Override
public int getLength() {
return shuffled.length;
}
@Override
public int getNextIndex(int index) {
int shuffledIndex = indexInShuffled[index];
if (++shuffledIndex < shuffled.length) return shuffled[shuffledIndex];
else return C.INDEX_UNSET;
}
@Override
public int getPreviousIndex(int index) {
int shuffledIndex = indexInShuffled[index];
return --shuffledIndex >= 0 ? shuffled[shuffledIndex] : C.INDEX_UNSET;
}
@Override
public int getLastIndex() {
return shuffled.length > 0 ? shuffled[shuffled.length - 1] : C.INDEX_UNSET;
}
@Override
public int getFirstIndex() {
return shuffled.length > 0 ? shuffled[0] : C.INDEX_UNSET;
}
@Override
public ShuffleOrder cloneAndInsert(int i, int i1) {
LogHelper.e(TAG, "I was cloned and inserted", "");
return null;
}
@Override
public ShuffleOrder cloneAndRemove(int i) {
LogHelper.e(TAG, "I was cloned and removed", "");
return null;
}
@Override
public ShuffleOrder cloneAndClear() {
LogHelper.e(TAG, "I was cloned and cleared", "");
return new UduxShuffleorder(0, 0, new Random());
}
}
```
So the idea of mine is that when shuffle is clicked, the current position becomes the first song and the remaining length of the song is shuffled.
i make the player use the shuffle Order like this
``` initExo();
//This method is used to initialize the media source
clearSource();
mediaSource = new ConcatenatingMediaSource();
for (Track track : songManager.getCurrentPlayList()) {
if (track != null && !track.getSource().isEmpty()) {
HlsMediaSource source = new
HlsMediaSource(Uri.parse(track.getSource()), cacheDataSourceFactory(), 5, null, null);
mediaSource.addMediaSource(source);
} else {
Log.e("Bad_Track", track.toString());
}
}
//Prepare the player here
preparePlayer();
// we want to move to the actual song we wanna play because exoplayer
// plays the first song immediately after preparing the source
mExoPlayer.seekTo((int) item.getQueueId(), C.TIME_UNSET);
mHandler.postDelayed(() -> {
if (songManager.isShuffleMode()) {
ShuffleOrder order = new UduxShuffleorder(songManager.currentPlayList.size(),
mExoPlayer.getCurrentWindowIndex(), new Random());
getShuffledOrder(order);
//Set the shuffle Mode to the Player and Hope to God it doesnt crash
mediaSource.setShuffleOrder(order, () -> mExoPlayer.setShuffleModeEnabled(true));
songManager.setShuffleMode(true);
//send the signal to the player that we have shuffled the List
mCallback.onTracksShuffled(mExoPlayer.getCurrentWindowIndex());
}
```
I used a handler to delay adding the shuffle order to the media source, because if i do it immediately, `exoplayer` thinks the shuffleOrder is longer than the mediaSource length and calls `CloneAndRemove` method of the shuffle order which isn't implemented and crashes the app. So with the handler, its sure the player would be ready before the shuffle order is set :) .
What brings me here is the unimplemented Methods
`ShuffleOrder cloneAndRemove(int removalIndex);`
`ShuffleOrder cloneAndInsert(int insertionIndex, int insertionCount);`
which i didnt implement because i didnt understand what the `defaultShuffleOrder` was doing.
Observation.
When i am in shuffle mode and i try to move a song to a new position, the above methods .are called, so because initially i returned `null` the app crashes at that point. to avoid the app crash, i took Exoplayer's default implementation of that method to mine. it does not crash but it does scatter the list :)
i would need help as to how to implement those method that when i move a song in shuffled mode to another position, it behaves normally without randomising the list anymore
Assuming i have a Shuffled list
```
1
3
2
4
```
moving song 1 to song 3 should not change the order of 2 and 4.
I hope i am clear enough. Thank you.
Contributor guide
Assessment
This issue has not been assessed yet.