fix(YouTube - Playback speed): Remember playback speed with new speed menu (#3810)

This commit is contained in:
LisoUseInAIKyrios 2024-10-24 07:47:01 -04:00 committed by GitHub
parent c35091305e
commit c3a5e14a0a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 73 additions and 19 deletions

View file

@ -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

View file

@ -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<TwoRegisterInstruction>(speedSelectionValueInstructionIndex).registerA
setPlaybackSpeedClassFieldReference =
getInstruction<ReferenceInstruction>(speedSelectionValueInstructionIndex + 1).reference.toString()
@ -172,8 +180,19 @@ object VideoInformationPatch : BytecodePatch(
getInstruction<ReferenceInstruction>(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<TwoRegisterInstruction>(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"
)
}
}

View file

@ -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

View file

@ -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,
)
)

View file

@ -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<ReferenceInstruction>(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
}
}
}