changed when video segments are queried
this should fix issues with the background/pop-up player and download dialog
This commit is contained in:
parent
ea39cb868f
commit
8011192dd3
6 changed files with 116 additions and 92 deletions
|
@ -101,7 +101,6 @@ import org.schabi.newpipe.util.PermissionHelper;
|
|||
import org.schabi.newpipe.util.ShareUtils;
|
||||
import org.schabi.newpipe.util.SponsorBlockUtils;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
import org.schabi.newpipe.util.VideoSegment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
@ -160,8 +159,12 @@ public final class VideoDetailFragment
|
|||
private boolean showRelatedStreams;
|
||||
private boolean showDescription;
|
||||
private String selectedTabTag;
|
||||
@AttrRes @NonNull final List<Integer> tabIcons = new ArrayList<>();
|
||||
@StringRes @NonNull final List<Integer> tabContentDescriptions = new ArrayList<>();
|
||||
@AttrRes
|
||||
@NonNull
|
||||
final List<Integer> tabIcons = new ArrayList<>();
|
||||
@StringRes
|
||||
@NonNull
|
||||
final List<Integer> tabContentDescriptions = new ArrayList<>();
|
||||
private boolean tabSettingsChanged = false;
|
||||
private int lastAppBarVerticalOffset = Integer.MAX_VALUE; // prevents useless updates
|
||||
|
||||
|
@ -187,12 +190,13 @@ public final class VideoDetailFragment
|
|||
private final CompositeDisposable disposables = new CompositeDisposable();
|
||||
@Nullable
|
||||
private Disposable positionSubscriber = null;
|
||||
@Nullable
|
||||
private Disposable videoSegmentsSubscriber = null;
|
||||
|
||||
private List<VideoStream> sortedVideoStreams;
|
||||
private int selectedVideoStreamIndex = -1;
|
||||
private BottomSheetBehavior<FrameLayout> bottomSheetBehavior;
|
||||
private BroadcastReceiver broadcastReceiver;
|
||||
private VideoSegment[] videoSegments;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
|
@ -379,6 +383,9 @@ public final class VideoDetailFragment
|
|||
if (positionSubscriber != null) {
|
||||
positionSubscriber.dispose();
|
||||
}
|
||||
if (videoSegmentsSubscriber != null) {
|
||||
videoSegmentsSubscriber.dispose();
|
||||
}
|
||||
if (currentWorker != null) {
|
||||
currentWorker.dispose();
|
||||
}
|
||||
|
@ -678,8 +685,8 @@ public final class VideoDetailFragment
|
|||
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
animate(binding.touchAppendDetail, true, 250, AnimationType.ALPHA,
|
||||
0, () ->
|
||||
animate(binding.touchAppendDetail, false, 1500,
|
||||
AnimationType.ALPHA, 1000));
|
||||
animate(binding.touchAppendDetail, false, 1500,
|
||||
AnimationType.ALPHA, 1000));
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
@ -887,43 +894,7 @@ public final class VideoDetailFragment
|
|||
|
||||
private void runWorker(final boolean forceLoad, final boolean addToBackStack) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||
|
||||
final String apiUrl = prefs.getString(getContext()
|
||||
.getString(R.string.sponsor_block_api_url_key), null);
|
||||
final boolean isSponsorBlockEnabled = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_enable_key), false);
|
||||
final boolean includeSponsorCategory = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_category_sponsor_key), false);
|
||||
final boolean includeIntroCategory = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_category_intro_key), false);
|
||||
final boolean includeOutroCategory = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_category_outro_key), false);
|
||||
final boolean includeInteractionCategory = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_category_interaction_key), false);
|
||||
final boolean includeSelfPromoCategory = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_category_self_promo_key), false);
|
||||
final boolean includeMusicCategory = prefs.getBoolean(getContext()
|
||||
.getString(R.string.sponsor_block_category_non_music_key), false);
|
||||
|
||||
currentWorker = ExtractorHelper.getStreamInfo(serviceId, url, forceLoad)
|
||||
.flatMap(streamInfo -> Single.fromCallable(() -> {
|
||||
if (isSponsorBlockEnabled
|
||||
&& streamInfo.getUrl().startsWith("https://www.youtube.com")
|
||||
&& apiUrl != null
|
||||
&& !apiUrl.isEmpty()) {
|
||||
this.videoSegments = SponsorBlockUtils.getYouTubeVideoSegments(
|
||||
apiUrl,
|
||||
streamInfo.getId(),
|
||||
includeSponsorCategory,
|
||||
includeIntroCategory,
|
||||
includeOutroCategory,
|
||||
includeInteractionCategory,
|
||||
includeSelfPromoCategory,
|
||||
includeMusicCategory);
|
||||
}
|
||||
|
||||
return streamInfo;
|
||||
}))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(result -> {
|
||||
|
@ -1182,7 +1153,6 @@ public final class VideoDetailFragment
|
|||
playerService.getView().setVisibility(View.GONE);
|
||||
}
|
||||
addVideoPlayerView();
|
||||
playerService.setVideoSegments(videoSegments);
|
||||
|
||||
final Intent playerIntent = NavigationHelper
|
||||
.getPlayerIntent(requireContext(), MainPlayer.class, queue, true, autoPlayEnabled);
|
||||
|
@ -1634,29 +1604,43 @@ public final class VideoDetailFragment
|
|||
}
|
||||
|
||||
public void openDownloadDialog() {
|
||||
try {
|
||||
final DownloadDialog downloadDialog = DownloadDialog.newInstance(currentInfo);
|
||||
downloadDialog.setVideoStreams(sortedVideoStreams);
|
||||
downloadDialog.setAudioStreams(currentInfo.getAudioStreams());
|
||||
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
||||
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
|
||||
downloadDialog.setVideoSegments(videoSegments);
|
||||
videoSegmentsSubscriber = Single.fromCallable(() -> {
|
||||
try {
|
||||
return SponsorBlockUtils.getYouTubeVideoSegments(getContext(), currentInfo);
|
||||
} catch (final Exception e) {
|
||||
// TODO: handle
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(videoSegments -> {
|
||||
try {
|
||||
final DownloadDialog downloadDialog =
|
||||
DownloadDialog.newInstance(currentInfo);
|
||||
downloadDialog.setVideoStreams(sortedVideoStreams);
|
||||
downloadDialog.setAudioStreams(currentInfo.getAudioStreams());
|
||||
downloadDialog.setSelectedVideoStream(selectedVideoStreamIndex);
|
||||
downloadDialog.setSubtitleStreams(currentInfo.getSubtitles());
|
||||
downloadDialog.setVideoSegments(videoSegments);
|
||||
|
||||
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
||||
} catch (final Exception e) {
|
||||
final ErrorInfo info = ErrorInfo.make(UserAction.UI_ERROR,
|
||||
ServiceList.all()
|
||||
.get(currentInfo
|
||||
.getServiceId())
|
||||
.getServiceInfo()
|
||||
.getName(), "",
|
||||
R.string.could_not_setup_download_menu);
|
||||
downloadDialog.show(
|
||||
activity.getSupportFragmentManager(), "downloadDialog");
|
||||
} catch (final Exception e) {
|
||||
final ErrorInfo info = ErrorInfo.make(UserAction.UI_ERROR,
|
||||
ServiceList.all()
|
||||
.get(currentInfo
|
||||
.getServiceId())
|
||||
.getServiceInfo()
|
||||
.getName(), "",
|
||||
R.string.could_not_setup_download_menu);
|
||||
|
||||
ErrorActivity.reportError(activity,
|
||||
e,
|
||||
activity.getClass(),
|
||||
activity.findViewById(android.R.id.content), info);
|
||||
}
|
||||
ErrorActivity.reportError(activity,
|
||||
e,
|
||||
activity.getClass(),
|
||||
activity.findViewById(android.R.id.content), info);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -37,7 +37,6 @@ import androidx.core.content.ContextCompat;
|
|||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.databinding.PlayerBinding;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
import org.schabi.newpipe.util.VideoSegment;
|
||||
|
||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
|
@ -244,10 +243,6 @@ public final class MainPlayer extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
public void setVideoSegments(final VideoSegment[] videoSegments) {
|
||||
player.setVideoSegments(videoSegments);
|
||||
}
|
||||
|
||||
|
||||
public class LocalBinder extends Binder {
|
||||
|
||||
|
|
|
@ -227,6 +227,7 @@ public final class Player implements
|
|||
public static final String SELECT_ON_APPEND = "select_on_append";
|
||||
public static final String PLAYER_TYPE = "player_type";
|
||||
public static final String IS_MUTED = "is_muted";
|
||||
public static final String VIDEO_SEGMENTS = "video_segments";
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Time constants
|
||||
|
@ -381,7 +382,6 @@ public final class Player implements
|
|||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// SponsorBlock
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
private VideoSegment[] videoSegments;
|
||||
private SponsorBlockMode sponsorBlockMode = SponsorBlockMode.DISABLED;
|
||||
|
||||
|
||||
|
@ -842,7 +842,7 @@ public final class Player implements
|
|||
}
|
||||
|
||||
if (playQueue != null) {
|
||||
playQueueManager = new MediaSourceManager(this, playQueue);
|
||||
playQueueManager = new MediaSourceManager(context, this, playQueue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4223,13 +4223,6 @@ public final class Player implements
|
|||
// SponsorBlock
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
//region
|
||||
public VideoSegment[] getVideoSegments() {
|
||||
return videoSegments;
|
||||
}
|
||||
|
||||
public void setVideoSegments(final VideoSegment[] videoSegments) {
|
||||
this.videoSegments = videoSegments;
|
||||
}
|
||||
|
||||
public void onBlockingSponsorsButtonClicked() {
|
||||
if (DEBUG) {
|
||||
|
@ -4263,6 +4256,7 @@ public final class Player implements
|
|||
}
|
||||
|
||||
public VideoSegment getSkippableSegment(final int progress) {
|
||||
final VideoSegment[] videoSegments = currentItem.getVideoSegments();
|
||||
if (videoSegments == null) {
|
||||
return null;
|
||||
}
|
||||
|
@ -4285,7 +4279,7 @@ public final class Player implements
|
|||
private void markSegments() {
|
||||
binding.playbackSeekBar.clearMarkers();
|
||||
|
||||
final VideoSegment[] segments = getVideoSegments();
|
||||
final VideoSegment[] segments = currentItem.getVideoSegments();
|
||||
|
||||
if (segments == null || segments.length == 0) {
|
||||
return;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.schabi.newpipe.player.playback;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
|
||||
|
@ -23,6 +24,7 @@ import org.schabi.newpipe.player.playqueue.events.PlayQueueEvent;
|
|||
import org.schabi.newpipe.player.playqueue.events.RemoveEvent;
|
||||
import org.schabi.newpipe.player.playqueue.events.ReorderEvent;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.SponsorBlockUtils;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -69,6 +71,8 @@ public class MediaSourceManager {
|
|||
*/
|
||||
private static final int MAXIMUM_LOADER_SIZE = WINDOW_SIZE * 2 + 1;
|
||||
|
||||
@NonNull
|
||||
private final Context context;
|
||||
@NonNull
|
||||
private final PlaybackListener playbackListener;
|
||||
@NonNull
|
||||
|
@ -125,14 +129,16 @@ public class MediaSourceManager {
|
|||
|
||||
private final Handler removeMediaSourceHandler = new Handler();
|
||||
|
||||
public MediaSourceManager(@NonNull final PlaybackListener listener,
|
||||
public MediaSourceManager(@NonNull final Context context,
|
||||
@NonNull final PlaybackListener listener,
|
||||
@NonNull final PlayQueue playQueue) {
|
||||
this(listener, playQueue, 400L,
|
||||
this(context, listener, playQueue, 400L,
|
||||
/*playbackNearEndGapMillis=*/TimeUnit.MILLISECONDS.convert(30, TimeUnit.SECONDS),
|
||||
/*progressUpdateIntervalMillis*/TimeUnit.MILLISECONDS.convert(2, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private MediaSourceManager(@NonNull final PlaybackListener listener,
|
||||
private MediaSourceManager(@NonNull final Context context,
|
||||
@NonNull final PlaybackListener listener,
|
||||
@NonNull final PlayQueue playQueue,
|
||||
final long loadDebounceMillis,
|
||||
final long playbackNearEndGapMillis,
|
||||
|
@ -146,6 +152,7 @@ public class MediaSourceManager {
|
|||
+ " ms] for them to be useful.");
|
||||
}
|
||||
|
||||
this.context = context;
|
||||
this.playbackListener = listener;
|
||||
this.playQueue = playQueue;
|
||||
|
||||
|
@ -428,6 +435,9 @@ public class MediaSourceManager {
|
|||
|
||||
final long expiration = System.currentTimeMillis()
|
||||
+ ServiceHelper.getCacheExpirationMillis(streamInfo.getServiceId());
|
||||
|
||||
stream.setVideoSegments(SponsorBlockUtils.getYouTubeVideoSegments(context, streamInfo));
|
||||
|
||||
return new LoadedMediaSource(source, stream, expiration);
|
||||
}).onErrorReturn(throwable -> new FailedMediaSource(stream,
|
||||
new StreamInfoLoadException(throwable)));
|
||||
|
|
|
@ -7,6 +7,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfo;
|
|||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.util.ExtractorHelper;
|
||||
import org.schabi.newpipe.util.VideoSegment;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
@ -35,6 +36,8 @@ public class PlayQueueItem implements Serializable {
|
|||
private long recoveryPosition;
|
||||
private Throwable error;
|
||||
|
||||
private VideoSegment[] videoSegments;
|
||||
|
||||
PlayQueueItem(@NonNull final StreamInfo info) {
|
||||
this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(),
|
||||
info.getThumbnailUrl(), info.getUploaderName(), info.getStreamType());
|
||||
|
@ -142,4 +145,12 @@ public class PlayQueueItem implements Serializable {
|
|||
public void setAutoQueued(final boolean autoQueued) {
|
||||
isAutoQueued = autoQueued;
|
||||
}
|
||||
|
||||
public VideoSegment[] getVideoSegments() {
|
||||
return videoSegments;
|
||||
}
|
||||
|
||||
public void setVideoSegments(final VideoSegment[] videoSegments) {
|
||||
this.videoSegments = videoSegments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,13 @@ package org.schabi.newpipe.util;
|
|||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonParser;
|
||||
|
@ -13,6 +16,8 @@ import com.grack.nanojson.JsonParser;
|
|||
import org.schabi.newpipe.App;
|
||||
import org.schabi.newpipe.DownloaderImpl;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
|
@ -29,15 +34,40 @@ public final class SponsorBlockUtils {
|
|||
}
|
||||
|
||||
@SuppressWarnings("CheckStyle")
|
||||
public static VideoSegment[] getYouTubeVideoSegments(final String apiUrl,
|
||||
final String videoId,
|
||||
final boolean includeSponsorCategory,
|
||||
final boolean includeIntroCategory,
|
||||
final boolean includeOutroCategory,
|
||||
final boolean includeInteractionCategory,
|
||||
final boolean includeSelfPromoCategory,
|
||||
final boolean includeMusicCategory)
|
||||
public static VideoSegment[] getYouTubeVideoSegments(final Context context,
|
||||
final StreamInfo streamInfo)
|
||||
throws UnsupportedEncodingException {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
final boolean isSponsorBlockEnabled = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_enable_key), false);
|
||||
|
||||
if (!isSponsorBlockEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String apiUrl = prefs.getString(context
|
||||
.getString(R.string.sponsor_block_api_url_key), null);
|
||||
|
||||
if (!streamInfo.getUrl().startsWith("https://www.youtube.com")
|
||||
|| apiUrl == null
|
||||
|| apiUrl.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean includeSponsorCategory = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_category_sponsor_key), false);
|
||||
final boolean includeIntroCategory = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_category_intro_key), false);
|
||||
final boolean includeOutroCategory = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_category_outro_key), false);
|
||||
final boolean includeInteractionCategory = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_category_interaction_key), false);
|
||||
final boolean includeSelfPromoCategory = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_category_self_promo_key), false);
|
||||
final boolean includeMusicCategory = prefs.getBoolean(context
|
||||
.getString(R.string.sponsor_block_category_non_music_key), false);
|
||||
|
||||
final ArrayList<String> categoryParamList = new ArrayList<>();
|
||||
|
||||
if (includeSponsorCategory) {
|
||||
|
@ -66,7 +96,7 @@ public final class SponsorBlockUtils {
|
|||
String categoryParams = "[\"" + TextUtils.join("\",\"", categoryParamList) + "\"]";
|
||||
categoryParams = URLEncoder.encode(categoryParams, "utf-8");
|
||||
|
||||
final String videoIdHash = toSha256(videoId);
|
||||
final String videoIdHash = toSha256(streamInfo.getId());
|
||||
|
||||
if (videoIdHash == null) {
|
||||
return null;
|
||||
|
@ -106,7 +136,7 @@ public final class SponsorBlockUtils {
|
|||
final JsonObject jObj1 = (JsonObject) obj1;
|
||||
|
||||
final String responseVideoId = jObj1.getString("videoID");
|
||||
if (!responseVideoId.equals(videoId)) {
|
||||
if (!responseVideoId.equals(streamInfo.getId())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue