-Changed intents to start all players, including player swap.
-Make play queue and items serializable -Removed now deprecated code for playing url in exoplayer
This commit is contained in:
parent
705028c79d
commit
b54d18d888
12 changed files with 368 additions and 261 deletions
|
|
@ -268,9 +268,9 @@ public class BackgroundPlayer extends Service {
|
|||
@Override
|
||||
public void handleIntent(Intent intent) {
|
||||
super.handleIntent(intent);
|
||||
Serializable serializable = intent.getSerializableExtra(BackgroundPlayer.AUDIO_STREAM);
|
||||
if (serializable instanceof AudioStream) audioStream = (AudioStream) serializable;
|
||||
playUrl(audioStream.url, MediaFormat.getSuffixById(audioStream.format), true);
|
||||
|
||||
notBuilder = createNotification();
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
|
||||
if (bigNotRemoteView != null) bigNotRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false);
|
||||
if (notRemoteView != null) notRemoteView.setProgressBar(R.id.notificationProgressBar, 100, 0, false);
|
||||
|
|
@ -294,14 +294,6 @@ public class BackgroundPlayer extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playUrl(String url, String format, boolean autoPlay) {
|
||||
super.playUrl(url, format, autoPlay);
|
||||
|
||||
notBuilder = createNotification();
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepared(boolean playWhenReady) {
|
||||
super.onPrepared(playWhenReady);
|
||||
|
|
@ -348,15 +340,13 @@ public class BackgroundPlayer extends Service {
|
|||
|
||||
@Override
|
||||
public void onFastRewind() {
|
||||
// super.onFastRewind();
|
||||
simpleExoPlayer.seekTo(0, 0);
|
||||
playQueue.setIndex(playQueue.getIndex() - 1);
|
||||
triggerProgressUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFastForward() {
|
||||
// super.onFastForward();
|
||||
simpleExoPlayer.seekTo(2, 0);
|
||||
playQueue.setIndex(playQueue.getIndex() + 1);
|
||||
triggerProgressUpdate();
|
||||
}
|
||||
|
||||
|
|
@ -380,6 +370,15 @@ public class BackgroundPlayer extends Service {
|
|||
@Override
|
||||
public void onError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playback Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
super.shutdown();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,13 +70,21 @@ import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListene
|
|||
|
||||
import org.schabi.newpipe.Downloader;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
||||
import org.schabi.newpipe.playlist.PlayQueue;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.Serializable;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
|
@ -90,7 +98,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
AudioManager.OnAudioFocusChangeListener, MediaSourceManager.PlaybackListener {
|
||||
// TODO: Check api version for deprecated audio manager methods
|
||||
|
||||
public static final boolean DEBUG = false;
|
||||
public static final boolean DEBUG = true;
|
||||
public static final String TAG = "BasePlayer";
|
||||
|
||||
protected Context context;
|
||||
|
|
@ -104,6 +112,11 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
// Intent
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public static final String INTENT_TYPE = "intent_type";
|
||||
public static final String SINGLE_STREAM = "single";
|
||||
public static final String EXTERNAL_PLAYLIST = "external";
|
||||
public static final String INTERNAL_PLAYLIST = "internal";
|
||||
|
||||
public static final String VIDEO_URL = "video_url";
|
||||
public static final String VIDEO_TITLE = "video_title";
|
||||
public static final String VIDEO_THUMBNAIL_URL = "video_thumbnail_url";
|
||||
|
|
@ -111,6 +124,9 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
public static final String CHANNEL_NAME = "channel_name";
|
||||
public static final String PLAYBACK_SPEED = "playback_speed";
|
||||
|
||||
public static final String RESTORE_QUEUE_INDEX = "restore_queue_index";
|
||||
public static final String RESTORE_WINDOW_POS = "restore_window_pos";
|
||||
|
||||
protected Bitmap videoThumbnail = null;
|
||||
protected String videoUrl = "";
|
||||
protected String videoTitle = "";
|
||||
|
|
@ -125,8 +141,8 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
protected MediaSourceManager playbackManager;
|
||||
protected PlayQueue playQueue;
|
||||
|
||||
private int windowIndex;
|
||||
private long windowPos;
|
||||
protected int restoreQueueIndex;
|
||||
protected long restoreWindowPos;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Player
|
||||
|
|
@ -219,15 +235,54 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||
if (intent == null) return;
|
||||
|
||||
videoUrl = intent.getStringExtra(VIDEO_URL);
|
||||
videoTitle = intent.getStringExtra(VIDEO_TITLE);
|
||||
videoThumbnailUrl = intent.getStringExtra(VIDEO_THUMBNAIL_URL);
|
||||
videoStartPos = intent.getLongExtra(START_POSITION, -1L);
|
||||
uploaderName = intent.getStringExtra(CHANNEL_NAME);
|
||||
restoreQueueIndex = intent.getIntExtra(RESTORE_QUEUE_INDEX, 0);
|
||||
restoreWindowPos = intent.getLongExtra(START_POSITION, 0);
|
||||
setPlaybackSpeed(intent.getFloatExtra(PLAYBACK_SPEED, getPlaybackSpeed()));
|
||||
|
||||
switch (intent.getStringExtra(INTENT_TYPE)) {
|
||||
case SINGLE_STREAM:
|
||||
handleSinglePlaylistIntent(intent);
|
||||
break;
|
||||
case EXTERNAL_PLAYLIST:
|
||||
handleExternalPlaylistIntent(intent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
initThumbnail();
|
||||
//play(getSelectedVideoStream(), true);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleExternalPlaylistIntent(Intent intent) {
|
||||
final int serviceId = intent.getIntExtra(ExternalPlayQueue.SERVICE_ID, -1);
|
||||
final int index = intent.getIntExtra(ExternalPlayQueue.INDEX, 0);
|
||||
final Serializable serializable = intent.getSerializableExtra(ExternalPlayQueue.STREAMS);
|
||||
final String nextPageUrl = intent.getStringExtra(ExternalPlayQueue.NEXT_PAGE_URL);
|
||||
|
||||
List<InfoItem> info = new ArrayList<>();
|
||||
if (serializable instanceof List) {
|
||||
for (final Object o : (List) serializable) {
|
||||
if (o instanceof InfoItem) info.add((StreamInfoItem) o);
|
||||
}
|
||||
}
|
||||
|
||||
playQueue = new ExternalPlayQueue(serviceId, nextPageUrl, info, index);
|
||||
playQueue.init();
|
||||
|
||||
playbackManager = new MediaSourceManager(this, playQueue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleSinglePlaylistIntent(Intent intent) {
|
||||
final Serializable serializable = intent.getSerializableExtra(SinglePlayQueue.STREAM);
|
||||
if (!(serializable instanceof StreamInfo)) return;
|
||||
|
||||
playQueue = new SinglePlayQueue((StreamInfo) serializable, PlayQueueItem.DEFAULT_QUALITY);
|
||||
playQueue.init();
|
||||
|
||||
playbackManager = new MediaSourceManager(this, playQueue);
|
||||
}
|
||||
|
||||
public void initThumbnail() {
|
||||
|
|
@ -247,27 +302,6 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
});
|
||||
}
|
||||
|
||||
public void playUrl(String url, String format, boolean autoPlay) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "play() called with: url = [" + url + "], autoPlay = [" + autoPlay + "]");
|
||||
}
|
||||
|
||||
if (url == null || simpleExoPlayer == null) {
|
||||
RuntimeException runtimeException = new RuntimeException((url == null ? "Url " : "Player ") + " null");
|
||||
onError(runtimeException);
|
||||
throw runtimeException;
|
||||
}
|
||||
|
||||
changeState(STATE_LOADING);
|
||||
|
||||
isPrepared = false;
|
||||
|
||||
if (simpleExoPlayer.getPlaybackState() != Player.STATE_IDLE) simpleExoPlayer.stop();
|
||||
if (videoStartPos > 0) simpleExoPlayer.seekTo(videoStartPos);
|
||||
simpleExoPlayer.prepare(mediaSource);
|
||||
simpleExoPlayer.setPlayWhenReady(autoPlay);
|
||||
}
|
||||
|
||||
public void destroyPlayer() {
|
||||
if (DEBUG) Log.d(TAG, "destroyPlayer() called");
|
||||
if (simpleExoPlayer != null) {
|
||||
|
|
@ -466,7 +500,6 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
|
||||
public void onRepeatClicked() {
|
||||
if (DEBUG) Log.d(TAG, "onRepeatClicked() called");
|
||||
// TODO: implement repeat all when playlist is implemented
|
||||
|
||||
final int mode;
|
||||
|
||||
|
|
@ -482,7 +515,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
mode = Player.REPEAT_MODE_OFF;
|
||||
break;
|
||||
}
|
||||
// Switch the modes between DISABLED and REPEAT_ONE, till playlist is implemented
|
||||
|
||||
simpleExoPlayer.setRepeatMode(mode);
|
||||
if (DEBUG) Log.d(TAG, "onRepeatClicked() currentRepeatMode = " + simpleExoPlayer.getRepeatMode());
|
||||
}
|
||||
|
|
@ -566,8 +599,6 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
Log.d(TAG, "Blocking...");
|
||||
|
||||
simpleExoPlayer.stop();
|
||||
windowIndex = simpleExoPlayer.getCurrentWindowIndex();
|
||||
windowPos = Math.max(0, simpleExoPlayer.getContentPosition());
|
||||
|
||||
changeState(STATE_BUFFERING);
|
||||
}
|
||||
|
|
@ -576,42 +607,51 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
public void unblock() {
|
||||
Log.d(TAG, "Unblocking...");
|
||||
|
||||
if (windowIndex != playbackManager.getCurrentSourceIndex()) {
|
||||
windowIndex = playbackManager.getCurrentSourceIndex();
|
||||
windowPos = 0;
|
||||
if (restoreQueueIndex != playQueue.getIndex()) {
|
||||
restoreQueueIndex = playQueue.getIndex();
|
||||
restoreWindowPos = 0;
|
||||
}
|
||||
|
||||
simpleExoPlayer.prepare(playbackManager.getMediaSource());
|
||||
simpleExoPlayer.seekTo(windowIndex, windowPos);
|
||||
simpleExoPlayer.setPlayWhenReady(true);
|
||||
simpleExoPlayer.seekTo(playbackManager.getCurrentSourceIndex(), restoreWindowPos);
|
||||
simpleExoPlayer.setPlayWhenReady(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync(final int windowIndex, final StreamInfo info) {
|
||||
public void sync(final StreamInfo info, final int sortedStreamsIndex) {
|
||||
Log.d(TAG, "Syncing...");
|
||||
|
||||
videoUrl = info.url;
|
||||
videoThumbnailUrl = info.thumbnail_url;
|
||||
videoTitle = info.name;
|
||||
|
||||
if (simpleExoPlayer.getCurrentWindowIndex() != windowIndex) {
|
||||
if (simpleExoPlayer.getCurrentWindowIndex() != playbackManager.getCurrentSourceIndex()) {
|
||||
Log.w(TAG, "Rewinding to correct window");
|
||||
simpleExoPlayer.seekTo(windowIndex, 0L);
|
||||
simpleExoPlayer.seekTo(playbackManager.getCurrentSourceIndex(), 0L);
|
||||
}
|
||||
|
||||
simpleExoPlayer.setPlayWhenReady(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSource sourceOf(final StreamInfo info) {
|
||||
public MediaSource sourceOf(final StreamInfo info, final int sortedStreamsIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
Log.d(TAG, "Shutting down...");
|
||||
|
||||
playbackManager.dispose();
|
||||
playQueue.dispose();
|
||||
destroy();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// General Player
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void onError(Exception exception){
|
||||
destroy();
|
||||
}
|
||||
public abstract void onError(Exception exception);
|
||||
|
||||
public void onPrepared(boolean playWhenReady) {
|
||||
if (DEBUG) Log.d(TAG, "onPrepared() called with: playWhenReady = [" + playWhenReady + "]");
|
||||
|
|
@ -840,4 +880,12 @@ public abstract class BasePlayer implements Player.EventListener,
|
|||
public void setPlaybackSpeed(float speed) {
|
||||
simpleExoPlayer.setPlaybackParameters(new PlaybackParameters(speed, 1f));
|
||||
}
|
||||
|
||||
public int getCurrentQueueIndex() {
|
||||
return playQueue != null ? playQueue.getIndex() : -1;
|
||||
}
|
||||
|
||||
public PlayQueue getPlayQueue() {
|
||||
return playQueue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,8 @@ public class MainVideoPlayer extends Activity {
|
|||
if (activityPaused) {
|
||||
playerImpl.initPlayer();
|
||||
playerImpl.getPlayPauseButton().setImageResource(R.drawable.ic_play_arrow_white);
|
||||
playerImpl.play(false);
|
||||
playerImpl.playQueue.init();
|
||||
//playerImpl.play(false);
|
||||
activityPaused = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -230,21 +231,25 @@ public class MainVideoPlayer extends Activity {
|
|||
channelTextView.setText(getUploaderName());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playback Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void sync(final int windowIndex, final StreamInfo info) {
|
||||
super.sync(windowIndex, info);
|
||||
public void shutdown() {
|
||||
super.shutdown();
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync(final StreamInfo info, final int sortedStreamsIndex) {
|
||||
super.sync(info, sortedStreamsIndex);
|
||||
titleTextView.setText(getVideoTitle());
|
||||
channelTextView.setText(getUploaderName());
|
||||
|
||||
playPauseButton.setImageResource(R.drawable.ic_pause_white);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playUrl(String url, String format, boolean autoPlay) {
|
||||
super.playUrl(url, format, autoPlay);
|
||||
playPauseButton.setImageResource(autoPlay ? R.drawable.ic_pause_white : R.drawable.ic_play_arrow_white);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFullScreenButtonClicked() {
|
||||
if (DEBUG) Log.d(TAG, "onFullScreenButtonClicked() called");
|
||||
|
|
@ -331,7 +336,6 @@ public class MainVideoPlayer extends Activity {
|
|||
public void onError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
Toast.makeText(context, "Failed to play this video", Toast.LENGTH_SHORT).show();
|
||||
//finish();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package org.schabi.newpipe.player;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource;
|
||||
import com.google.android.exoplayer2.source.MediaSource;
|
||||
|
|
@ -19,7 +18,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.MaybeObserver;
|
||||
import io.reactivex.SingleObserver;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.annotations.NonNull;
|
||||
|
|
@ -67,13 +65,15 @@ class MediaSourceManager {
|
|||
* Signals to the listener to synchronize the player's window to the manager's
|
||||
* window.
|
||||
* */
|
||||
void sync(final int windowIndex, final StreamInfo info);
|
||||
void sync(final StreamInfo info, final int sortedStreamsIndex);
|
||||
|
||||
/*
|
||||
* Requests the listener to resolve a stream info into a media source respective
|
||||
* of the listener's implementation (background, popup or main video player),
|
||||
* */
|
||||
MediaSource sourceOf(final StreamInfo info);
|
||||
MediaSource sourceOf(final StreamInfo info, final int sortedStreamsIndex);
|
||||
|
||||
void shutdown();
|
||||
}
|
||||
|
||||
MediaSourceManager(@NonNull final MediaSourceManager.PlaybackListener listener,
|
||||
|
|
@ -118,9 +118,7 @@ class MediaSourceManager {
|
|||
|
||||
void report(final Exception error) {
|
||||
// ignore error checking for now, just remove the current index
|
||||
if (error != null) {
|
||||
tryBlock();
|
||||
}
|
||||
if (error == null || !tryBlock()) return;
|
||||
|
||||
final int index = playQueue.getIndex();
|
||||
playQueue.remove(index);
|
||||
|
|
@ -129,6 +127,19 @@ class MediaSourceManager {
|
|||
load();
|
||||
}
|
||||
|
||||
int queueIndexOf(final int sourceIndex) {
|
||||
return sourceIndex < sourceToQueueIndex.size() ? sourceToQueueIndex.get(sourceIndex) : -1;
|
||||
}
|
||||
|
||||
void updateCurrent(final int newSortedStreamsIndex) {
|
||||
if (!tryBlock()) return;
|
||||
|
||||
PlayQueueItem item = playQueue.getCurrent();
|
||||
item.setSortedQualityIndex(newSortedStreamsIndex);
|
||||
resetSources();
|
||||
load();
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
if (loadingReactor != null) loadingReactor.cancel();
|
||||
if (playQueueReactor != null) playQueueReactor.cancel();
|
||||
|
|
@ -180,7 +191,10 @@ class MediaSourceManager {
|
|||
if (!isPlayQueueReady()) {
|
||||
tryBlock();
|
||||
playQueue.fetch();
|
||||
} else if (playQueue.isEmpty()) {
|
||||
playbackListener.shutdown();
|
||||
}
|
||||
|
||||
if (playQueueReactor != null) playQueueReactor.request(1);
|
||||
}
|
||||
|
||||
|
|
@ -240,14 +254,16 @@ class MediaSourceManager {
|
|||
}
|
||||
|
||||
private void sync() {
|
||||
final PlayQueueItem currentItem = playQueue.getCurrent();
|
||||
|
||||
final Consumer<StreamInfo> onSuccess = new Consumer<StreamInfo>() {
|
||||
@Override
|
||||
public void accept(StreamInfo streamInfo) throws Exception {
|
||||
playbackListener.sync(getCurrentSourceIndex(), streamInfo);
|
||||
playbackListener.sync(streamInfo, currentItem.getSortedQualityIndex());
|
||||
}
|
||||
};
|
||||
|
||||
playQueue.getCurrent().getStream().subscribe(onSuccess);
|
||||
currentItem.getStream().subscribe(onSuccess);
|
||||
}
|
||||
|
||||
private void load() {
|
||||
|
|
@ -280,7 +296,7 @@ class MediaSourceManager {
|
|||
|
||||
@Override
|
||||
public void onSuccess(@NonNull StreamInfo streamInfo) {
|
||||
final MediaSource source = playbackListener.sourceOf(streamInfo);
|
||||
final MediaSource source = playbackListener.sourceOf(streamInfo, item.getSortedQualityIndex());
|
||||
insert(playQueue.indexOf(item), source);
|
||||
if (tryUnblock()) sync();
|
||||
}
|
||||
|
|
@ -305,13 +321,12 @@ class MediaSourceManager {
|
|||
// Media Source List Manipulation
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void replace(final int queueIndex, final MediaSource source) {
|
||||
private void reset(final int queueIndex) {
|
||||
if (queueIndex < 0) return;
|
||||
|
||||
final int sourceIndex = sourceToQueueIndex.indexOf(queueIndex);
|
||||
if (sourceIndex != -1) {
|
||||
// Add the source after the one to remove, so the window will remain the same in the player
|
||||
sources.addMediaSource(sourceIndex + 1, source);
|
||||
sourceToQueueIndex.remove(sourceIndex);
|
||||
sources.removeMediaSource(sourceIndex);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,10 +272,11 @@ public class PopupVideoPlayer extends Service {
|
|||
notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 77);
|
||||
break;
|
||||
case Player.REPEAT_MODE_ONE:
|
||||
notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 255);
|
||||
//todo change image
|
||||
notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 168);
|
||||
break;
|
||||
case Player.REPEAT_MODE_ALL:
|
||||
// Waiting :)
|
||||
notRemoteView.setInt(R.id.notificationRepeat, setAlphaMethodName, 255);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -390,18 +391,6 @@ public class PopupVideoPlayer extends Service {
|
|||
super("VideoPlayerImpl" + PopupVideoPlayer.TAG, PopupVideoPlayer.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playUrl(String url, String format, boolean autoPlay) {
|
||||
super.playUrl(url, format, autoPlay);
|
||||
|
||||
windowLayoutParams.width = (int) popupWidth;
|
||||
windowLayoutParams.height = (int) getMinimumVideoHeight(popupWidth);
|
||||
windowManager.updateViewLayout(getRootView(), windowLayoutParams);
|
||||
|
||||
notBuilder = createNotification();
|
||||
startForeground(NOTIFICATION_ID, notBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initViews(View rootView) {
|
||||
super.initViews(rootView);
|
||||
|
|
@ -475,7 +464,6 @@ public class PopupVideoPlayer extends Service {
|
|||
public void onError(Exception exception) {
|
||||
exception.printStackTrace();
|
||||
Toast.makeText(context, "Failed to play this video", Toast.LENGTH_SHORT).show();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -486,6 +474,16 @@ public class PopupVideoPlayer extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playback Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
super.shutdown();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Broadcast Receiver
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
@ -583,8 +581,14 @@ public class PopupVideoPlayer extends Service {
|
|||
if (DEBUG)
|
||||
Log.d(TAG, "onDoubleTap() called with: e = [" + e + "]" + "rawXy = " + e.getRawX() + ", " + e.getRawY() + ", xy = " + e.getX() + ", " + e.getY());
|
||||
if (!playerImpl.isPlaying()) return false;
|
||||
if (e.getX() > popupWidth / 2) playerImpl.onFastForward();
|
||||
else playerImpl.onFastRewind();
|
||||
if (e.getX() > popupWidth / 2) {
|
||||
//playerImpl.onFastForward();
|
||||
playerImpl.playQueue.setIndex(playerImpl.playQueue.getIndex() + 1);
|
||||
} else {
|
||||
//playerImpl.onFastRewind();
|
||||
playerImpl.playQueue.setIndex(playerImpl.playQueue.getIndex() - 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -766,7 +770,7 @@ public class PopupVideoPlayer extends Service {
|
|||
mainHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
playerImpl.play(true);
|
||||
playerImpl.playQueue.init();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@ import com.google.android.exoplayer2.source.MergingMediaSource;
|
|||
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
import org.schabi.newpipe.playlist.PlayQueue;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||
import org.schabi.newpipe.util.AnimationUtils;
|
||||
import org.schabi.newpipe.util.ListHelper;
|
||||
|
||||
|
|
@ -89,7 +89,10 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
public static final String INDEX_SEL_VIDEO_STREAM = "index_selected_video_stream";
|
||||
public static final String STARTED_FROM_NEWPIPE = "started_from_newpipe";
|
||||
|
||||
private int selectedIndexStream;
|
||||
public static final String PLAY_QUEUE = "play_queue";
|
||||
public static final String PLAYER_INTENT = "player_intent";
|
||||
|
||||
private int selectedIndexStream = -1;
|
||||
private ArrayList<VideoStream> videoStreamsList = new ArrayList<>();
|
||||
private AudioStream videoOnlyAudioStream;
|
||||
|
||||
|
|
@ -202,65 +205,55 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
simpleExoPlayer.setVideoListener(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleSingleStreamIntent(Intent intent) {
|
||||
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||
if (intent == null) return;
|
||||
|
||||
selectedIndexStream = intent.getIntExtra(INDEX_SEL_VIDEO_STREAM, -1);
|
||||
|
||||
Serializable serializable = intent.getSerializableExtra(VIDEO_STREAMS_LIST);
|
||||
|
||||
if (serializable instanceof ArrayList) videoStreamsList = (ArrayList<VideoStream>) serializable;
|
||||
if (serializable instanceof Vector) videoStreamsList = new ArrayList<>((List<VideoStream>) serializable);
|
||||
|
||||
Serializable audioStream = intent.getSerializableExtra(VIDEO_ONLY_AUDIO_STREAM);
|
||||
if (audioStream != null) videoOnlyAudioStream = (AudioStream) audioStream;
|
||||
|
||||
startedFromNewPipe = intent.getBooleanExtra(STARTED_FROM_NEWPIPE, true);
|
||||
play(true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleIntent(Intent intent) {
|
||||
super.handleIntent(intent);
|
||||
|
||||
if (intent == null) return;
|
||||
|
||||
handleExternalPlaylistIntent(intent);
|
||||
if (intent.getStringExtra(INTENT_TYPE).equals(PLAYER_INTENT)) {
|
||||
handlePlayerIntent(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handleExternalPlaylistIntent(Intent intent) {
|
||||
selectedIndexStream = 0;
|
||||
public void handleSinglePlaylistIntent(Intent intent) {
|
||||
final Serializable serializable = intent.getSerializableExtra(SinglePlayQueue.STREAM);
|
||||
if (!(serializable instanceof StreamInfo)) return;
|
||||
|
||||
final int serviceId = intent.getIntExtra("serviceId", -1);
|
||||
final int index = intent.getIntExtra("index", 0);
|
||||
final Serializable serializable = intent.getSerializableExtra("streams");
|
||||
final String nextPageUrl = intent.getStringExtra("nextPageUrl");
|
||||
final int sortedStreamsIndex = intent.getIntExtra(INDEX_SEL_VIDEO_STREAM, -1);
|
||||
|
||||
List<InfoItem> info = new ArrayList<>();
|
||||
if (serializable instanceof List) {
|
||||
for (final Object o : (List) serializable) {
|
||||
if (o instanceof InfoItem) info.add((StreamInfoItem) o);
|
||||
}
|
||||
}
|
||||
playQueue = new SinglePlayQueue((StreamInfo) serializable, sortedStreamsIndex);
|
||||
playQueue.init();
|
||||
|
||||
playQueue = new ExternalPlayQueue(serviceId, nextPageUrl, info, index);
|
||||
playbackManager = new MediaSourceManager(this, playQueue);
|
||||
}
|
||||
|
||||
public void play(boolean autoPlay) {
|
||||
playUrl(getSelectedVideoStream().url, MediaFormat.getSuffixById(getSelectedVideoStream().format), autoPlay);
|
||||
@SuppressWarnings("unchecked")
|
||||
public void handlePlayerIntent(Intent intent) {
|
||||
final Serializable serializable = intent.getSerializableExtra(PLAY_QUEUE);
|
||||
if (!(serializable instanceof PlayQueue)) return;
|
||||
|
||||
selectedIndexStream = intent.getIntExtra(INDEX_SEL_VIDEO_STREAM, -1);
|
||||
|
||||
playQueue = (PlayQueue) serializable;
|
||||
playQueue.init();
|
||||
|
||||
playbackManager = new MediaSourceManager(this, playQueue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sync(final int windowIndex, final StreamInfo info) {
|
||||
super.sync(windowIndex, info);
|
||||
public void sync(final StreamInfo info, final int sortedStreamsIndex) {
|
||||
super.sync(info, sortedStreamsIndex);
|
||||
|
||||
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false);
|
||||
videoStreamsList = new ArrayList<>(videos);
|
||||
selectedIndexStream = ListHelper.getDefaultResolutionIndex(context, videos);
|
||||
|
||||
if (sortedStreamsIndex == PlayQueueItem.DEFAULT_QUALITY) {
|
||||
selectedIndexStream = ListHelper.getDefaultResolutionIndex(context, videos);
|
||||
} else {
|
||||
selectedIndexStream = sortedStreamsIndex;
|
||||
}
|
||||
|
||||
qualityPopupMenu.getMenu().removeGroup(qualityPopupMenuGroupId);
|
||||
buildQualityMenu(qualityPopupMenu);
|
||||
|
|
@ -270,9 +263,16 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
}
|
||||
|
||||
@Override
|
||||
public MediaSource sourceOf(final StreamInfo info) {
|
||||
public MediaSource sourceOf(final StreamInfo info, final int sortedStreamsIndex) {
|
||||
final List<VideoStream> videos = ListHelper.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false);
|
||||
final VideoStream video = videos.get(ListHelper.getDefaultResolutionIndex(context, videos));
|
||||
|
||||
final VideoStream video;
|
||||
if (sortedStreamsIndex == PlayQueueItem.DEFAULT_QUALITY) {
|
||||
final int index = ListHelper.getDefaultResolutionIndex(context, videos);
|
||||
video = videos.get(index);
|
||||
} else {
|
||||
video = videos.get(sortedStreamsIndex);
|
||||
}
|
||||
|
||||
final MediaSource mediaSource = super.buildMediaSource(video.url, MediaFormat.getSuffixById(video.format));
|
||||
if (!video.isVideoOnly) return mediaSource;
|
||||
|
|
@ -282,26 +282,6 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
return new MergingMediaSource(mediaSource, new ExtractorMediaSource(audioUri, cacheDataSourceFactory, extractorsFactory, null, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playUrl(String url, String format, boolean autoPlay) {
|
||||
if (DEBUG) Log.d(TAG, "play() called with: url = [" + url + "], autoPlay = [" + autoPlay + "]");
|
||||
qualityChanged = false;
|
||||
|
||||
if (url == null || simpleExoPlayer == null) {
|
||||
RuntimeException runtimeException = new RuntimeException((url == null ? "Url " : "Player ") + " null");
|
||||
onError(runtimeException);
|
||||
throw runtimeException;
|
||||
}
|
||||
|
||||
qualityPopupMenu.getMenu().removeGroup(qualityPopupMenuGroupId);
|
||||
buildQualityMenu(qualityPopupMenu);
|
||||
|
||||
playbackSpeedPopupMenu.getMenu().removeGroup(playbackSpeedPopupMenuGroupId);
|
||||
buildPlaybackSpeedMenu(playbackSpeedPopupMenu);
|
||||
|
||||
super.playUrl(url, format, autoPlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSource buildMediaSource(String url, String overrideExtension) {
|
||||
MediaSource mediaSource = super.buildMediaSource(url, overrideExtension);
|
||||
|
|
@ -460,6 +440,7 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
|
||||
if (duration != playbackSeekBar.getMax()) {
|
||||
playbackEndTime.setText(getTimeString(duration));
|
||||
playbackSeekBar.setMax(duration);
|
||||
}
|
||||
if (currentState != STATE_PAUSED) {
|
||||
if (currentState != STATE_PAUSED_SEEK) playbackSeekBar.setProgress(currentProgress);
|
||||
|
|
@ -478,7 +459,7 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
if (DEBUG) Log.d(TAG, "onVideoPlayPauseRepeat() called");
|
||||
if (qualityChanged) {
|
||||
setVideoStartPos(0);
|
||||
play(true);
|
||||
//play(true);
|
||||
} else super.onVideoPlayPauseRepeat();
|
||||
}
|
||||
|
||||
|
|
@ -528,11 +509,10 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
|
||||
if (qualityPopupMenuGroupId == menuItem.getGroupId()) {
|
||||
if (selectedIndexStream == menuItem.getItemId()) return true;
|
||||
setVideoStartPos(simpleExoPlayer.getCurrentPosition());
|
||||
|
||||
selectedIndexStream = menuItem.getItemId();
|
||||
if (!(getCurrentState() == STATE_COMPLETED)) play(wasPlaying);
|
||||
else qualityChanged = true;
|
||||
restoreQueueIndex = playQueue.getIndex();
|
||||
restoreWindowPos = simpleExoPlayer.getCurrentPosition();
|
||||
playbackManager.updateCurrent(menuItem.getItemId());
|
||||
|
||||
qualityTextView.setText(menuItem.getTitle());
|
||||
return true;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue