diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoSpeedChangedFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoSpeedChangedFingerprint.kt
new file mode 100644
index 000000000..091159ee1
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoSpeedChangedFingerprint.kt
@@ -0,0 +1,17 @@
+package app.revanced.patches.youtube.video.speed.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+import org.jf.dexlib2.Opcode
+
+object VideoSpeedChangedFingerprint : MethodFingerprint(
+ opcodes = listOf(
+ Opcode.IGET_OBJECT,
+ Opcode.IF_EQZ,
+ Opcode.IF_EQZ,
+ Opcode.IGET,
+ Opcode.CHECK_CAST,
+ Opcode.IGET_OBJECT,
+ Opcode.INVOKE_VIRTUAL
+ ),
+ customFingerprint = { it.name == "onItemClick" }
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoSpeedParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoSpeedParentFingerprint.kt
new file mode 100644
index 000000000..c97886640
--- /dev/null
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoSpeedParentFingerprint.kt
@@ -0,0 +1,8 @@
+package app.revanced.patches.youtube.video.speed.bytecode.fingerprints
+
+import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
+
+object VideoSpeedParentFingerprint : MethodFingerprint(
+ returnType = "V",
+ strings = listOf("PLAYBACK_RATE_MENU_BOTTOM_SHEET_FRAGMENT")
+)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoUserSpeedChangeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoUserSpeedChangeFingerprint.kt
deleted file mode 100644
index 5ae0f6e50..000000000
--- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/fingerprints/VideoUserSpeedChangeFingerprint.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package app.revanced.patches.youtube.video.speed.bytecode.fingerprints
-
-import app.revanced.patcher.extensions.or
-import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
-import org.jf.dexlib2.AccessFlags
-import org.jf.dexlib2.Opcode
-
-object VideoUserSpeedChangeFingerprint : MethodFingerprint(
- "V",
- AccessFlags.PUBLIC or AccessFlags.FINAL,
- listOf("L","L","I","J"),
- listOf(
- Opcode.IGET_OBJECT,
- Opcode.IF_EQZ,
- Opcode.IF_EQZ,
- Opcode.IGET,
- Opcode.CHECK_CAST,
- Opcode.IGET_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.IGET_OBJECT,
- Opcode.INVOKE_STATIC,
- Opcode.MOVE_RESULT_OBJECT,
- Opcode.INVOKE_VIRTUAL,
- Opcode.INVOKE_VIRTUAL,
- Opcode.RETURN_VOID
- )
-)
\ No newline at end of file
diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/patch/VideoSpeedBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/patch/VideoSpeedBytecodePatch.kt
index af2296c21..f6d889d4e 100644
--- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/patch/VideoSpeedBytecodePatch.kt
+++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/bytecode/patch/VideoSpeedBytecodePatch.kt
@@ -7,22 +7,25 @@ import app.revanced.patcher.extensions.addInstruction
import app.revanced.patcher.extensions.addInstructions
import app.revanced.patcher.extensions.or
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve
-import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchResult
import app.revanced.patcher.patch.PatchResultSuccess
+import app.revanced.patcher.patch.annotations.DependsOn
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import app.revanced.patcher.util.smali.toInstructions
-import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedSetterFingerprint
-import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoUserSpeedChangeFingerprint
import app.revanced.patches.youtube.misc.videoid.legacy.patch.LegacyVideoIdPatch
+import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedChangedFingerprint
+import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedParentFingerprint
+import app.revanced.patches.youtube.video.speed.bytecode.fingerprints.VideoSpeedSetterFingerprint
import app.revanced.shared.annotation.YouTubeCompatibility
+import app.revanced.shared.extensions.toErrorResult
import app.revanced.shared.util.bytecode.BytecodeHelper
import app.revanced.shared.util.integrations.Constants.VIDEO_PATH
import org.jf.dexlib2.AccessFlags
+import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference
+import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.FieldReference
-import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.immutable.ImmutableMethod
import org.jf.dexlib2.immutable.ImmutableMethodImplementation
import org.jf.dexlib2.immutable.ImmutableMethodParameter
@@ -33,74 +36,83 @@ import org.jf.dexlib2.immutable.ImmutableMethodParameter
@Version("0.0.1")
class VideoSpeedBytecodePatch : BytecodePatch(
listOf(
- VideoSpeedSetterFingerprint, VideoUserSpeedChangeFingerprint
+ VideoSpeedChangedFingerprint,
+ VideoSpeedParentFingerprint,
+ VideoSpeedSetterFingerprint
)
) {
- private companion object {
- const val INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR =
- "$VIDEO_PATH/VideoSpeedPatch;"
- }
override fun execute(context: BytecodeContext): PatchResult {
- val userSpeedResult = VideoUserSpeedChangeFingerprint.result!!
- val userSpeedMutableMethod = userSpeedResult.mutableMethod
+ VideoSpeedParentFingerprint.result?.let { parentResult ->
+ val parentClassDef = parentResult.classDef
- val setterResult = VideoSpeedSetterFingerprint.result!!
- val setterMutableMethod = setterResult.mutableMethod
+ VideoSpeedChangedFingerprint.also { it.resolve(context, parentClassDef) }.result?.let { result ->
+ startIndex = result.scanResult.patternScanResult!!.startIndex
+ endIndex = result.scanResult.patternScanResult!!.endIndex
+
+ with (result.method) {
+ val speedInstruction = implementation!!.instructions
- VideoUserSpeedChangeFingerprint.resolve(context, setterResult.classDef)
- val FirstReference =
- VideoUserSpeedChangeFingerprint.result!!.method.let { method ->
- (method.implementation!!.instructions.elementAt(5) as ReferenceInstruction).reference as FieldReference
- }
- val SecondReference =
- VideoUserSpeedChangeFingerprint.result!!.method.let { method ->
- (method.implementation!!.instructions.elementAt(10) as ReferenceInstruction).reference as FieldReference
- }
- val ThirdReference =
- VideoUserSpeedChangeFingerprint.result!!.method.let { method ->
- (method.implementation!!.instructions.elementAt(11) as ReferenceInstruction).reference as MethodReference
- }
+ firstRef =
+ (speedInstruction.elementAt(startIndex) as ReferenceInstruction).reference as FieldReference
- userSpeedMutableMethod.addInstruction(
- 0, "invoke-static {}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->userChangedSpeed()V"
- )
+ secondRef =
+ (speedInstruction.elementAt(endIndex - 1) as ReferenceInstruction).reference as FieldReference
- setterMutableMethod.addInstructions(
- 0,
- """
- invoke-static {p1, p2}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->getSpeedValue([Ljava/lang/Object;I)F
- move-result v0
- invoke-direct {p0, v0}, ${setterResult.classDef.type}->overrideSpeed(F)V
- """,
- )
+ thirdRef =
+ (speedInstruction.elementAt(endIndex) as ReferenceInstruction).reference as DexBackedMethodReference
- val classDef = userSpeedResult.mutableClass
- classDef.methods.add(
- ImmutableMethod(
- classDef.type,
- "overrideSpeed",
- listOf(ImmutableMethodParameter("F", null, null)),
- "V",
- AccessFlags.PRIVATE or AccessFlags.PRIVATE,
- null,
- null,
- ImmutableMethodImplementation(
- 4, """
- const/4 v0, 0x0
- cmpg-float v0, v3, v0
- if-gez v0, :cond_0
- return-void
- :cond_0
- iget-object v0, v2, ${setterResult.classDef.type}->${FirstReference.name}:${FirstReference.type}
- check-cast v0, ${SecondReference.definingClass}
- iget-object v1, v0, ${SecondReference.definingClass}->${SecondReference.name}:${SecondReference.type}
- invoke-virtual {v1, v3}, $ThirdReference
- return-void
- """.toInstructions(), null, null
+ val register =
+ (speedInstruction.elementAt(endIndex) as FiveRegisterInstruction).registerD
+
+ result.mutableMethod.addInstruction(
+ endIndex,
+ "invoke-static { v$register }, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR" +
+ "->" +
+ "userChangedSpeed(F)V"
+ )
+ }
+
+ } ?: return VideoSpeedChangedFingerprint.toErrorResult()
+
+ val parentMutableClass = parentResult.mutableClass
+
+ parentMutableClass.methods.add(
+ ImmutableMethod(
+ parentMutableClass.type,
+ "overrideSpeed",
+ listOf(ImmutableMethodParameter("F", null, null)),
+ "V",
+ AccessFlags.PRIVATE or AccessFlags.PRIVATE,
+ null,
+ null,
+ ImmutableMethodImplementation(
+ 4, """
+ const/4 v0, 0x0
+ cmpg-float v0, v3, v0
+ if-lez v0, :cond_0
+ iget-object v0, v2, ${parentClassDef.type}->${firstRef.name}:${firstRef.type}
+ check-cast v0, ${secondRef.definingClass}
+ iget-object v1, v0, ${secondRef.definingClass}->${secondRef.name}:${secondRef.type}
+ invoke-virtual {v1, v3}, $thirdRef
+ :cond_0
+ return-void
+ """.toInstructions(), null, null
+ )
+ ).toMutable()
+ )
+
+ } ?: return VideoSpeedParentFingerprint.toErrorResult()
+
+ VideoSpeedSetterFingerprint.result?.let { result ->
+ result.mutableMethod.addInstructions(
+ 0, """
+ invoke-static {}, $INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->getSpeedValue()F
+ move-result v0
+ invoke-direct {p0, v0}, ${result.classDef.type}->overrideSpeed(F)V
+ """,
)
- ).toMutable()
- )
+ } ?: return VideoSpeedSetterFingerprint.toErrorResult()
LegacyVideoIdPatch.injectCall("$INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR->newVideoStarted(Ljava/lang/String;)V")
@@ -108,4 +120,16 @@ class VideoSpeedBytecodePatch : BytecodePatch(
return PatchResultSuccess()
}
+
+ private companion object {
+ const val INTEGRATIONS_VIDEO_SPEED_CLASS_DESCRIPTOR =
+ "$VIDEO_PATH/VideoSpeedPatch;"
+
+ var startIndex: Int = 0
+ var endIndex: Int = 0
+
+ private lateinit var firstRef: FieldReference
+ private lateinit var secondRef: FieldReference
+ private lateinit var thirdRef: DexBackedMethodReference
+ }
}
\ No newline at end of file
diff --git a/src/main/resources/youtube/settings/host/values/strings.xml b/src/main/resources/youtube/settings/host/values/strings.xml
index 58d8f756f..e2ee161de 100644
--- a/src/main/resources/youtube/settings/host/values/strings.xml
+++ b/src/main/resources/youtube/settings/host/values/strings.xml
@@ -239,6 +239,9 @@ Is it ready to submit?"
Does not save video quality values even when changing video quality
Save the video quality value whenever you change the video quality
Enable save video quality
+ Does not save video speed values even when changing video speed
+ Save the video speed value whenever you change the video speed
+ Enable save video speed
Seekbar tapping is enabled
Enable seekbar tapping
Even if the brightness is set to 0 by swiping, auto brightness is not activated
@@ -507,6 +510,13 @@ Would you like to continue?"
Dislikes shown with separator
Dislikes with separator
Hidden
+ Failed to set quality
+ No internet connection
+ Changing default mobile data quality to:
+ Failed to change default mobile data quality
+ Changing default Wi-Fi quality to:
+ Failed to change default WI-FI quality
+ Changing default speed to:
ReVanced settings
Swipe controls related settings
Swipe controls settings
@@ -522,12 +532,6 @@ Would you like to continue?"
Video ads are shown
Video ads are hidden
Hide video ads
- Failed to set quality
- No internet connection
- Changing default mobile data quality to:
- Failed to change default mobile data quality
- Changing default Wi-Fi quality to:
- Failed to change default WI-FI quality
Video related settings
Video settings
Failed to add channel %s to the %s whitelist
diff --git a/src/main/resources/youtube/settings/xml/revanced_prefs.xml b/src/main/resources/youtube/settings/xml/revanced_prefs.xml
index 3aee4d57e..c26dba799 100644
--- a/src/main/resources/youtube/settings/xml/revanced_prefs.xml
+++ b/src/main/resources/youtube/settings/xml/revanced_prefs.xml
@@ -295,6 +295,9 @@
+
+