Skip to content

Commit

Permalink
fix(YouTube - Playback speed): Remember playback speed with new speed…
Browse files Browse the repository at this point in the history
… menu (ReVanced#3810)
  • Loading branch information
LisoUseInAIKyrios authored Oct 24, 2024
1 parent c350913 commit c3a5e14
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,27 +11,28 @@ 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
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.",
Expand All @@ -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;"
Expand All @@ -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
Expand Down Expand Up @@ -158,22 +166,33 @@ 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()
setPlaybackSpeedMethodReference =
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")
}
Expand Down Expand Up @@ -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"
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
)
)
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
}
}

0 comments on commit c3a5e14

Please sign in to comment.