From 7c9c3de6449fd00c5fa97e48ac27e2100b1ad64a Mon Sep 17 00:00:00 2001 From: John Zhen M Date: Tue, 29 Aug 2017 08:00:11 -0700 Subject: [PATCH] -Rename playlist in players to play queue. --- .../org/schabi/newpipe/player/BasePlayer.java | 7 +- ...ourceManager.java => PlaybackManager.java} | 22 ++++-- ...alPlaylist.java => ExternalPlayQueue.java} | 79 ++++++++++++------- .../schabi/newpipe/playlist/PlayQueue.java | 42 ++++++++++ ...listAdapter.java => PlayQueueAdapter.java} | 72 +++++++++++------ .../{PlaylistItem.java => PlayQueueItem.java} | 4 +- ...emHolder.java => PlayQueueItemHolder.java} | 4 +- .../org/schabi/newpipe/playlist/Playlist.java | 38 --------- .../newpipe/playlist/PlaylistItemBuilder.java | 40 +--------- 9 files changed, 164 insertions(+), 144 deletions(-) rename app/src/main/java/org/schabi/newpipe/player/{MediaSourceManager.java => PlaybackManager.java} (50%) rename app/src/main/java/org/schabi/newpipe/playlist/{ExternalPlaylist.java => ExternalPlayQueue.java} (60%) create mode 100644 app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java rename app/src/main/java/org/schabi/newpipe/playlist/{PlaylistAdapter.java => PlayQueueAdapter.java} (63%) rename app/src/main/java/org/schabi/newpipe/playlist/{PlaylistItem.java => PlayQueueItem.java} (95%) rename app/src/main/java/org/schabi/newpipe/playlist/{PlaylistItemHolder.java => PlayQueueItemHolder.java} (93%) delete mode 100644 app/src/main/java/org/schabi/newpipe/playlist/Playlist.java diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 4d5631bc9..3746927be 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -250,12 +250,7 @@ public abstract class BasePlayer implements Player.EventListener, AudioManager.O changeState(STATE_LOADING); isPrepared = false; - - final MediaSource ms = buildMediaSource(url, format); - final DynamicConcatenatingMediaSource dcms = new DynamicConcatenatingMediaSource(); - dcms.addMediaSource(ms); - mediaSource = dcms; - dcms.addMediaSource(new LoopingMediaSource(ms, 2)); + mediaSource = buildMediaSource(url, format); if (simpleExoPlayer.getPlaybackState() != Player.STATE_IDLE) simpleExoPlayer.stop(); if (videoStartPos > 0) simpleExoPlayer.seekTo(videoStartPos); diff --git a/app/src/main/java/org/schabi/newpipe/player/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/PlaybackManager.java similarity index 50% rename from app/src/main/java/org/schabi/newpipe/player/MediaSourceManager.java rename to app/src/main/java/org/schabi/newpipe/player/PlaybackManager.java index ee4ef5df4..8b3973a54 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/PlaybackManager.java @@ -3,19 +3,31 @@ package org.schabi.newpipe.player; import com.google.android.exoplayer2.source.DynamicConcatenatingMediaSource; import com.google.android.exoplayer2.source.MediaSource; -import org.schabi.newpipe.playlist.Playlist; +import org.schabi.newpipe.playlist.PlayQueue; import java.util.List; -public class MediaSourceManager { +public class PlaybackManager { private DynamicConcatenatingMediaSource source; - private Playlist playlist; + private PlayQueue playQueue; + private int index; + private List sources; - public MediaSourceManager(Playlist playlist) { + public PlaybackManager(PlayQueue playQueue, int index) { this.source = new DynamicConcatenatingMediaSource(); - this.playlist = playlist; + + this.playQueue = playQueue; + this.index = index; + + + + } + + interface OnChangeListener { + void isLoading(); + void isLoaded(); } } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/ExternalPlaylist.java b/app/src/main/java/org/schabi/newpipe/playlist/ExternalPlayQueue.java similarity index 60% rename from app/src/main/java/org/schabi/newpipe/playlist/ExternalPlaylist.java rename to app/src/main/java/org/schabi/newpipe/playlist/ExternalPlayQueue.java index 9ffc71303..fba48d82d 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/ExternalPlaylist.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/ExternalPlayQueue.java @@ -16,26 +16,61 @@ import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; import io.reactivex.Maybe; -import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; -public class ExternalPlaylist extends Playlist { +public class ExternalPlayQueue extends PlayQueue { + + private final static int LOAD_PROXIMITY = 10; + + private boolean isComplete; private AtomicInteger pageNumber; private StreamingService service; - public ExternalPlaylist(final PlayListInfoItem playlist) { - super(); - service = getService(playlist.serviceId); - pageNumber = new AtomicInteger(0); + private PlayListInfoItem playlist; - load(playlist); + public ExternalPlayQueue(final PlayListInfoItem playlist) { + super(); + this.service = getService(playlist.serviceId); + this.pageNumber = new AtomicInteger(0); + this.playlist = playlist; + + fetch(); } - private void load(final PlayListInfoItem playlist) { + @Override + public boolean isComplete() { + return isComplete; + } + + @Override + public void load(int index, boolean loadNeighbors) { + if (index > streams.size() || streams.get(index) == null) return; + + streams.get(index).load(); + + if (loadNeighbors) { + int leftBound = index - LOAD_BOUND >= 0 ? index - LOAD_BOUND : 0; + int rightBound = index + LOAD_BOUND < streams.size() ? index + LOAD_BOUND : streams.size() - 1; + + for (int i = leftBound; i < rightBound; i++) { + final PlayQueueItem item = streams.get(i); + if (item != null) item.load(); + } + } + } + + @Override + public Maybe get(int index) { + if (index > streams.size() || streams.get(index) == null) return Maybe.empty(); + return streams.get(index).getStream(); + } + + + public synchronized void fetch() { final int page = pageNumber.getAndIncrement(); final Callable task = new Callable() { @@ -49,8 +84,10 @@ public class ExternalPlaylist extends Playlist { final Consumer onSuccess = new Consumer() { @Override public void accept(PlayListInfo playListInfo) throws Exception { + if (!playListInfo.hasNextPage) isComplete = true; + streams.addAll(extractPlaylistItems(playListInfo)); - changeBroadcast.onNext(streams); + notifyChange(); } }; @@ -61,33 +98,16 @@ public class ExternalPlaylist extends Playlist { .subscribe(onSuccess); } - private List extractPlaylistItems(final PlayListInfo info) { - List result = new ArrayList<>(); + private List extractPlaylistItems(final PlayListInfo info) { + List result = new ArrayList<>(); for (final InfoItem stream : info.related_streams) { if (stream instanceof StreamInfoItem) { - result.add(new PlaylistItem((StreamInfoItem) stream)); + result.add(new PlayQueueItem((StreamInfoItem) stream)); } } return result; } - @Override - boolean isComplete() { - return false; - } - - @Override - void load(int index) { - while (streams.size() < index) { - pageNumber.incrementAndGet(); - } - } - - @Override - Observable get(int index) { - return null; - } - private StreamingService getService(final int serviceId) { try { return NewPipe.getService(serviceId); @@ -95,5 +115,4 @@ public class ExternalPlaylist extends Playlist { return null; } } - } diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java new file mode 100644 index 000000000..ecf9e578f --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueue.java @@ -0,0 +1,42 @@ +package org.schabi.newpipe.playlist; + +import android.support.annotation.NonNull; + +import org.schabi.newpipe.extractor.stream_info.StreamInfo; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import io.reactivex.Maybe; +import io.reactivex.subjects.BehaviorSubject; + +public abstract class PlayQueue { + private final String TAG = "PlayQueue@" + Integer.toHexString(hashCode()); + + final int LOAD_BOUND = 2; + + protected List streams; + private BehaviorSubject> changeBroadcast; + + PlayQueue() { + streams = Collections.synchronizedList(new ArrayList()); + changeBroadcast = BehaviorSubject.create(); + } + + @NonNull + public List getStreams() { + return streams; + } + + public void notifyChange() { + changeBroadcast.onNext(streams); + } + + public abstract boolean isComplete(); + + public abstract void load(int index, boolean loadNeighbors); + + public abstract Maybe get(int index); +} + diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistAdapter.java b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java similarity index 63% rename from app/src/main/java/org/schabi/newpipe/playlist/PlaylistAdapter.java rename to app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java index 6f6c924d7..662f9f2f1 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueAdapter.java @@ -1,6 +1,5 @@ package org.schabi.newpipe.playlist; -import android.app.Activity; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; @@ -10,7 +9,6 @@ import android.view.ViewGroup; import org.schabi.newpipe.R; import org.schabi.newpipe.info_list.StreamInfoItemHolder; -import java.util.ArrayList; import java.util.List; /** @@ -33,11 +31,11 @@ import java.util.List; * along with NewPipe. If not, see . */ -public class PlaylistAdapter extends RecyclerView.Adapter { - private static final String TAG = PlaylistAdapter.class.toString(); +public class PlayQueueAdapter extends RecyclerView.Adapter { + private static final String TAG = PlayQueueAdapter.class.toString(); private final PlaylistItemBuilder playlistItemBuilder; - private final List playlistItems; + private final PlayQueue playQueue; private boolean showFooter = false; private View header = null; private View footer = null; @@ -55,34 +53,60 @@ public class PlaylistAdapter extends RecyclerView.Adapter data) { - playlistItemBuilder = new PlaylistItemBuilder(); - playlistItems = data; + public PlayQueueAdapter(PlayQueue playQueue) { + this.playlistItemBuilder = new PlaylistItemBuilder(); + this.playQueue = playQueue; } public void setSelectedListener(PlaylistItemBuilder.OnSelectedListener listener) { playlistItemBuilder.setOnSelectedListener(listener); } - public void addInfoItemList(List data) { + public void addItems(List data) { if(data != null) { - playlistItems.addAll(data); - notifyDataSetChanged(); + playQueue.getStreams().addAll(data); + notifyPlaylistChange(); } } - public void addInfoItem(PlaylistItem data) { + public void addItem(PlayQueueItem data) { if (data != null) { - playlistItems.add(data); - notifyDataSetChanged(); + playQueue.getStreams().add(data); + notifyPlaylistChange(); } } - public void clearStreamItemList() { - if(playlistItems.isEmpty()) { + public void removeItem(int index) { + if (index < playQueue.getStreams().size()) { + playQueue.getStreams().remove(index); + notifyPlaylistChange(); + } + } + + public void swapItems(int source, int target) { + final List items = playQueue.getStreams(); + if (source < items.size() && target < items.size()) { + final PlayQueueItem sourceItem = items.get(source); + final PlayQueueItem targetItem = items.get(target); + + items.set(target, sourceItem); + items.set(source, targetItem); + + notifyPlaylistChange(); + } + } + + public void clear() { + if(playQueue.getStreams().isEmpty()) { return; } - playlistItems.clear(); + playQueue.getStreams().clear(); + + notifyPlaylistChange(); + } + + private void notifyPlaylistChange() { + playQueue.notifyChange(); notifyDataSetChanged(); } @@ -96,13 +120,13 @@ public class PlaylistAdapter extends RecyclerView.Adapter getItemsList() { - return playlistItems; + public List getItems() { + return playQueue.getStreams(); } @Override public int getItemCount() { - int count = playlistItems.size(); + int count = playQueue.getStreams().size(); if(header != null) count++; if(footer != null && showFooter) count++; return count; @@ -116,7 +140,7 @@ public class PlaylistAdapter extends RecyclerView.Adapter stream; - public PlaylistItem(final StreamInfoItem streamInfoItem) { + public PlayQueueItem(final StreamInfoItem streamInfoItem) { this.title = streamInfoItem.getTitle(); this.url = streamInfoItem.getLink(); this.serviceId = streamInfoItem.service_id; diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueItemHolder.java similarity index 93% rename from app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemHolder.java rename to app/src/main/java/org/schabi/newpipe/playlist/PlayQueueItemHolder.java index d1251c535..c25210ee2 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlayQueueItemHolder.java @@ -29,12 +29,12 @@ import org.schabi.newpipe.info_list.InfoItemHolder; * along with NewPipe. If not, see . */ -public class PlaylistItemHolder extends RecyclerView.ViewHolder { +public class PlayQueueItemHolder extends RecyclerView.ViewHolder { public final TextView itemVideoTitleView, itemDurationView; public final View itemRoot; - public PlaylistItemHolder(View v) { + public PlayQueueItemHolder(View v) { super(v); itemRoot = v.findViewById(R.id.itemRoot); itemVideoTitleView = (TextView) v.findViewById(R.id.itemVideoTitleView); diff --git a/app/src/main/java/org/schabi/newpipe/playlist/Playlist.java b/app/src/main/java/org/schabi/newpipe/playlist/Playlist.java deleted file mode 100644 index 02faaa755..000000000 --- a/app/src/main/java/org/schabi/newpipe/playlist/Playlist.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.schabi.newpipe.playlist; - -import android.support.annotation.NonNull; - -import org.schabi.newpipe.extractor.stream_info.StreamInfo; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import io.reactivex.Observable; -import io.reactivex.subjects.PublishSubject; - -public abstract class Playlist { - private final String TAG = "Playlist@" + Integer.toHexString(hashCode()); - - private final int LOAD_BOUND = 2; - - List streams; - PublishSubject> changeBroadcast; - - Playlist() { - streams = Collections.synchronizedList(new ArrayList()); - changeBroadcast = PublishSubject.create(); - } - - @NonNull - public PublishSubject> getChangeBroadcast() { - return changeBroadcast; - } - - abstract boolean isComplete(); - - abstract void load(int index); - - abstract Observable get(int index); -} - diff --git a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemBuilder.java b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemBuilder.java index 1a74240ce..829f502ab 100644 --- a/app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/playlist/PlaylistItemBuilder.java @@ -1,48 +1,14 @@ package org.schabi.newpipe.playlist; -import android.content.Context; import android.text.TextUtils; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.nostra13.universalimageloader.core.DisplayImageOptions; -import com.nostra13.universalimageloader.core.ImageLoader; - -import org.schabi.newpipe.ImageErrorLoadingListener; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.AbstractStreamInfo; -import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.extractor.channel.ChannelInfoItem; -import org.schabi.newpipe.extractor.playlist.PlayListInfoItem; -import org.schabi.newpipe.extractor.stream_info.StreamInfoItem; -import org.schabi.newpipe.info_list.ChannelInfoItemHolder; -import org.schabi.newpipe.info_list.InfoItemHolder; -import org.schabi.newpipe.info_list.PlaylistInfoItemHolder; -import org.schabi.newpipe.info_list.StreamInfoItemHolder; import java.util.Locale; -/** - * Created by Christian Schabesberger on 26.09.16. - *

- * Copyright (C) Christian Schabesberger 2016 - * InfoItemBuilder.java is part of NewPipe. - *

- * NewPipe is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - *

- * NewPipe is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - *

- * You should have received a copy of the GNU General Public License - * along with NewPipe. If not, see . - */ public class PlaylistItemBuilder { @@ -60,10 +26,10 @@ public class PlaylistItemBuilder { this.onStreamInfoItemSelectedListener = listener; } - public View buildView(ViewGroup parent, final PlaylistItem item) { + public View buildView(ViewGroup parent, final PlayQueueItem item) { final LayoutInflater inflater = LayoutInflater.from(parent.getContext()); final View itemView = inflater.inflate(R.layout.stream_item, parent, false); - final PlaylistItemHolder holder = new PlaylistItemHolder(itemView); + final PlayQueueItemHolder holder = new PlayQueueItemHolder(itemView); buildStreamInfoItem(holder, item); @@ -71,7 +37,7 @@ public class PlaylistItemBuilder { } - public void buildStreamInfoItem(PlaylistItemHolder holder, final PlaylistItem item) { + public void buildStreamInfoItem(PlayQueueItemHolder holder, final PlayQueueItem item) { if (!TextUtils.isEmpty(item.getTitle())) holder.itemVideoTitleView.setText(item.getTitle()); if (item.getDuration() > 0) {