-Hooking playback manager and play queue into main video player.
This commit is contained in:
parent
701320b100
commit
b859823011
|
@ -1,5 +1,6 @@
|
||||||
package org.schabi.newpipe.fragments.playlist;
|
package org.schabi.newpipe.fragments.playlist;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -17,6 +18,7 @@ import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
@ -29,14 +31,19 @@ import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlayListExtractor;
|
import org.schabi.newpipe.extractor.playlist.PlayListExtractor;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlayListInfo;
|
import org.schabi.newpipe.extractor.playlist.PlayListInfo;
|
||||||
|
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||||
import org.schabi.newpipe.fragments.BaseFragment;
|
import org.schabi.newpipe.fragments.BaseFragment;
|
||||||
import org.schabi.newpipe.fragments.search.OnScrollBelowItemsListener;
|
import org.schabi.newpipe.fragments.search.OnScrollBelowItemsListener;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
import org.schabi.newpipe.info_list.InfoListAdapter;
|
import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||||
|
import org.schabi.newpipe.player.BasePlayer;
|
||||||
|
import org.schabi.newpipe.player.MainVideoPlayer;
|
||||||
|
import org.schabi.newpipe.player.VideoPlayer;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.Utils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -78,6 +85,7 @@ public class PlaylistFragment extends BaseFragment {
|
||||||
private ImageView headerBannerView;
|
private ImageView headerBannerView;
|
||||||
private ImageView headerAvatarView;
|
private ImageView headerAvatarView;
|
||||||
private TextView headerTitleView;
|
private TextView headerTitleView;
|
||||||
|
private Button headerPlayAllButton;
|
||||||
|
|
||||||
/*////////////////////////////////////////////////////////////////////////*/
|
/*////////////////////////////////////////////////////////////////////////*/
|
||||||
// Reactors
|
// Reactors
|
||||||
|
@ -95,6 +103,15 @@ public class PlaylistFragment extends BaseFragment {
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void play(Context context, Class targetClazz) {
|
||||||
|
Intent mIntent = new Intent(context, targetClazz)
|
||||||
|
.putExtra("url", playlistUrl)
|
||||||
|
.putExtra("nextPage", 1)
|
||||||
|
.putExtra("index", 0)
|
||||||
|
.putExtra("stream", currentPlaylistInfo);
|
||||||
|
startActivity(mIntent);
|
||||||
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Fragment's LifeCycle
|
// Fragment's LifeCycle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -246,6 +263,9 @@ public class PlaylistFragment extends BaseFragment {
|
||||||
headerBannerView = headerRootLayout.findViewById(R.id.playlist_banner_image);
|
headerBannerView = headerRootLayout.findViewById(R.id.playlist_banner_image);
|
||||||
headerAvatarView = headerRootLayout.findViewById(R.id.playlist_avatar_view);
|
headerAvatarView = headerRootLayout.findViewById(R.id.playlist_avatar_view);
|
||||||
headerTitleView = headerRootLayout.findViewById(R.id.playlist_title_view);
|
headerTitleView = headerRootLayout.findViewById(R.id.playlist_title_view);
|
||||||
|
|
||||||
|
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_play_all_button);
|
||||||
|
headerPlayAllButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initListeners() {
|
protected void initListeners() {
|
||||||
|
@ -266,6 +286,13 @@ public class PlaylistFragment extends BaseFragment {
|
||||||
loadMore(true);
|
loadMore(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
headerPlayAllButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
play(activity, MainVideoPlayer.class);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -434,7 +461,7 @@ public class PlaylistFragment extends BaseFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handlePlayListInfo(PlayListInfo info, boolean onlyVideos, boolean addVideos) {
|
private void handlePlayListInfo(PlayListInfo info, boolean onlyVideos, boolean addVideos) {
|
||||||
currentPlaylistInfo = info;
|
if (currentPlaylistInfo == null) currentPlaylistInfo = info;
|
||||||
|
|
||||||
animateView(errorPanel, false, 300);
|
animateView(errorPanel, false, 300);
|
||||||
animateView(playlistStreams, true, 200);
|
animateView(playlistStreams, true, 200);
|
||||||
|
@ -468,7 +495,10 @@ public class PlaylistFragment extends BaseFragment {
|
||||||
if (!hasNextPage) infoListAdapter.showFooter(false);
|
if (!hasNextPage) infoListAdapter.showFooter(false);
|
||||||
|
|
||||||
//if (!listRestored) {
|
//if (!listRestored) {
|
||||||
if (addVideos) infoListAdapter.addInfoItemList(info.related_streams);
|
if (addVideos) {
|
||||||
|
infoListAdapter.addInfoItemList(info.related_streams);
|
||||||
|
currentPlaylistInfo.related_streams.addAll(info.related_streams);
|
||||||
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,6 +72,7 @@ import org.schabi.newpipe.Downloader;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||||
import org.schabi.newpipe.playlist.PlayQueue;
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
|
import org.schabi.newpipe.util.Utils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
@ -257,7 +258,6 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||||
changeState(STATE_LOADING);
|
changeState(STATE_LOADING);
|
||||||
|
|
||||||
isPrepared = false;
|
isPrepared = false;
|
||||||
mediaSource = buildMediaSource(url, format);
|
|
||||||
|
|
||||||
if (simpleExoPlayer.getPlaybackState() != Player.STATE_IDLE) simpleExoPlayer.stop();
|
if (simpleExoPlayer.getPlaybackState() != Player.STATE_IDLE) simpleExoPlayer.stop();
|
||||||
if (videoStartPos > 0) simpleExoPlayer.seekTo(videoStartPos);
|
if (videoStartPos > 0) simpleExoPlayer.seekTo(videoStartPos);
|
||||||
|
@ -548,7 +548,7 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||||
@Override
|
@Override
|
||||||
public void onPositionDiscontinuity() {
|
public void onPositionDiscontinuity() {
|
||||||
int newIndex = simpleExoPlayer.getCurrentWindowIndex();
|
int newIndex = simpleExoPlayer.getCurrentWindowIndex();
|
||||||
|
playbackManager.refreshMedia(newIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -567,12 +567,12 @@ public abstract class BasePlayer implements Player.EventListener,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sync(final StreamInfo info) {
|
public void sync(final StreamInfo info) {
|
||||||
|
videoTitle = info.title;
|
||||||
|
channelName = info.uploader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaSource sourceOf(final StreamInfo info) {
|
public MediaSource sourceOf(final StreamInfo info) {
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -454,9 +454,15 @@ public class MainVideoPlayer extends Activity {
|
||||||
@Override
|
@Override
|
||||||
public boolean onDoubleTap(MotionEvent e) {
|
public boolean onDoubleTap(MotionEvent e) {
|
||||||
if (DEBUG) Log.d(TAG, "onDoubleTap() called with: e = [" + e + "]" + "rawXy = " + e.getRawX() + ", " + e.getRawY() + ", xy = " + e.getX() + ", " + e.getY());
|
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 (!playerImpl.isPlaying()) return false;
|
||||||
if (e.getX() > playerImpl.getRootView().getWidth() / 2) playerImpl.onFastForward();
|
|
||||||
else playerImpl.onFastRewind();
|
if (e.getX() > playerImpl.getRootView().getWidth() / 2)
|
||||||
|
playerImpl.playQueue.setIndex(playerImpl.playQueue.getIndex() + 1);
|
||||||
|
//playerImpl.onFastForward();
|
||||||
|
else
|
||||||
|
playerImpl.playQueue.setIndex(playerImpl.playQueue.getIndex() - 1);
|
||||||
|
//playerImpl.onFastRewind();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,14 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.Maybe;
|
import io.reactivex.Maybe;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.annotations.NonNull;
|
import io.reactivex.annotations.NonNull;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public class PlaybackManager {
|
public class PlaybackManager {
|
||||||
|
|
||||||
|
private static final int WINDOW_SIZE = 5;
|
||||||
|
|
||||||
private DynamicConcatenatingMediaSource mediaSource;
|
private DynamicConcatenatingMediaSource mediaSource;
|
||||||
private List<PlayQueueItem> queueSource;
|
private List<PlayQueueItem> queueSource;
|
||||||
private int sourceIndex;
|
private int sourceIndex;
|
||||||
|
@ -58,8 +62,11 @@ public class PlaybackManager {
|
||||||
load(0);
|
load(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeSource(final int index) {
|
public void changeSource(final MediaSource newSource) {
|
||||||
|
listener.block();
|
||||||
|
this.mediaSource.removeMediaSource(0);
|
||||||
|
this.mediaSource.addMediaSource(0, newSource);
|
||||||
|
listener.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshMedia(final int newMediaIndex) {
|
public void refreshMedia(final int newMediaIndex) {
|
||||||
|
@ -71,7 +78,7 @@ public class PlaybackManager {
|
||||||
queueSource.remove(0);
|
queueSource.remove(0);
|
||||||
} else {
|
} else {
|
||||||
//something went wrong
|
//something went wrong
|
||||||
init();
|
reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +92,8 @@ public class PlaybackManager {
|
||||||
private Subscription loaderReactor;
|
private Subscription loaderReactor;
|
||||||
|
|
||||||
private void load() {
|
private void load() {
|
||||||
if (mediaSource.getSize() < 5 && queueSource.size() < 5) load(mediaSource.getSize());
|
if (mediaSource.getSize() < WINDOW_SIZE && queueSource.size() < WINDOW_SIZE)
|
||||||
|
load(mediaSource.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void load(final int from) {
|
private void load(final int from) {
|
||||||
|
@ -94,23 +102,33 @@ public class PlaybackManager {
|
||||||
if (loaderReactor != null) loaderReactor.cancel();
|
if (loaderReactor != null) loaderReactor.cancel();
|
||||||
|
|
||||||
List<Maybe<StreamInfo>> maybes = new ArrayList<>();
|
List<Maybe<StreamInfo>> maybes = new ArrayList<>();
|
||||||
for (int i = from; i < 5; i++) {
|
for (int i = from; i < WINDOW_SIZE; i++) {
|
||||||
final int index = playQueue.getIndex() + i;
|
final int index = playQueue.getIndex() + i;
|
||||||
final PlayQueueItem item = playQueue.get(index);
|
final PlayQueueItem item = playQueue.get(index);
|
||||||
queueSource.set(i, item);
|
|
||||||
|
if (queueSource.size() > i) queueSource.set(i, item);
|
||||||
|
else queueSource.add(item);
|
||||||
|
|
||||||
maybes.add(item.getStream());
|
maybes.add(item.getStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
Maybe.concat(maybes).subscribe(new Subscriber<StreamInfo>() {
|
Maybe.concat(maybes).subscribe(getSubscriber());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Subscriber<StreamInfo> getSubscriber() {
|
||||||
|
return new Subscriber<StreamInfo>() {
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribe(Subscription s) {
|
public void onSubscribe(Subscription s) {
|
||||||
|
if (loaderReactor != null) loaderReactor.cancel();
|
||||||
loaderReactor = s;
|
loaderReactor = s;
|
||||||
|
s.request(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(StreamInfo streamInfo) {
|
public void onNext(StreamInfo streamInfo) {
|
||||||
mediaSource.addMediaSource(listener.sourceOf(streamInfo));
|
mediaSource.addMediaSource(listener.sourceOf(streamInfo));
|
||||||
onLoaded();
|
tryUnblock();
|
||||||
|
loaderReactor.request(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -120,11 +138,13 @@ public class PlaybackManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
|
if (loaderReactor != null) loaderReactor.cancel();
|
||||||
|
loaderReactor = null;
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLoaded() {
|
private void tryUnblock() {
|
||||||
if (mediaSource.getSize() > 0 && queueSource.size() > 0) listener.unblock();
|
if (mediaSource.getSize() > 0 && queueSource.size() > 0) listener.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +154,15 @@ public class PlaybackManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clear(int from) {
|
private void clear(int from) {
|
||||||
listener.block();
|
|
||||||
while (mediaSource.getSize() > from) {
|
while (mediaSource.getSize() > from) {
|
||||||
queueSource.remove(from);
|
queueSource.remove(from);
|
||||||
mediaSource.removeMediaSource(from);
|
mediaSource.removeMediaSource(from);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clear() {
|
||||||
|
listener.block();
|
||||||
|
clear(0);
|
||||||
listener.unblock();
|
listener.unblock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +177,7 @@ public class PlaybackManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNext(@NonNull PlayQueueEvent event) {
|
public void onNext(@NonNull PlayQueueEvent event) {
|
||||||
if (playQueue.getStreams().size() - playQueue.getIndex() < 10 && !playQueue.isComplete()) {
|
if (playQueue.getStreams().size() - playQueue.getIndex() < WINDOW_SIZE && !playQueue.isComplete()) {
|
||||||
listener.block();
|
listener.block();
|
||||||
playQueue.fetch();
|
playQueue.fetch();
|
||||||
}
|
}
|
||||||
|
@ -177,14 +201,14 @@ public class PlaybackManager {
|
||||||
load(1);
|
load(1);
|
||||||
break;
|
break;
|
||||||
case CLEAR:
|
case CLEAR:
|
||||||
clear(0);
|
clear();
|
||||||
break;
|
break;
|
||||||
case NEXT:
|
case NEXT:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
onLoaded();
|
tryUnblock();
|
||||||
if (playQueueReactor != null) playQueueReactor.request(1);
|
if (playQueueReactor != null) playQueueReactor.request(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,12 +219,13 @@ public class PlaybackManager {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onComplete() {
|
public void onComplete() {
|
||||||
// Never completes, only canceled
|
dispose();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (playQueueReactor != null) playQueueReactor.cancel();
|
if (playQueueReactor != null) playQueueReactor.cancel();
|
||||||
|
playQueueReactor = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,11 @@ import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.MediaFormat;
|
import org.schabi.newpipe.extractor.MediaFormat;
|
||||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
|
import org.schabi.newpipe.extractor.playlist.PlayListInfo;
|
||||||
|
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
||||||
import org.schabi.newpipe.util.AnimationUtils;
|
import org.schabi.newpipe.util.AnimationUtils;
|
||||||
|
import org.schabi.newpipe.util.Utils;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -198,7 +202,7 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void handleIntent(Intent intent) {
|
public void handleIntent2(Intent intent) {
|
||||||
super.handleIntent(intent);
|
super.handleIntent(intent);
|
||||||
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||||
if (intent == null) return;
|
if (intent == null) return;
|
||||||
|
@ -217,6 +221,38 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
||||||
play(true);
|
play(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MediaSource sourceOf(final StreamInfo info) {
|
||||||
|
videoStreamsList = Utils.getSortedStreamVideosList(context, info.video_streams, info.video_only_streams, false);
|
||||||
|
videoOnlyAudioStream = Utils.getHighestQualityAudio(info.audio_streams);
|
||||||
|
|
||||||
|
return buildMediaSource(getSelectedVideoStream().url, MediaFormat.getSuffixById(getSelectedVideoStream().format));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unblock() {
|
||||||
|
play(true);
|
||||||
|
super.unblock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleIntent(Intent intent) {
|
||||||
|
if (intent == null) return;
|
||||||
|
|
||||||
|
selectedIndexStream = 0;
|
||||||
|
|
||||||
|
String url = intent.getStringExtra("url");
|
||||||
|
int nextPage = intent.getIntExtra("nextPage", 0);
|
||||||
|
int index = intent.getIntExtra("index", 0);
|
||||||
|
|
||||||
|
PlayListInfo info;
|
||||||
|
Serializable serializable = intent.getSerializableExtra("stream");
|
||||||
|
if (serializable instanceof PlayListInfo) info = (PlayListInfo) serializable;
|
||||||
|
else return;
|
||||||
|
|
||||||
|
playQueue = new ExternalPlayQueue(url, info, nextPage, index);
|
||||||
|
playbackManager = new PlaybackManager(this, playQueue);
|
||||||
|
mediaSource = playbackManager.getMediaSource();
|
||||||
|
}
|
||||||
|
|
||||||
public void play(boolean autoPlay) {
|
public void play(boolean autoPlay) {
|
||||||
playUrl(getSelectedVideoStream().url, MediaFormat.getSuffixById(getSelectedVideoStream().format), autoPlay);
|
playUrl(getSelectedVideoStream().url, MediaFormat.getSuffixById(getSelectedVideoStream().format), autoPlay);
|
||||||
|
|
|
@ -34,12 +34,11 @@ public class ExternalPlayQueue extends PlayQueue {
|
||||||
final PlayListInfo info,
|
final PlayListInfo info,
|
||||||
final int nextPage,
|
final int nextPage,
|
||||||
final int index) {
|
final int index) {
|
||||||
super(index);
|
super(index, extractPlaylistItems(info));
|
||||||
|
|
||||||
this.service = getService(info.service_id);
|
this.service = getService(info.service_id);
|
||||||
this.pageNumber = new AtomicInteger(nextPage);
|
this.pageNumber = new AtomicInteger(nextPage);
|
||||||
this.playlistUrl = playlistUrl;
|
this.playlistUrl = playlistUrl;
|
||||||
|
|
||||||
getStreams().addAll(extractPlaylistItems(info));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -47,12 +46,6 @@ public class ExternalPlayQueue extends PlayQueue {
|
||||||
return isComplete;
|
return isComplete;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load(int index) {
|
|
||||||
if (index > getStreams().size() || getStreams().get(index) == null) return;
|
|
||||||
getStreams().get(index).load();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlayQueueItem get(int index) {
|
public PlayQueueItem get(int index) {
|
||||||
if (index > getStreams().size() || getStreams().get(index) == null) return null;
|
if (index > getStreams().size() || getStreams().get(index) == null) return null;
|
||||||
|
@ -93,7 +86,7 @@ public class ExternalPlayQueue extends PlayQueue {
|
||||||
if (fetchReactor != null) fetchReactor.dispose();
|
if (fetchReactor != null) fetchReactor.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PlayQueueItem> extractPlaylistItems(final PlayListInfo info) {
|
private static List<PlayQueueItem> extractPlaylistItems(final PlayListInfo info) {
|
||||||
List<PlayQueueItem> result = new ArrayList<>();
|
List<PlayQueueItem> result = new ArrayList<>();
|
||||||
for (final InfoItem stream : info.related_streams) {
|
for (final InfoItem stream : info.related_streams) {
|
||||||
if (stream instanceof StreamInfoItem) {
|
if (stream instanceof StreamInfoItem) {
|
||||||
|
|
|
@ -25,8 +25,14 @@ public abstract class PlayQueue {
|
||||||
private BehaviorSubject<PlayQueueEvent> changeBroadcast;
|
private BehaviorSubject<PlayQueueEvent> changeBroadcast;
|
||||||
private Flowable<PlayQueueEvent> playQueueFlowable;
|
private Flowable<PlayQueueEvent> playQueueFlowable;
|
||||||
|
|
||||||
PlayQueue(final int index) {
|
PlayQueue() {
|
||||||
|
this(0, Collections.<PlayQueueItem>emptyList());
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayQueue(final int index, final List<PlayQueueItem> startWith) {
|
||||||
streams = Collections.synchronizedList(new ArrayList<PlayQueueItem>());
|
streams = Collections.synchronizedList(new ArrayList<PlayQueueItem>());
|
||||||
|
streams.addAll(startWith);
|
||||||
|
|
||||||
queueIndex = new AtomicInteger(index);
|
queueIndex = new AtomicInteger(index);
|
||||||
|
|
||||||
changeBroadcast = BehaviorSubject.create();
|
changeBroadcast = BehaviorSubject.create();
|
||||||
|
@ -37,9 +43,6 @@ public abstract class PlayQueue {
|
||||||
// single stream or local queues are always complete
|
// single stream or local queues are always complete
|
||||||
public abstract boolean isComplete();
|
public abstract boolean isComplete();
|
||||||
|
|
||||||
// load in the background the item at index, may do nothing if the queue is incomplete
|
|
||||||
public abstract void load(int index);
|
|
||||||
|
|
||||||
// load partial queue in the background, does nothing if the queue is complete
|
// load partial queue in the background, does nothing if the queue is complete
|
||||||
public abstract void fetch();
|
public abstract void fetch();
|
||||||
|
|
||||||
|
|
|
@ -69,10 +69,6 @@ public class PlayQueueItem {
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void load() {
|
|
||||||
stream.subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private Maybe<StreamInfo> getInfo() {
|
private Maybe<StreamInfo> getInfo() {
|
||||||
final Callable<StreamInfo> task = new Callable<StreamInfo>() {
|
final Callable<StreamInfo> task = new Callable<StreamInfo>() {
|
||||||
|
@ -101,7 +97,6 @@ public class PlayQueueItem {
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnError(onError)
|
.doOnError(onError)
|
||||||
.onErrorComplete()
|
|
||||||
.doOnComplete(onComplete)
|
.doOnComplete(onComplete)
|
||||||
.cache();
|
.cache();
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,4 +78,19 @@
|
||||||
tools:ignore="RtlHardcoded"
|
tools:ignore="RtlHardcoded"
|
||||||
tools:text="234 videos"/>
|
tools:text="234 videos"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/playlist_play_all_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_below="@+id/playlist_banner_image"
|
||||||
|
android:layout_gravity="center_vertical|right"
|
||||||
|
android:layout_marginRight="2dp"
|
||||||
|
android:text="Play All"
|
||||||
|
android:textSize="@dimen/channel_rss_title_size"
|
||||||
|
android:theme="@style/RedButton"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:ignore="RtlHardcoded"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
Loading…
Reference in New Issue