diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/NewVideoQualityChangedFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/NewVideoQualityChangedFingerprint.kt similarity index 93% rename from src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/NewVideoQualityChangedFingerprint.kt rename to src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/NewVideoQualityChangedFingerprint.kt index f0fc4e9e3..64486ba5c 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/NewVideoQualityChangedFingerprint.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/shared/fingerprints/NewVideoQualityChangedFingerprint.kt @@ -1,4 +1,4 @@ -package app.revanced.patches.youtube.video.quality.fingerprints +package app.revanced.patches.youtube.shared.fingerprints import app.revanced.patcher.extensions.or import app.revanced.patcher.fingerprint.MethodFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt index 71c0a2d14..4fac93f39 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/information/VideoInformationPatch.kt @@ -11,11 +11,12 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch +import app.revanced.patches.youtube.shared.fingerprints.NewVideoQualityChangedFingerprint import app.revanced.patches.youtube.video.information.fingerprints.* import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch +import app.revanced.patches.youtube.video.quality.fingerprints.PlaybackSpeedMenuSpeedChangedFingerprint import app.revanced.patches.youtube.video.videoid.VideoIdPatch import app.revanced.util.alsoResolve -import app.revanced.util.exception import app.revanced.util.getReference import app.revanced.util.indexOfFirstInstructionOrThrow import app.revanced.util.resultOrThrow @@ -23,15 +24,15 @@ import com.android.tools.smali.dexlib2.AccessFlags import com.android.tools.smali.dexlib2.Opcode import com.android.tools.smali.dexlib2.builder.BuilderInstruction import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation +import com.android.tools.smali.dexlib2.iface.Method +import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction import com.android.tools.smali.dexlib2.iface.instruction.TwoRegisterInstruction +import com.android.tools.smali.dexlib2.iface.reference.MethodReference import com.android.tools.smali.dexlib2.immutable.ImmutableMethod import com.android.tools.smali.dexlib2.immutable.ImmutableMethodParameter import com.android.tools.smali.dexlib2.util.MethodUtil -import com.android.tools.smali.dexlib2.iface.Method -import com.android.tools.smali.dexlib2.iface.instruction.FiveRegisterInstruction -import com.android.tools.smali.dexlib2.iface.reference.MethodReference @Patch( description = "Hooks YouTube to get information about the current playing video.", @@ -43,7 +44,8 @@ object VideoInformationPatch : BytecodePatch( MdxPlayerDirectorSetVideoStageFingerprint, CreateVideoPlayerSeekbarFingerprint, PlayerControllerSetTimeReferenceFingerprint, - OnPlaybackSpeedItemClickFingerprint + OnPlaybackSpeedItemClickFingerprint, + NewVideoQualityChangedFingerprint ) ) { private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/youtube/patches/VideoInformation;" @@ -60,6 +62,12 @@ object VideoInformationPatch : BytecodePatch( private lateinit var timeMethod: MutableMethod private var timeInitInsertIndex = 2 + // Old speed menu, where speeds are entries in a list. Method is also used by the player speed button. + private lateinit var legacySpeedSelectionInsertMethod: MutableMethod + private var legacySpeedSelectionInsertIndex = -1 + private var legacySpeedSelectionValueRegister = -1 + + // New speed menu, with preset buttons and 0.05x fine adjustments buttons. private lateinit var speedSelectionInsertMethod: MutableMethod private var speedSelectionInsertIndex = -1 private var speedSelectionValueRegister = -1 @@ -158,13 +166,13 @@ object VideoInformationPatch : BytecodePatch( /* * Hook the user playback speed selection */ - OnPlaybackSpeedItemClickFingerprint.result?.mutableMethod?.apply { - speedSelectionInsertMethod = this + OnPlaybackSpeedItemClickFingerprint.resultOrThrow().mutableMethod.apply { + legacySpeedSelectionInsertMethod = this val speedSelectionMethodInstructions = this.implementation!!.instructions val speedSelectionValueInstructionIndex = speedSelectionMethodInstructions.indexOfFirst { it.opcode == Opcode.IGET } - speedSelectionValueRegister = + legacySpeedSelectionValueRegister = getInstruction(speedSelectionValueInstructionIndex).registerA setPlaybackSpeedClassFieldReference = getInstruction(speedSelectionValueInstructionIndex + 1).reference.toString() @@ -172,8 +180,19 @@ object VideoInformationPatch : BytecodePatch( getInstruction(speedSelectionValueInstructionIndex + 2).reference.toString() setPlaybackSpeedContainerClassFieldReference = getReference(speedSelectionMethodInstructions, -1, Opcode.IF_EQZ) - speedSelectionInsertIndex = speedSelectionValueInstructionIndex + 1 - } ?: throw OnPlaybackSpeedItemClickFingerprint.exception + legacySpeedSelectionInsertIndex = speedSelectionValueInstructionIndex + 1 + } + + // New playback speed menu. + PlaybackSpeedMenuSpeedChangedFingerprint.alsoResolve( + context, + NewVideoQualityChangedFingerprint + ).mutableMethod.apply { + val index = indexOfFirstInstructionOrThrow(Opcode.IGET) + speedSelectionInsertMethod = this + speedSelectionInsertIndex = index + 1 + speedSelectionValueRegister = getInstruction(index).registerA + } userSelectedPlaybackSpeedHook(INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed") } @@ -278,9 +297,15 @@ object VideoInformationPatch : BytecodePatch( /** * Hook the video speed selected by the user. */ - internal fun userSelectedPlaybackSpeedHook(targetMethodClass: String, targetMethodName: String) = + internal fun userSelectedPlaybackSpeedHook(targetMethodClass: String, targetMethodName: String) { + legacySpeedSelectionInsertMethod.addInstruction( + legacySpeedSelectionInsertIndex++, + "invoke-static { v$legacySpeedSelectionValueRegister }, $targetMethodClass->$targetMethodName(F)V" + ) + speedSelectionInsertMethod.addInstruction( speedSelectionInsertIndex++, - "invoke-static {v$speedSelectionValueRegister}, $targetMethodClass->$targetMethodName(F)V" + "invoke-static { v$speedSelectionValueRegister }, $targetMethodClass->$targetMethodName(F)V" ) + } } \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt index 71849406a..3e3c7000e 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/RememberVideoQualityPatch.kt @@ -13,8 +13,8 @@ import app.revanced.patches.shared.misc.settings.preference.ListPreference import app.revanced.patches.shared.misc.settings.preference.SwitchPreference import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch import app.revanced.patches.youtube.misc.settings.SettingsPatch +import app.revanced.patches.youtube.shared.fingerprints.NewVideoQualityChangedFingerprint import app.revanced.patches.youtube.video.information.VideoInformationPatch -import app.revanced.patches.youtube.video.quality.fingerprints.NewVideoQualityChangedFingerprint import app.revanced.patches.youtube.video.quality.fingerprints.SetQualityByIndexMethodClassFieldReferenceFingerprint import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualityItemOnClickParentFingerprint import app.revanced.patches.youtube.video.quality.fingerprints.VideoQualitySetterFingerprint diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/PlaybackSpeedMenuSpeedChangedFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/PlaybackSpeedMenuSpeedChangedFingerprint.kt new file mode 100644 index 000000000..bfa357484 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/youtube/video/quality/fingerprints/PlaybackSpeedMenuSpeedChangedFingerprint.kt @@ -0,0 +1,29 @@ +package app.revanced.patches.youtube.video.quality.fingerprints + +import app.revanced.patcher.extensions.or +import app.revanced.patcher.fingerprint.MethodFingerprint +import app.revanced.patches.youtube.shared.fingerprints.NewVideoQualityChangedFingerprint +import com.android.tools.smali.dexlib2.AccessFlags +import com.android.tools.smali.dexlib2.Opcode + +/** + * Resolves with the class found in [NewVideoQualityChangedFingerprint]. + */ +internal object PlaybackSpeedMenuSpeedChangedFingerprint : MethodFingerprint( + accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL, + returnType = "L", + parameters = listOf("L"), + opcodes = listOf( + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IF_EQZ, + Opcode.IGET_OBJECT, + Opcode.INVOKE_INTERFACE, + Opcode.MOVE_RESULT_OBJECT, + Opcode.IGET, + Opcode.INVOKE_VIRTUAL, + Opcode.SGET_OBJECT, + Opcode.RETURN_OBJECT, + ) +) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt index cc30d0de4..96827168f 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/video/speed/remember/RememberPlaybackSpeedPatch.kt @@ -14,7 +14,7 @@ import app.revanced.patches.youtube.misc.settings.SettingsPatch import app.revanced.patches.youtube.video.information.VideoInformationPatch import app.revanced.patches.youtube.video.speed.custom.CustomPlaybackSpeedPatch import app.revanced.patches.youtube.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint -import app.revanced.util.exception +import app.revanced.util.resultOrThrow import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction @Patch( @@ -54,7 +54,7 @@ object RememberPlaybackSpeedPatch : BytecodePatch( /* * Hook the code that is called when the playback speeds are initialized, and sets the playback speed */ - InitializePlaybackSpeedValuesFingerprint.result?.apply { + InitializePlaybackSpeedValuesFingerprint.resultOrThrow().apply { // Infer everything necessary for calling the method setPlaybackSpeed(). val onItemClickListenerClassFieldReference = mutableMethod.getInstruction(0).reference @@ -67,7 +67,7 @@ object RememberPlaybackSpeedPatch : BytecodePatch( move-result v0 # Check if the playback speed is not 1.0x. - const/high16 v1, 0x3f800000 # 1.0f + const/high16 v1, 1.0f cmpg-float v1, v0, v1 if-eqz v1, :do_not_override @@ -82,9 +82,9 @@ object RememberPlaybackSpeedPatch : BytecodePatch( # Invoke setPlaybackSpeed on that class. invoke-virtual {v2, v0}, ${VideoInformationPatch.setPlaybackSpeedMethodReference} - """.trimIndent(), + """, ExternalLabel("do_not_override", mutableMethod.getInstruction(0)) ) - } ?: throw InitializePlaybackSpeedValuesFingerprint.exception + } } }