-Added documentations for play queue components.
This commit is contained in:
parent
80f3e3c3b6
commit
c75c2d0f21
8 changed files with 179 additions and 34 deletions
|
|
@ -27,6 +27,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.AudioManager;
|
||||
import android.media.audiofx.AudioEffect;
|
||||
|
|
@ -34,6 +35,7 @@ import android.net.Uri;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
|
|
@ -70,6 +72,7 @@ import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvicto
|
|||
import com.google.android.exoplayer2.upstream.cache.SimpleCache;
|
||||
import com.google.android.exoplayer2.util.Util;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.ImageSize;
|
||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||
|
||||
import org.schabi.newpipe.Downloader;
|
||||
|
|
|
|||
|
|
@ -64,7 +64,6 @@ import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
|||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.player.old.PlayVideoActivity;
|
||||
import org.schabi.newpipe.player.playback.MediaSourceManager;
|
||||
import org.schabi.newpipe.playlist.PlayQueueItem;
|
||||
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.UserAction;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ import org.schabi.newpipe.extractor.MediaFormat;
|
|||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
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;
|
||||
|
|
@ -395,20 +396,25 @@ public abstract class VideoPlayer extends BasePlayer implements SimpleExoPlayer.
|
|||
final Format format = group.getFormat(trackIndex);
|
||||
final boolean isSetCurrent = selectedTrackGroup.indexOf(format) != -1;
|
||||
|
||||
// If the source is extracted (e.g. mp4), then we use the resolution contained in the stream
|
||||
if (group.length == 1 && videoTrackGroups.length == availableStreams.size()) {
|
||||
popupMenu.getMenu().add(qualityPopupMenuGroupId, acc, Menu.NONE, MediaFormat.getNameById(stream.format) + " " + stream.resolution + " (" + format.width + "x" + format.height + ")");
|
||||
// If the source is non-adaptive (extractor source), then we use the resolution contained in the stream
|
||||
if (isSetCurrent) qualityTextView.setText(stream.resolution);
|
||||
|
||||
final String menuItem = MediaFormat.getNameById(stream.format) + " " +
|
||||
stream.resolution + " (" + format.width + "x" + format.height + ")";
|
||||
popupMenu.getMenu().add(qualityPopupMenuGroupId, acc, Menu.NONE, menuItem);
|
||||
} else {
|
||||
// Otherwise, we have a DASH source, which contains multiple formats and
|
||||
// Otherwise, we have an adaptive source, which contains multiple formats and
|
||||
// thus have no inherent quality format
|
||||
if (isSetCurrent) qualityTextView.setText(resolutionStringOf(format));
|
||||
|
||||
final MediaFormat mediaFormat = MediaFormat.getFromMimeType(format.sampleMimeType);
|
||||
final String mediaName = mediaFormat == null ? format.sampleMimeType : mediaFormat.name;
|
||||
|
||||
final String resolution = resolutionStringOf(format);
|
||||
popupMenu.getMenu().add(qualityPopupMenuGroupId, acc, Menu.NONE, mediaName + " " + resolution);
|
||||
if (isSetCurrent) qualityTextView.setText(resolution);
|
||||
final String menuItem = mediaName + " " + format.width + "x" + format.height;
|
||||
popupMenu.getMenu().add(qualityPopupMenuGroupId, acc, Menu.NONE, menuItem);
|
||||
}
|
||||
|
||||
trackGroupInfos.add(new TrackGroupInfo(trackIndex, groupIndex, MediaFormat.getNameById(stream.format), stream.resolution, format));
|
||||
acc++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,15 @@ import io.reactivex.disposables.Disposable;
|
|||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* DeferredMediaSource is specifically designed to allow external control over when
|
||||
* the source metadata are loaded while being compatible with ExoPlayer's playlists.
|
||||
*
|
||||
* This media source follows the structure of how NewPipeExtractor's
|
||||
* {@link org.schabi.newpipe.extractor.stream.StreamInfoItem} is converted into
|
||||
* {@link org.schabi.newpipe.extractor.stream.StreamInfo}. Once conversion is complete,
|
||||
* this media source behaves identically as any other native media sources.
|
||||
* */
|
||||
public final class DeferredMediaSource implements MediaSource {
|
||||
private final String TAG = "DeferredMediaSource@" + Integer.toHexString(hashCode());
|
||||
|
||||
|
|
@ -30,6 +39,9 @@ public final class DeferredMediaSource implements MediaSource {
|
|||
public final static int STATE_DISPOSED = 3;
|
||||
|
||||
public interface Callback {
|
||||
/**
|
||||
* Player-specific MediaSource resolution from given StreamInfo.
|
||||
* */
|
||||
MediaSource sourceOf(final StreamInfo info);
|
||||
}
|
||||
|
||||
|
|
@ -51,6 +63,9 @@ public final class DeferredMediaSource implements MediaSource {
|
|||
this.state = STATE_INIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parameters are kept in the class for delayed preparation.
|
||||
* */
|
||||
@Override
|
||||
public void prepareSource(ExoPlayer exoPlayer, boolean isTopLevelSource, Listener listener) {
|
||||
this.exoPlayer = exoPlayer;
|
||||
|
|
@ -62,6 +77,17 @@ public final class DeferredMediaSource implements MediaSource {
|
|||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Externally controlled loading. This method fully prepares the source to be used
|
||||
* like any other native MediaSource.
|
||||
*
|
||||
* Ideally, this should be called after this source has entered PREPARED state and
|
||||
* called once only.
|
||||
*
|
||||
* If loading fails here, an error will be propagated out and result in a
|
||||
* {@link com.google.android.exoplayer2.ExoPlaybackException}, which is delegated
|
||||
* out to the player.
|
||||
* */
|
||||
public synchronized void load() {
|
||||
if (state != STATE_PREPARED || stream == null || loader != null) return;
|
||||
Log.d(TAG, "Loading: [" + stream.getTitle() + "] with url: " + stream.getUrl());
|
||||
|
|
|
|||
|
|
@ -60,22 +60,37 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
|||
.subscribe(getReactor());
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// DeferredMediaSource listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public MediaSource sourceOf(StreamInfo info) {
|
||||
return playbackListener.sourceOf(info);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Exposed Methods
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/*
|
||||
* Returns the media source index of the currently playing stream.
|
||||
* */
|
||||
/**
|
||||
* Returns the media source index of the currently playing stream.
|
||||
* */
|
||||
public int getCurrentSourceIndex() {
|
||||
return sourceToQueueIndex.indexOf(playQueue.getIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the play queue index of a given media source playlist index.
|
||||
* */
|
||||
public int getQueueIndexOf(final int sourceIndex) {
|
||||
if (sourceIndex < 0 || sourceIndex >= sourceToQueueIndex.size()) return -1;
|
||||
return sourceToQueueIndex.get(sourceIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispose the manager and releases all message buses and loaders.
|
||||
* */
|
||||
public void dispose() {
|
||||
if (playQueueReactor != null) playQueueReactor.cancel();
|
||||
if (syncReactor != null) syncReactor.dispose();
|
||||
|
|
@ -90,6 +105,9 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
|||
playQueue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the current playing stream and the streams within its WINDOW_SIZE bound.
|
||||
* */
|
||||
public void load() {
|
||||
// The current item has higher priority
|
||||
final int currentIndex = playQueue.getIndex();
|
||||
|
|
@ -140,6 +158,7 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
|||
remove(removeEvent.index());
|
||||
break;
|
||||
}
|
||||
// Reset the sources if the index to remove is the current playing index
|
||||
case INIT:
|
||||
case REORDER:
|
||||
tryBlock();
|
||||
|
|
@ -249,8 +268,12 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
|||
// Media Source List Manipulation
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
// Insert source into playlist with position in respect to the play queue
|
||||
// If the play queue index already exists, then the insert is ignored
|
||||
/**
|
||||
* Inserts a source into {@link DynamicConcatenatingMediaSource} with position
|
||||
* in respect to the play queue.
|
||||
*
|
||||
* If the play queue index already exists, then the insert is ignored.
|
||||
* */
|
||||
private void insert(final int queueIndex, final DeferredMediaSource source) {
|
||||
if (queueIndex < 0) return;
|
||||
|
||||
|
|
@ -262,6 +285,11 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a source from {@link DynamicConcatenatingMediaSource} with the given play queue index.
|
||||
*
|
||||
* If the play queue index does not exist, the removal is ignored.
|
||||
* */
|
||||
private void remove(final int queueIndex) {
|
||||
if (queueIndex < 0) return;
|
||||
|
||||
|
|
@ -276,9 +304,4 @@ public class MediaSourceManager implements DeferredMediaSource.Callback {
|
|||
sourceToQueueIndex.set(i, sourceToQueueIndex.get(i) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaSource sourceOf(StreamInfo info) {
|
||||
return playbackListener.sourceOf(info);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue