Merge branch 'TeamNewPipe:dev' into feature-7870
This commit is contained in:
commit
813f55152a
6 changed files with 53 additions and 30 deletions
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
@ -68,7 +68,7 @@ The [checkStyle](https://github.com/checkstyle/checkstyle) plugin verifies that
|
||||||
- Go to `File -> Settings -> Plugins`, search for `checkstyle` and install `CheckStyle-IDEA`.
|
- Go to `File -> Settings -> Plugins`, search for `checkstyle` and install `CheckStyle-IDEA`.
|
||||||
- Go to `File -> Settings -> Tools -> Checkstyle`.
|
- Go to `File -> Settings -> Tools -> Checkstyle`.
|
||||||
- Add NewPipe's configuration file by clicking the `+` in the right toolbar of the "Configuration File" list.
|
- Add NewPipe's configuration file by clicking the `+` in the right toolbar of the "Configuration File" list.
|
||||||
- Under the "Use a local Checkstyle file" bullet, click on `Browse` and pick the file named `checkstyle.xml` in the project's root folder.
|
- Under the "Use a local Checkstyle file" bullet, click on `Browse` and, enter `checkstyle` folder under the project's root path and pick the file named `checkstyle.xml`.
|
||||||
- Enable "Store relative to project location" so that moving the directory around does not create issues.
|
- Enable "Store relative to project location" so that moving the directory around does not create issues.
|
||||||
- Insert a description in the top bar, then click `Next` and then `Finish`.
|
- Insert a description in the top bar, then click `Next` and then `Finish`.
|
||||||
- Activate the configuration file you just added by enabling the checkbox on the left.
|
- Activate the configuration file you just added by enabling the checkbox on the left.
|
||||||
|
|
|
@ -33,8 +33,16 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
|
||||||
|
|
||||||
private final CompositeDisposable playlistDisposables = new CompositeDisposable();
|
private final CompositeDisposable playlistDisposables = new CompositeDisposable();
|
||||||
|
|
||||||
public PlaylistAppendDialog(final List<StreamEntity> streamEntities) {
|
/**
|
||||||
super(streamEntities);
|
* Create a new instance of {@link PlaylistAppendDialog}.
|
||||||
|
*
|
||||||
|
* @param streamEntities a list of {@link StreamEntity} to be added to playlists
|
||||||
|
* @return a new instance of {@link PlaylistAppendDialog}
|
||||||
|
*/
|
||||||
|
public static PlaylistAppendDialog newInstance(final List<StreamEntity> streamEntities) {
|
||||||
|
final PlaylistAppendDialog dialog = new PlaylistAppendDialog();
|
||||||
|
dialog.setStreamEntities(streamEntities);
|
||||||
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -103,13 +111,14 @@ public final class PlaylistAppendDialog extends PlaylistDialog {
|
||||||
// Helper
|
// Helper
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
/** Display create playlist dialog. */
|
||||||
public void openCreatePlaylistDialog() {
|
public void openCreatePlaylistDialog() {
|
||||||
if (getStreamEntities() == null || !isAdded()) {
|
if (getStreamEntities() == null || !isAdded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final PlaylistCreationDialog playlistCreationDialog =
|
final PlaylistCreationDialog playlistCreationDialog =
|
||||||
new PlaylistCreationDialog(getStreamEntities());
|
PlaylistCreationDialog.newInstance(getStreamEntities());
|
||||||
// Move the dismissListener to the new dialog.
|
// Move the dismissListener to the new dialog.
|
||||||
playlistCreationDialog.setOnDismissListener(this.getOnDismissListener());
|
playlistCreationDialog.setOnDismissListener(this.getOnDismissListener());
|
||||||
this.setOnDismissListener(null);
|
this.setOnDismissListener(null);
|
||||||
|
|
|
@ -21,8 +21,17 @@ import java.util.List;
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||||
|
|
||||||
public final class PlaylistCreationDialog extends PlaylistDialog {
|
public final class PlaylistCreationDialog extends PlaylistDialog {
|
||||||
public PlaylistCreationDialog(final List<StreamEntity> streamEntities) {
|
|
||||||
super(streamEntities);
|
/**
|
||||||
|
* Create a new instance of {@link PlaylistCreationDialog}.
|
||||||
|
*
|
||||||
|
* @param streamEntities a list of {@link StreamEntity} to be added to playlists
|
||||||
|
* @return a new instance of {@link PlaylistCreationDialog}
|
||||||
|
*/
|
||||||
|
public static PlaylistCreationDialog newInstance(final List<StreamEntity> streamEntities) {
|
||||||
|
final PlaylistCreationDialog dialog = new PlaylistCreationDialog();
|
||||||
|
dialog.setStreamEntities(streamEntities);
|
||||||
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -31,10 +31,6 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave
|
||||||
|
|
||||||
private org.schabi.newpipe.util.SavedState savedState;
|
private org.schabi.newpipe.util.SavedState savedState;
|
||||||
|
|
||||||
public PlaylistDialog(final List<StreamEntity> streamEntities) {
|
|
||||||
this.streamEntities = streamEntities;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// LifeCycle
|
// LifeCycle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -120,6 +116,10 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave
|
||||||
this.onDismissListener = onDismissListener;
|
this.onDismissListener = onDismissListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setStreamEntities(final List<StreamEntity> streamEntities) {
|
||||||
|
this.streamEntities = streamEntities;
|
||||||
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Dialog creation
|
// Dialog creation
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@ -143,8 +143,8 @@ public abstract class PlaylistDialog extends DialogFragment implements StateSave
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(hasPlaylists ->
|
.subscribe(hasPlaylists ->
|
||||||
onExec.accept(hasPlaylists
|
onExec.accept(hasPlaylists
|
||||||
? new PlaylistAppendDialog(streamEntities)
|
? PlaylistAppendDialog.newInstance(streamEntities)
|
||||||
: new PlaylistCreationDialog(streamEntities))
|
: PlaylistCreationDialog.newInstance(streamEntities))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ import androidx.appcompat.content.res.AppCompatResources;
|
||||||
import androidx.appcompat.view.ContextThemeWrapper;
|
import androidx.appcompat.view.ContextThemeWrapper;
|
||||||
import androidx.appcompat.widget.AppCompatImageButton;
|
import androidx.appcompat.widget.AppCompatImageButton;
|
||||||
import androidx.appcompat.widget.PopupMenu;
|
import androidx.appcompat.widget.PopupMenu;
|
||||||
|
import androidx.collection.ArraySet;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.GestureDetectorCompat;
|
import androidx.core.view.GestureDetectorCompat;
|
||||||
|
@ -4217,21 +4218,21 @@ public final class Player implements
|
||||||
// in livestreams) so we will be not able to execute the block below.
|
// in livestreams) so we will be not able to execute the block below.
|
||||||
// Reload the play queue manager in this case, which is the behavior when we don't know the
|
// Reload the play queue manager in this case, which is the behavior when we don't know the
|
||||||
// index of the video renderer or playQueueManagerReloadingNeeded returns true.
|
// index of the video renderer or playQueueManagerReloadingNeeded returns true.
|
||||||
if (!getCurrentStreamInfo().isPresent()) {
|
final Optional<StreamInfo> optCurrentStreamInfo = getCurrentStreamInfo();
|
||||||
|
if (!optCurrentStreamInfo.isPresent()) {
|
||||||
reloadPlayQueueManager();
|
reloadPlayQueueManager();
|
||||||
setRecovery();
|
setRecovery();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int videoRenderIndex = getVideoRendererIndex();
|
final StreamInfo info = optCurrentStreamInfo.get();
|
||||||
final StreamInfo info = getCurrentStreamInfo().get();
|
|
||||||
|
|
||||||
// In the case we don't know the source type, fallback to the one with video with audio or
|
// In the case we don't know the source type, fallback to the one with video with audio or
|
||||||
// audio-only source.
|
// audio-only source.
|
||||||
final SourceType sourceType = videoResolver.getStreamSourceType().orElse(
|
final SourceType sourceType = videoResolver.getStreamSourceType().orElse(
|
||||||
SourceType.VIDEO_WITH_AUDIO_OR_AUDIO_ONLY);
|
SourceType.VIDEO_WITH_AUDIO_OR_AUDIO_ONLY);
|
||||||
|
|
||||||
if (playQueueManagerReloadingNeeded(sourceType, info, videoRenderIndex)) {
|
if (playQueueManagerReloadingNeeded(sourceType, info, getVideoRendererIndex())) {
|
||||||
reloadPlayQueueManager();
|
reloadPlayQueueManager();
|
||||||
} else {
|
} else {
|
||||||
final StreamType streamType = info.getStreamType();
|
final StreamType streamType = info.getStreamType();
|
||||||
|
@ -4242,19 +4243,22 @@ public final class Player implements
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final TrackGroupArray videoTrackGroupArray = Objects.requireNonNull(
|
final DefaultTrackSelector.ParametersBuilder parametersBuilder =
|
||||||
trackSelector.getCurrentMappedTrackInfo()).getTrackGroups(videoRenderIndex);
|
trackSelector.buildUponParameters();
|
||||||
|
|
||||||
if (videoEnabled) {
|
if (videoEnabled) {
|
||||||
// Clearing the null selection override enable again the video stream (and its
|
// Enable again the video track and the subtitles, if there is one selected
|
||||||
// fetching).
|
parametersBuilder.setDisabledTrackTypes(Collections.emptySet());
|
||||||
trackSelector.setParameters(trackSelector.buildUponParameters()
|
|
||||||
.clearSelectionOverride(videoRenderIndex, videoTrackGroupArray));
|
|
||||||
} else {
|
} else {
|
||||||
// Using setRendererDisabled still fetch the video stream in background, contrary
|
// Disable the video track and the ability to select subtitles
|
||||||
// to setSelectionOverride with a null override.
|
// Use an ArraySet because we can't use Set.of() on all supported APIs by the app
|
||||||
trackSelector.setParameters(trackSelector.buildUponParameters()
|
final ArraySet<Integer> disabledTracks = new ArraySet<>();
|
||||||
.setSelectionOverride(videoRenderIndex, videoTrackGroupArray, null));
|
disabledTracks.add(C.TRACK_TYPE_TEXT);
|
||||||
|
disabledTracks.add(C.TRACK_TYPE_VIDEO);
|
||||||
|
parametersBuilder.setDisabledTrackTypes(disabledTracks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackSelector.setParameters(parametersBuilder);
|
||||||
}
|
}
|
||||||
|
|
||||||
setRecovery();
|
setRecovery();
|
||||||
|
|
|
@ -54,6 +54,7 @@ public final class SparseItemUtil {
|
||||||
// if the duration is >= 0 (provided that the item is not a livestream) and there is an
|
// if the duration is >= 0 (provided that the item is not a livestream) and there is an
|
||||||
// uploader url, probably all info is already there, so there is no need to fetch it
|
// uploader url, probably all info is already there, so there is no need to fetch it
|
||||||
callback.accept(new SinglePlayQueue(item));
|
callback.accept(new SinglePlayQueue(item));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// either the duration or the uploader url are not available, so fetch more info
|
// either the duration or the uploader url are not available, so fetch more info
|
||||||
|
@ -80,12 +81,12 @@ public final class SparseItemUtil {
|
||||||
@NonNull final String url,
|
@NonNull final String url,
|
||||||
@Nullable final String uploaderUrl,
|
@Nullable final String uploaderUrl,
|
||||||
@NonNull final Consumer<String> callback) {
|
@NonNull final Consumer<String> callback) {
|
||||||
if (isNullOrEmpty(uploaderUrl)) {
|
if (!isNullOrEmpty(uploaderUrl)) {
|
||||||
fetchStreamInfoAndSaveToDatabase(context, serviceId, url,
|
|
||||||
streamInfo -> callback.accept(streamInfo.getUploaderUrl()));
|
|
||||||
} else {
|
|
||||||
callback.accept(uploaderUrl);
|
callback.accept(uploaderUrl);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
fetchStreamInfoAndSaveToDatabase(context, serviceId, url,
|
||||||
|
streamInfo -> callback.accept(streamInfo.getUploaderUrl()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue