mirror of
https://github.com/inotia00/revanced-patches.git
synced 2025-04-29 22:24:31 +02:00
fix(YouTube - Video playback): Overridden to default playback speed in onResume
callback https://github.com/inotia00/ReVanced_Extended/issues/2896
This commit is contained in:
parent
457dbfec6c
commit
64af7fd8b6
@ -3,10 +3,14 @@ package app.revanced.extension.youtube.patches.video;
|
||||
import static app.revanced.extension.shared.utils.StringRef.str;
|
||||
import static app.revanced.extension.youtube.shared.RootView.isShortsActive;
|
||||
|
||||
import androidx.annotation.GuardedBy;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import app.revanced.extension.shared.settings.BooleanSetting;
|
||||
import app.revanced.extension.shared.settings.FloatSetting;
|
||||
import app.revanced.extension.shared.utils.Logger;
|
||||
@ -28,48 +32,61 @@ public class PlaybackSpeedPatch {
|
||||
Settings.DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC.get();
|
||||
private static final long TOAST_DELAY_MILLISECONDS = 750;
|
||||
private static long lastTimeSpeedChanged;
|
||||
|
||||
/**
|
||||
* The last used playback speed.
|
||||
* This value is used when the default playback speed is 'Auto'.
|
||||
*/
|
||||
private static float lastSelectedPlaybackSpeed = 1.0f;
|
||||
private static float lastSelectedShortsPlaybackSpeed = 1.0f;
|
||||
|
||||
private static volatile String channelId = "";
|
||||
private static volatile String videoId = "";
|
||||
private static boolean isLiveStream;
|
||||
/**
|
||||
* The last regular video id.
|
||||
*/
|
||||
private static String videoId = "";
|
||||
|
||||
private static volatile String channelIdShorts = "";
|
||||
private static volatile String videoIdShorts = "";
|
||||
private static boolean isLiveStreamShorts;
|
||||
@GuardedBy("itself")
|
||||
private static final Map<String, Float> ignoredPlaybackSpeedVideoIds = new LinkedHashMap<>() {
|
||||
private static final int NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK = 3;
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry eldest) {
|
||||
return size() > NUMBER_OF_LAST_VIDEO_IDS_TO_TRACK;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* This method is used to reset the playback speed to 1.0 when a general video is started, whether it is a live stream, music, or whitelist.
|
||||
*/
|
||||
public static void newVideoStarted(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName,
|
||||
@NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle,
|
||||
final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) {
|
||||
if (isShortsActive()) {
|
||||
channelIdShorts = newlyLoadedChannelId;
|
||||
videoIdShorts = newlyLoadedVideoId;
|
||||
isLiveStreamShorts = newlyLoadedLiveStreamValue;
|
||||
|
||||
Logger.printDebug(() -> "newVideoStarted: " + newlyLoadedVideoId);
|
||||
} else {
|
||||
channelId = newlyLoadedChannelId;
|
||||
return;
|
||||
}
|
||||
if (videoId.equals(newlyLoadedVideoId)) {
|
||||
return;
|
||||
}
|
||||
videoId = newlyLoadedVideoId;
|
||||
isLiveStream = newlyLoadedLiveStreamValue;
|
||||
|
||||
Logger.printDebug(() -> "newShortsVideoStarted: " + newlyLoadedVideoId);
|
||||
boolean isMusic = isMusic(newlyLoadedVideoId);
|
||||
boolean isWhitelisted = Whitelist.isChannelWhitelistedPlaybackSpeed(newlyLoadedVideoId);
|
||||
|
||||
if (newlyLoadedLiveStreamValue || isMusic || isWhitelisted) {
|
||||
synchronized(ignoredPlaybackSpeedVideoIds) {
|
||||
if (!ignoredPlaybackSpeedVideoIds.containsKey(newlyLoadedVideoId)) {
|
||||
lastSelectedPlaybackSpeed = 1.0f;
|
||||
ignoredPlaybackSpeedVideoIds.put(newlyLoadedVideoId, lastSelectedPlaybackSpeed);
|
||||
|
||||
VideoInformation.setPlaybackSpeed(lastSelectedPlaybackSpeed);
|
||||
VideoInformation.overridePlaybackSpeed(lastSelectedPlaybackSpeed);
|
||||
|
||||
Logger.printDebug(() -> "changing playback speed to: 1.0, isLiveStream: " + newlyLoadedLiveStreamValue +
|
||||
", isMusic: " + isMusic + ", isWhitelisted: " + isWhitelisted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void newShortsVideoStarted(@NonNull String newlyLoadedChannelId, @NonNull String newlyLoadedChannelName,
|
||||
@NonNull String newlyLoadedVideoId, @NonNull String newlyLoadedVideoTitle,
|
||||
final long newlyLoadedVideoLength, boolean newlyLoadedLiveStreamValue) {
|
||||
channelIdShorts = newlyLoadedChannelId;
|
||||
videoIdShorts = newlyLoadedVideoId;
|
||||
isLiveStreamShorts = newlyLoadedLiveStreamValue;
|
||||
|
||||
Logger.printDebug(() -> "newShortsVideoStarted: " + newlyLoadedVideoId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,32 +115,29 @@ public class PlaybackSpeedPatch {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* This method is called every second for regular videos and Shorts.
|
||||
*/
|
||||
public static float getPlaybackSpeed(float playbackSpeed) {
|
||||
boolean isShorts = isShortsActive();
|
||||
String currentChannelId = isShorts ? channelIdShorts : channelId;
|
||||
String currentVideoId = isShorts ? videoIdShorts : videoId;
|
||||
boolean currentVideoIsLiveStream = isShorts ? isLiveStreamShorts : isLiveStream;
|
||||
boolean currentVideoIsWhitelisted = Whitelist.isChannelWhitelistedPlaybackSpeed(currentChannelId);
|
||||
boolean currentVideoIsMusic = !isShorts && isMusic();
|
||||
|
||||
if (currentVideoIsLiveStream || currentVideoIsWhitelisted || currentVideoIsMusic) {
|
||||
Logger.printDebug(() -> "changing playback speed to: 1.0");
|
||||
VideoInformation.setPlaybackSpeed(1.0f);
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
float defaultPlaybackSpeed = isShorts ? DEFAULT_PLAYBACK_SPEED_SHORTS.get() : DEFAULT_PLAYBACK_SPEED.get();
|
||||
|
||||
if (defaultPlaybackSpeed < 0) {
|
||||
float finalPlaybackSpeed = isShorts ? playbackSpeed : lastSelectedPlaybackSpeed;
|
||||
if (defaultPlaybackSpeed < 0) { // If the default playback speed is 'Auto', it will be overridden to the last used playback speed.
|
||||
float finalPlaybackSpeed = isShorts ? lastSelectedShortsPlaybackSpeed : lastSelectedPlaybackSpeed;
|
||||
VideoInformation.overridePlaybackSpeed(finalPlaybackSpeed);
|
||||
Logger.printDebug(() -> "changing playback speed to: " + finalPlaybackSpeed);
|
||||
return finalPlaybackSpeed;
|
||||
} else {
|
||||
} else { // Otherwise the default playback speed is used.
|
||||
synchronized (ignoredPlaybackSpeedVideoIds) {
|
||||
if (isShorts) {
|
||||
// For Shorts, the VideoInformation.overridePlaybackSpeed() method is not used, so manually save the playback speed in VideoInformation.
|
||||
VideoInformation.setPlaybackSpeed(defaultPlaybackSpeed);
|
||||
} else if (ignoredPlaybackSpeedVideoIds.containsKey(videoId)) {
|
||||
// For general videos, check whether the default video playback speed should not be applied.
|
||||
Logger.printDebug(() -> "changing playback speed to: 1.0");
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.printDebug(() -> "changing playback speed to: " + defaultPlaybackSpeed);
|
||||
return defaultPlaybackSpeed;
|
||||
}
|
||||
@ -138,6 +152,19 @@ public class PlaybackSpeedPatch {
|
||||
public static void userSelectedPlaybackSpeed(float playbackSpeed) {
|
||||
try {
|
||||
boolean isShorts = isShortsActive();
|
||||
|
||||
// Saves the user-selected playback speed in the method.
|
||||
if (isShorts) {
|
||||
lastSelectedShortsPlaybackSpeed = playbackSpeed;
|
||||
} else {
|
||||
lastSelectedPlaybackSpeed = playbackSpeed;
|
||||
// If the user has manually changed the playback speed, the whitelist has already been applied.
|
||||
// If there is a videoId on the map, it will be removed.
|
||||
synchronized (ignoredPlaybackSpeedVideoIds) {
|
||||
ignoredPlaybackSpeedVideoIds.remove(videoId);
|
||||
}
|
||||
}
|
||||
|
||||
if (PatchStatus.RememberPlaybackSpeed()) {
|
||||
BooleanSetting rememberPlaybackSpeedLastSelectedSetting = isShorts
|
||||
? Settings.REMEMBER_PLAYBACK_SPEED_SHORTS_LAST_SELECTED
|
||||
@ -178,15 +205,23 @@ public class PlaybackSpeedPatch {
|
||||
}
|
||||
}, TOAST_DELAY_MILLISECONDS);
|
||||
}
|
||||
} else if (!isShorts) {
|
||||
lastSelectedPlaybackSpeed = playbackSpeed;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Logger.printException(() -> "userSelectedPlaybackSpeed failure", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isMusic() {
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static void onDismiss() {
|
||||
synchronized (ignoredPlaybackSpeedVideoIds) {
|
||||
ignoredPlaybackSpeedVideoIds.remove(videoId);
|
||||
videoId = "";
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isMusic(String videoId) {
|
||||
if (DISABLE_DEFAULT_PLAYBACK_SPEED_MUSIC && !videoId.isEmpty()) {
|
||||
try {
|
||||
MusicRequest request = MusicRequest.getRequestForVideoId(videoId);
|
||||
|
@ -3,12 +3,14 @@ package app.revanced.patches.youtube.utils.dismiss
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.addInstruction
|
||||
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
|
||||
import app.revanced.patcher.patch.bytecodePatch
|
||||
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.EXTENSION_PATH
|
||||
import app.revanced.patches.youtube.utils.extension.sharedExtensionPatch
|
||||
import app.revanced.util.addStaticFieldToExtension
|
||||
import app.revanced.util.findMethodOrThrow
|
||||
import app.revanced.util.fingerprint.methodOrThrow
|
||||
import app.revanced.util.getReference
|
||||
import app.revanced.util.getWalkerMethod
|
||||
import app.revanced.util.indexOfFirstInstructionOrThrow
|
||||
import app.revanced.util.indexOfFirstInstructionReversedOrThrow
|
||||
import app.revanced.util.indexOfFirstLiteralInstructionOrThrow
|
||||
@ -21,6 +23,8 @@ import com.android.tools.smali.dexlib2.iface.reference.MethodReference
|
||||
private const val EXTENSION_VIDEO_UTILS_CLASS_DESCRIPTOR =
|
||||
"$EXTENSION_PATH/utils/VideoUtils;"
|
||||
|
||||
private lateinit var dismissMethod: MutableMethod
|
||||
|
||||
val dismissPlayerHookPatch = bytecodePatch(
|
||||
description = "dismissPlayerHookPatch"
|
||||
) {
|
||||
@ -36,6 +40,21 @@ val dismissPlayerHookPatch = bytecodePatch(
|
||||
reference?.returnType == "V" &&
|
||||
reference.parameterTypes.isEmpty()
|
||||
}
|
||||
|
||||
getWalkerMethod(dismissPlayerIndex).apply {
|
||||
val jumpIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.returnType == "V"
|
||||
}
|
||||
getWalkerMethod(jumpIndex).apply {
|
||||
val jumpIndex = indexOfFirstInstructionReversedOrThrow {
|
||||
opcode == Opcode.INVOKE_VIRTUAL &&
|
||||
getReference<MethodReference>()?.returnType == "V"
|
||||
}
|
||||
dismissMethod = getWalkerMethod(jumpIndex)
|
||||
}
|
||||
}
|
||||
|
||||
val dismissPlayerReference =
|
||||
getInstruction<ReferenceInstruction>(dismissPlayerIndex).reference as MethodReference
|
||||
val dismissPlayerClass = dismissPlayerReference.definingClass
|
||||
@ -81,3 +100,15 @@ val dismissPlayerHookPatch = bytecodePatch(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the video is closed.
|
||||
*/
|
||||
internal fun hookDismissObserver(descriptor: String) =
|
||||
dismissMethod.apply {
|
||||
println("Class: $definingClass Name: $name")
|
||||
addInstruction(
|
||||
0,
|
||||
"invoke-static {}, $descriptor"
|
||||
)
|
||||
}
|
@ -11,6 +11,8 @@ import app.revanced.patches.shared.customspeed.customPlaybackSpeedPatch
|
||||
import app.revanced.patches.shared.litho.addLithoFilter
|
||||
import app.revanced.patches.shared.litho.lithoFilterPatch
|
||||
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
|
||||
import app.revanced.patches.youtube.utils.dismiss.dismissPlayerHookPatch
|
||||
import app.revanced.patches.youtube.utils.dismiss.hookDismissObserver
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.COMPONENTS_PATH
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.PATCH_STATUS_CLASS_DESCRIPTOR
|
||||
import app.revanced.patches.youtube.utils.extension.Constants.VIDEO_PATH
|
||||
@ -25,7 +27,6 @@ import app.revanced.patches.youtube.utils.resourceid.sharedResourceIdPatch
|
||||
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
|
||||
import app.revanced.patches.youtube.utils.settings.settingsPatch
|
||||
import app.revanced.patches.youtube.video.information.hookBackgroundPlayVideoInformation
|
||||
import app.revanced.patches.youtube.video.information.hookShortsVideoInformation
|
||||
import app.revanced.patches.youtube.video.information.hookVideoInformation
|
||||
import app.revanced.patches.youtube.video.information.onCreateHook
|
||||
import app.revanced.patches.youtube.video.information.speedSelectionInsertMethod
|
||||
@ -87,6 +88,7 @@ val videoPlaybackPatch = bytecodePatch(
|
||||
),
|
||||
flyoutMenuHookPatch,
|
||||
lithoFilterPatch,
|
||||
dismissPlayerHookPatch,
|
||||
playerTypeHookPatch,
|
||||
recyclerViewTreeObserverPatch,
|
||||
shortsPlaybackPatch,
|
||||
@ -183,9 +185,9 @@ val videoPlaybackPatch = bytecodePatch(
|
||||
}
|
||||
|
||||
hookBackgroundPlayVideoInformation("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||
hookShortsVideoInformation("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newShortsVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||
hookVideoInformation("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZ)V")
|
||||
hookPlayerResponseVideoId("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->fetchMusicRequest(Ljava/lang/String;Z)V")
|
||||
hookDismissObserver("$EXTENSION_PLAYBACK_SPEED_CLASS_DESCRIPTOR->onDismiss()V")
|
||||
|
||||
updatePatchStatus(PATCH_STATUS_CLASS_DESCRIPTOR, "RememberPlaybackSpeed")
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user