mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-22 11:02:35 +01:00
-Added media session implementation for all players.
-Extracted version numbers in gradle dependencies. -Updated ExoPlayer to 2.7.1. -Updated RxJava to 2.1.10, RxAndroid to 2.0.2 and RxBinding to 2.1.1. -Removed deprecated implementation of media buttons.
This commit is contained in:
parent
5a05cb96be
commit
bc7188c8a8
@ -49,6 +49,11 @@ android {
|
||||
|
||||
ext {
|
||||
supportLibVersion = '27.1.0'
|
||||
exoPlayerLibVersion = '2.7.1'
|
||||
roomDbLibVersion = '1.0.0'
|
||||
leakCanaryVersion = '1.5.4'
|
||||
okHttpVersion = '1.5.0'
|
||||
icepickVersion = '3.2.0'
|
||||
}
|
||||
dependencies {
|
||||
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2') {
|
||||
@ -73,27 +78,28 @@ dependencies {
|
||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||
implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1'
|
||||
implementation 'com.nononsenseapps:filepicker:4.2.1'
|
||||
implementation 'com.google.android.exoplayer:exoplayer:2.7.1'
|
||||
implementation "com.google.android.exoplayer:exoplayer:$exoPlayerLibVersion"
|
||||
implementation "com.google.android.exoplayer:extension-mediasession:$exoPlayerLibVersion"
|
||||
|
||||
debugImplementation 'com.facebook.stetho:stetho:1.5.0'
|
||||
debugImplementation 'com.facebook.stetho:stetho-urlconnection:1.5.0'
|
||||
debugImplementation "com.facebook.stetho:stetho:$okHttpVersion"
|
||||
debugImplementation "com.facebook.stetho:stetho-urlconnection:$okHttpVersion"
|
||||
debugImplementation 'com.android.support:multidex:1.0.3'
|
||||
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.1.7'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.1.10'
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
|
||||
implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
|
||||
|
||||
implementation 'android.arch.persistence.room:runtime:1.0.0'
|
||||
implementation 'android.arch.persistence.room:rxjava2:1.0.0'
|
||||
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
|
||||
implementation "android.arch.persistence.room:runtime:$roomDbLibVersion"
|
||||
implementation "android.arch.persistence.room:rxjava2:$roomDbLibVersion"
|
||||
annotationProcessor "android.arch.persistence.room:compiler:$roomDbLibVersion"
|
||||
|
||||
implementation 'frankiesardo:icepick:3.2.0'
|
||||
annotationProcessor 'frankiesardo:icepick-processor:3.2.0'
|
||||
implementation "frankiesardo:icepick:$icepickVersion"
|
||||
annotationProcessor "frankiesardo:icepick-processor:$icepickVersion"
|
||||
|
||||
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
|
||||
betaImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
|
||||
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryVersion"
|
||||
betaImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
|
||||
releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryVersion"
|
||||
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
|
||||
debugImplementation 'com.facebook.stetho:stetho-okhttp3:1.5.0'
|
||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:$okHttpVersion"
|
||||
}
|
||||
|
@ -43,12 +43,6 @@
|
||||
android:launchMode="singleTask"
|
||||
android:label="@string/title_activity_background_player"/>
|
||||
|
||||
<receiver android:name="org.schabi.newpipe.player.BackgroundPlayer$MediaButtonReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_BUTTON" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<activity
|
||||
android:name=".player.PopupVideoPlayerActivity"
|
||||
android:launchMode="singleTask"
|
||||
|
@ -22,8 +22,6 @@ package org.schabi.newpipe.player;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@ -35,7 +33,6 @@ import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
@ -81,8 +78,6 @@ public final class BackgroundPlayer extends Service {
|
||||
private BasePlayerImpl basePlayerImpl;
|
||||
private LockManager lockManager;
|
||||
|
||||
private ComponentName mReceiverComponent;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Service-Activity Binder
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -119,9 +114,6 @@ public final class BackgroundPlayer extends Service {
|
||||
|
||||
mBinder = new PlayerServiceBinder(basePlayerImpl);
|
||||
shouldUpdateOnProgress = true;
|
||||
|
||||
mReceiverComponent = new ComponentName(this, MediaButtonReceiver.class);
|
||||
basePlayerImpl.getAudioReactor().registerMediaButtonEventReceiver(mReceiverComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -152,7 +144,6 @@ public final class BackgroundPlayer extends Service {
|
||||
lockManager.releaseWifiAndCpu();
|
||||
}
|
||||
if (basePlayerImpl != null) {
|
||||
basePlayerImpl.getAudioReactor().unregisterMediaButtonEventReceiver(mReceiverComponent);
|
||||
basePlayerImpl.stopActivityBinding();
|
||||
basePlayerImpl.destroy();
|
||||
}
|
||||
@ -573,49 +564,4 @@ public final class BackgroundPlayer extends Service {
|
||||
lockManager.releaseWifiAndCpu();
|
||||
}
|
||||
}
|
||||
|
||||
public static class MediaButtonReceiver extends BroadcastReceiver {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (!Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())) return;
|
||||
final KeyEvent event = intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
|
||||
if (event.getAction() != KeyEvent.ACTION_UP) return;
|
||||
final int keycode = event.getKeyCode();
|
||||
|
||||
final PendingIntent pendingIntent;
|
||||
switch (keycode) {
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
pendingIntent = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
|
||||
new Intent(ACTION_PLAY_NEXT), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
|
||||
pendingIntent = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
|
||||
new Intent(ACTION_PLAY_PREVIOUS), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY:
|
||||
pendingIntent = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
|
||||
new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||||
pendingIntent = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
|
||||
new Intent(ACTION_FAST_FORWARD), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_REWIND:
|
||||
pendingIntent = PendingIntent.getBroadcast(context, NOTIFICATION_ID,
|
||||
new Intent(ACTION_FAST_REWIND), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
break;
|
||||
default:
|
||||
pendingIntent = null;
|
||||
}
|
||||
|
||||
if (pendingIntent == null) return;
|
||||
try {
|
||||
pendingIntent.send();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error Sending intent MediaButtonReceiver", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +61,10 @@ import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.history.HistoryRecordManager;
|
||||
import org.schabi.newpipe.player.helper.AudioReactor;
|
||||
import org.schabi.newpipe.player.helper.LoadController;
|
||||
import org.schabi.newpipe.player.helper.MediaSessionManager;
|
||||
import org.schabi.newpipe.player.helper.PlayerDataSource;
|
||||
import org.schabi.newpipe.player.helper.PlayerHelper;
|
||||
import org.schabi.newpipe.player.playback.BasePlayerMediaSession;
|
||||
import org.schabi.newpipe.player.playback.CustomTrackSelector;
|
||||
import org.schabi.newpipe.player.playback.MediaSourceManager;
|
||||
import org.schabi.newpipe.player.playback.PlaybackListener;
|
||||
@ -148,6 +150,7 @@ public abstract class BasePlayer implements
|
||||
|
||||
protected SimpleExoPlayer simpleExoPlayer;
|
||||
protected AudioReactor audioReactor;
|
||||
protected MediaSessionManager mediaSessionManager;
|
||||
|
||||
private boolean isPrepared = false;
|
||||
private boolean isSynchronizing = false;
|
||||
@ -195,11 +198,13 @@ public abstract class BasePlayer implements
|
||||
final LoadControl loadControl = new LoadController(context);
|
||||
final RenderersFactory renderFactory = new DefaultRenderersFactory(context);
|
||||
simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(renderFactory, trackSelector, loadControl);
|
||||
audioReactor = new AudioReactor(context, simpleExoPlayer);
|
||||
|
||||
simpleExoPlayer.addListener(this);
|
||||
simpleExoPlayer.setPlayWhenReady(true);
|
||||
simpleExoPlayer.setSeekParameters(PlayerHelper.getSeekParameters(context));
|
||||
|
||||
audioReactor = new AudioReactor(context, simpleExoPlayer);
|
||||
mediaSessionManager = new MediaSessionManager(context, simpleExoPlayer,
|
||||
new BasePlayerMediaSession(this));
|
||||
}
|
||||
|
||||
public void initListeners() {}
|
||||
@ -262,8 +267,8 @@ public abstract class BasePlayer implements
|
||||
}
|
||||
if (isProgressLoopRunning()) stopProgressLoop();
|
||||
if (playQueue != null) playQueue.dispose();
|
||||
if (audioReactor != null) audioReactor.dispose();
|
||||
if (playbackManager != null) playbackManager.dispose();
|
||||
if (audioReactor != null) audioReactor.abandonAudioFocus();
|
||||
if (databaseUpdateReactor != null) databaseUpdateReactor.dispose();
|
||||
|
||||
if (playQueueAdapter != null) {
|
||||
@ -279,6 +284,7 @@ public abstract class BasePlayer implements
|
||||
|
||||
trackSelector = null;
|
||||
simpleExoPlayer = null;
|
||||
mediaSessionManager = null;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3,7 +3,6 @@ package org.schabi.newpipe.player.helper;
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioFocusRequest;
|
||||
@ -18,18 +17,14 @@ import com.google.android.exoplayer2.SimpleExoPlayer;
|
||||
import com.google.android.exoplayer2.audio.AudioRendererEventListener;
|
||||
import com.google.android.exoplayer2.decoder.DecoderCounters;
|
||||
|
||||
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, AudioRendererEventListener {
|
||||
public class AudioReactor implements AudioManager.OnAudioFocusChangeListener,
|
||||
AudioRendererEventListener {
|
||||
|
||||
private static final String TAG = "AudioFocusReactor";
|
||||
|
||||
private static final boolean SHOULD_BUILD_FOCUS_REQUEST =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
|
||||
|
||||
private static final boolean CAN_USE_MEDIA_BUTTONS =
|
||||
Build.VERSION.SDK_INT <= Build.VERSION_CODES.O_MR1;
|
||||
private static final String MEDIA_BUTTON_DEPRECATED_ERROR =
|
||||
"registerMediaButtonEventReceiver has been deprecated and maybe not supported anymore.";
|
||||
|
||||
private static final int DUCK_DURATION = 1500;
|
||||
private static final float DUCK_AUDIO_TO = .2f;
|
||||
|
||||
@ -42,7 +37,8 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
||||
|
||||
private final AudioFocusRequest request;
|
||||
|
||||
public AudioReactor(@NonNull final Context context, @NonNull final SimpleExoPlayer player) {
|
||||
public AudioReactor(@NonNull final Context context,
|
||||
@NonNull final SimpleExoPlayer player) {
|
||||
this.player = player;
|
||||
this.context = context;
|
||||
this.audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||
@ -59,6 +55,11 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
abandonAudioFocus();
|
||||
player.removeAudioDebugListener(this);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Audio Manager
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
@ -91,22 +92,6 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, Au
|
||||
audioManager.setStreamVolume(STREAM_TYPE, volume, 0);
|
||||
}
|
||||
|
||||
public void registerMediaButtonEventReceiver(ComponentName componentName) {
|
||||
if (CAN_USE_MEDIA_BUTTONS) {
|
||||
audioManager.registerMediaButtonEventReceiver(componentName);
|
||||
} else {
|
||||
Log.e(TAG, MEDIA_BUTTON_DEPRECATED_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterMediaButtonEventReceiver(ComponentName componentName) {
|
||||
if (CAN_USE_MEDIA_BUTTONS) {
|
||||
audioManager.unregisterMediaButtonEventReceiver(componentName);
|
||||
} else {
|
||||
Log.e(TAG, MEDIA_BUTTON_DEPRECATED_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// AudioFocus
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -0,0 +1,38 @@
|
||||
package org.schabi.newpipe.player.helper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
||||
|
||||
import org.schabi.newpipe.player.mediasession.DummyPlaybackPreparer;
|
||||
import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
|
||||
import org.schabi.newpipe.player.mediasession.PlayQueueNavigator;
|
||||
import org.schabi.newpipe.player.mediasession.PlayQueuePlaybackController;
|
||||
|
||||
public class MediaSessionManager {
|
||||
private static final String TAG = "MediaSessionManager";
|
||||
|
||||
private final MediaSessionCompat mediaSession;
|
||||
private final MediaSessionConnector sessionConnector;
|
||||
|
||||
public MediaSessionManager(@NonNull final Context context,
|
||||
@NonNull final Player player,
|
||||
@NonNull final MediaSessionCallback callback) {
|
||||
this.mediaSession = new MediaSessionCompat(context, TAG);
|
||||
this.sessionConnector = new MediaSessionConnector(mediaSession,
|
||||
new PlayQueuePlaybackController(callback));
|
||||
this.sessionConnector.setQueueNavigator(new PlayQueueNavigator(mediaSession, callback));
|
||||
this.sessionConnector.setPlayer(player, new DummyPlaybackPreparer());
|
||||
}
|
||||
|
||||
public MediaSessionCompat getMediaSession() {
|
||||
return mediaSession;
|
||||
}
|
||||
|
||||
public MediaSessionConnector getSessionConnector() {
|
||||
return sessionConnector;
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package org.schabi.newpipe.player.mediasession;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
||||
|
||||
public class DummyPlaybackPreparer implements MediaSessionConnector.PlaybackPreparer {
|
||||
@Override
|
||||
public long getSupportedPrepareActions() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepare() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareFromMediaId(String mediaId, Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareFromSearch(String query, Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareFromUri(Uri uri, Bundle extras) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCommands() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(Player player, String command, Bundle extras, ResultReceiver cb) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.schabi.newpipe.player.mediasession;
|
||||
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
|
||||
public interface MediaSessionCallback {
|
||||
void onSkipToPrevious();
|
||||
void onSkipToNext();
|
||||
void onSkipToIndex(final int index);
|
||||
|
||||
int getCurrentPlayingIndex();
|
||||
int getQueueSize();
|
||||
MediaDescriptionCompat getQueueMetadata(final int index);
|
||||
|
||||
void onPlay();
|
||||
void onPause();
|
||||
void onSetShuffle(final boolean isShuffled);
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package org.schabi.newpipe.player.mediasession;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.ResultReceiver;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_NEXT;
|
||||
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS;
|
||||
import static android.support.v4.media.session.PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM;
|
||||
|
||||
|
||||
public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator {
|
||||
public static final int DEFAULT_MAX_QUEUE_SIZE = 10;
|
||||
|
||||
private final MediaSessionCompat mediaSession;
|
||||
private final MediaSessionCallback callback;
|
||||
private final int maxQueueSize;
|
||||
|
||||
private long activeQueueItemId;
|
||||
|
||||
public PlayQueueNavigator(@NonNull final MediaSessionCompat mediaSession,
|
||||
@NonNull final MediaSessionCallback callback) {
|
||||
this.mediaSession = mediaSession;
|
||||
this.callback = callback;
|
||||
this.maxQueueSize = DEFAULT_MAX_QUEUE_SIZE;
|
||||
|
||||
this.activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSupportedQueueNavigatorActions(@Nullable Player player) {
|
||||
return ACTION_SKIP_TO_NEXT | ACTION_SKIP_TO_PREVIOUS | ACTION_SKIP_TO_QUEUE_ITEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimelineChanged(Player player) {
|
||||
publishFloatingQueueWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCurrentWindowIndexChanged(Player player) {
|
||||
if (activeQueueItemId == MediaSessionCompat.QueueItem.UNKNOWN_ID
|
||||
|| player.getCurrentTimeline().getWindowCount() > maxQueueSize) {
|
||||
publishFloatingQueueWindow();
|
||||
} else if (!player.getCurrentTimeline().isEmpty()) {
|
||||
activeQueueItemId = player.getCurrentWindowIndex();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getActiveQueueItemId(@Nullable Player player) {
|
||||
return callback.getCurrentPlayingIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious(Player player) {
|
||||
callback.onSkipToPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToQueueItem(Player player, long id) {
|
||||
callback.onSkipToIndex((int) id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext(Player player) {
|
||||
callback.onSkipToNext();
|
||||
}
|
||||
|
||||
private void publishFloatingQueueWindow() {
|
||||
if (callback.getQueueSize() == 0) {
|
||||
mediaSession.setQueue(Collections.<MediaSessionCompat.QueueItem>emptyList());
|
||||
activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID;
|
||||
return;
|
||||
}
|
||||
|
||||
// Yes this is almost a copypasta, got a problem with that? =\
|
||||
int windowCount = callback.getQueueSize();
|
||||
int currentWindowIndex = callback.getCurrentPlayingIndex();
|
||||
int queueSize = Math.min(maxQueueSize, windowCount);
|
||||
int startIndex = Util.constrainValue(currentWindowIndex - ((queueSize - 1) / 2), 0,
|
||||
windowCount - queueSize);
|
||||
|
||||
List<MediaSessionCompat.QueueItem> queue = new ArrayList<>();
|
||||
for (int i = startIndex; i < startIndex + queueSize; i++) {
|
||||
queue.add(new MediaSessionCompat.QueueItem(callback.getQueueMetadata(i), i));
|
||||
}
|
||||
mediaSession.setQueue(queue);
|
||||
activeQueueItemId = currentWindowIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCommands() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(Player player, String command, Bundle extras, ResultReceiver cb) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package org.schabi.newpipe.player.mediasession;
|
||||
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
|
||||
import com.google.android.exoplayer2.Player;
|
||||
import com.google.android.exoplayer2.ext.mediasession.DefaultPlaybackController;
|
||||
|
||||
public class PlayQueuePlaybackController extends DefaultPlaybackController {
|
||||
private final MediaSessionCallback callback;
|
||||
|
||||
public PlayQueuePlaybackController(final MediaSessionCallback callback) {
|
||||
super();
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlay(Player player) {
|
||||
callback.onPlay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(Player player) {
|
||||
callback.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetShuffleMode(Player player, int shuffleMode) {
|
||||
callback.onSetShuffle(shuffleMode == PlaybackStateCompat.SHUFFLE_MODE_ALL
|
||||
|| shuffleMode == PlaybackStateCompat.SHUFFLE_MODE_GROUP);
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package org.schabi.newpipe.player.playback;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.v4.media.MediaDescriptionCompat;
|
||||
|
||||
import org.schabi.newpipe.player.BasePlayer;
|
||||
import org.schabi.newpipe.player.mediasession.MediaSessionCallback;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
|
||||
public class BasePlayerMediaSession implements MediaSessionCallback {
|
||||
private BasePlayer player;
|
||||
|
||||
public BasePlayerMediaSession(final BasePlayer player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToPrevious() {
|
||||
player.onPlayPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext() {
|
||||
player.onPlayNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToIndex(int index) {
|
||||
if (player.getPlayQueue() == null) return;
|
||||
player.onSelected(player.getPlayQueue().getItem(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentPlayingIndex() {
|
||||
if (player.getPlayQueue() == null) return -1;
|
||||
return player.getPlayQueue().getIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getQueueSize() {
|
||||
if (player.getPlayQueue() == null) return -1;
|
||||
return player.getPlayQueue().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaDescriptionCompat getQueueMetadata(int index) {
|
||||
if (player.getPlayQueue() == null || player.getPlayQueue().getItem(index) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final PlayQueueItem item = player.getPlayQueue().getItem(index);
|
||||
MediaDescriptionCompat.Builder descriptionBuilder = new MediaDescriptionCompat.Builder()
|
||||
.setMediaId(String.valueOf(index))
|
||||
.setTitle(item.getTitle())
|
||||
.setSubtitle(item.getUploader());
|
||||
|
||||
final Uri thumbnailUri = Uri.parse(item.getThumbnailUrl());
|
||||
if (thumbnailUri != null) descriptionBuilder.setIconUri(thumbnailUri);
|
||||
|
||||
return descriptionBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlay() {
|
||||
if (!player.isPlaying()) player.onVideoPlayPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (player.isPlaying()) player.onVideoPlayPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSetShuffle(boolean isShuffled) {
|
||||
player.onShuffleModeEnabledChanged(isShuffled);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user