mirror of
https://github.com/revanced/revanced-patches
synced 2024-12-12 12:57:50 +01:00
refactor(youtube/video-information): include video speed (#1843)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
This commit is contained in:
parent
7403fc86ae
commit
33f795350d
@ -4,19 +4,7 @@ import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37"
|
||||
)
|
||||
)]
|
||||
[Package("com.google.android.youtube", arrayOf("18.08.37"))]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class SponsorBlockCompatibility
|
@ -29,7 +29,6 @@ import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch
|
||||
import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch
|
||||
import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.patch.RememberPlaybackSpeedPatch
|
||||
import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.*
|
||||
@ -41,11 +40,13 @@ import org.jf.dexlib2.iface.reference.StringReference
|
||||
@Patch
|
||||
@DependsOn(
|
||||
dependencies = [
|
||||
VideoInformationPatch::class, // updates video information and adds method to seek in video
|
||||
VideoIdPatch::class,
|
||||
PlayerControlsBytecodePatch::class,
|
||||
PlayerTypeHookPatch::class,
|
||||
IntegrationsPatch::class,
|
||||
VideoIdPatch::class,
|
||||
// Required to skip segments on time.
|
||||
VideoInformationPatch::class,
|
||||
// Used to prevent SponsorBlock from running on Shorts because SponsorBlock does not yet support Shorts.
|
||||
PlayerTypeHookPatch::class,
|
||||
PlayerControlsBytecodePatch::class,
|
||||
SponsorBlockResourcePatch::class,
|
||||
]
|
||||
)
|
||||
@ -75,7 +76,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
/*
|
||||
Hook the video time methods
|
||||
* Hook the video time methods
|
||||
*/
|
||||
with(VideoInformationPatch) {
|
||||
videoTimeHook(
|
||||
@ -85,12 +86,12 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
}
|
||||
|
||||
/*
|
||||
Set current video id
|
||||
* Set current video id
|
||||
*/
|
||||
VideoIdPatch.injectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V")
|
||||
|
||||
/*
|
||||
Seekbar drawing
|
||||
* Seekbar drawing
|
||||
*/
|
||||
val seekbarSignatureResult = SeekbarFingerprint.result!!.let {
|
||||
SeekbarOnDrawFingerprint.apply { resolve(context, it.mutableClass) }
|
||||
@ -99,7 +100,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
val seekbarMethodInstructions = seekbarMethod.implementation!!.instructions
|
||||
|
||||
/*
|
||||
Get the instance of the seekbar rectangle
|
||||
* Get the instance of the seekbar rectangle
|
||||
*/
|
||||
for ((index, instruction) in seekbarMethodInstructions.withIndex()) {
|
||||
if (instruction.opcode != Opcode.MOVE_OBJECT_FROM16) continue
|
||||
@ -127,7 +128,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
}
|
||||
|
||||
/*
|
||||
Set rectangle absolute left and right positions
|
||||
* Set rectangle absolute left and right positions
|
||||
*/
|
||||
val drawRectangleInstructions = seekbarMethodInstructions.withIndex().filter { (_, instruction) ->
|
||||
instruction is ReferenceInstruction && (instruction.reference as? MethodReference)?.name == "drawRect"
|
||||
@ -150,7 +151,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
)
|
||||
|
||||
/*
|
||||
Draw segment
|
||||
* Draw segment
|
||||
*/
|
||||
val drawSegmentInstructionInsertIndex = (seekbarMethodInstructions.size - 1 - 2)
|
||||
val (canvasInstance, centerY) = (seekbarMethodInstructions[drawSegmentInstructionInsertIndex] as FiveRegisterInstruction).let {
|
||||
@ -162,7 +163,7 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
)
|
||||
|
||||
/*
|
||||
Voting & Shield button
|
||||
* Voting & Shield button
|
||||
*/
|
||||
val controlsMethodResult = PlayerControlsBytecodePatch.showPlayerControlsFingerprintResult
|
||||
|
||||
@ -268,7 +269,9 @@ class SponsorBlockBytecodePatch : BytecodePatch(
|
||||
} ?: return PatchResultError("Could not find the method which contains the replaceMeWith* strings")
|
||||
|
||||
|
||||
// detect end of the video has been reached
|
||||
// The vote and create segment buttons automatically change their visibility when appropriate,
|
||||
// but if buttons are showing when the end of the video is reached then they will not automatically hide.
|
||||
// Add a hook to forcefully hide when the end of the video is reached.
|
||||
AutoRepeatParentFingerprint.result ?: return AutoRepeatParentFingerprint.toErrorResult()
|
||||
AutoRepeatFingerprint.also {
|
||||
it.resolve(context, AutoRepeatParentFingerprint.result!!.classDef)
|
||||
|
@ -4,19 +4,7 @@ import app.revanced.patcher.annotation.Compatibility
|
||||
import app.revanced.patcher.annotation.Package
|
||||
|
||||
@Compatibility(
|
||||
[Package(
|
||||
"com.google.android.youtube", arrayOf(
|
||||
"17.49.37",
|
||||
"18.03.36",
|
||||
"18.03.42",
|
||||
"18.04.35",
|
||||
"18.04.41",
|
||||
"18.05.32",
|
||||
"18.05.35",
|
||||
"18.05.40",
|
||||
"18.08.37"
|
||||
)
|
||||
)]
|
||||
[Package("com.google.android.youtube", arrayOf("18.08.37"))]
|
||||
)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
internal annotation class VideoInformationCompatibility
|
||||
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.misc.video.speed.remember.fingerprint
|
||||
package app.revanced.patches.youtube.misc.video.information.fingerprints
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import org.jf.dexlib2.Opcode
|
@ -1,5 +1,6 @@
|
||||
package app.revanced.patches.youtube.misc.video.information.patch
|
||||
|
||||
import app.revanced.extensions.toErrorResult
|
||||
import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
@ -20,10 +21,16 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility
|
||||
import app.revanced.patches.youtube.misc.video.information.fingerprints.*
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.patch.RememberPlaybackSpeedPatch
|
||||
import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
|
||||
import org.jf.dexlib2.AccessFlags
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.builder.BuilderInstruction
|
||||
import org.jf.dexlib2.builder.MutableMethodImplementation
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
import org.jf.dexlib2.immutable.ImmutableMethod
|
||||
import org.jf.dexlib2.immutable.ImmutableMethodParameter
|
||||
import org.jf.dexlib2.util.MethodUtil
|
||||
@ -39,6 +46,7 @@ class VideoInformationPatch : BytecodePatch(
|
||||
CreateVideoPlayerSeekbarFingerprint,
|
||||
PlayerControllerSetTimeReferenceFingerprint,
|
||||
VideoTimeFingerprint,
|
||||
OnPlaybackSpeedItemClickFingerprint,
|
||||
)
|
||||
) {
|
||||
override fun execute(context: BytecodeContext): PatchResult {
|
||||
@ -96,14 +104,14 @@ class VideoInformationPatch : BytecodePatch(
|
||||
}
|
||||
|
||||
/*
|
||||
Inject call for video id
|
||||
* Inject call for video id
|
||||
*/
|
||||
val videoIdMethodDescriptor = "$INTEGRATIONS_CLASS_DESCRIPTOR->setVideoId(Ljava/lang/String;)V"
|
||||
VideoIdPatch.injectCall(videoIdMethodDescriptor)
|
||||
VideoIdPatch.injectCallBackgroundPlay(videoIdMethodDescriptor)
|
||||
|
||||
/*
|
||||
Set the video time method
|
||||
* Set the video time method
|
||||
*/
|
||||
with(PlayerControllerSetTimeReferenceFingerprint.result!!) {
|
||||
timeMethod = context.toMethodWalker(method)
|
||||
@ -112,7 +120,7 @@ class VideoInformationPatch : BytecodePatch(
|
||||
}
|
||||
|
||||
/*
|
||||
Set the high precision video time method
|
||||
* Set the high precision video time method
|
||||
*/
|
||||
highPrecisionTimeMethod =
|
||||
(object : MethodFingerprint("V", null, listOf("J", "J", "J", "J", "I", "L"), null) {}).also {
|
||||
@ -120,10 +128,31 @@ class VideoInformationPatch : BytecodePatch(
|
||||
}.result!!.mutableMethod
|
||||
|
||||
/*
|
||||
Hook the methods which set the time
|
||||
* Hook the methods which set the time
|
||||
*/
|
||||
highPrecisionTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTimeHighPrecision")
|
||||
|
||||
|
||||
/*
|
||||
* Hook the user playback speed selection
|
||||
*/
|
||||
OnPlaybackSpeedItemClickFingerprint.result?.apply {
|
||||
speedSelectionInsertMethod = mutableMethod
|
||||
speedSelectionInsertIndex = scanResult.patternScanResult!!.startIndex - 3
|
||||
speedSelectionValueRegister =
|
||||
(mutableMethod.instruction(speedSelectionInsertIndex) as FiveRegisterInstruction).registerD
|
||||
|
||||
val speedSelectionMethodInstructions = mutableMethod.implementation!!.instructions
|
||||
setPlaybackSpeedContainerClassFieldReference =
|
||||
getReference(speedSelectionMethodInstructions, -1, Opcode.IF_EQZ)
|
||||
setPlaybackSpeedClassFieldReference =
|
||||
getReference(speedSelectionMethodInstructions, 1, Opcode.IGET)
|
||||
setPlaybackSpeedMethodReference =
|
||||
getReference(speedSelectionMethodInstructions, 2, Opcode.IGET)
|
||||
} ?: return OnPlaybackSpeedItemClickFingerprint.toErrorResult()
|
||||
|
||||
userSelectedPlaybackSpeedHook(INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed")
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
|
||||
@ -185,5 +214,30 @@ class VideoInformationPatch : BytecodePatch(
|
||||
TIME(2),
|
||||
HIGH_PRECISION_TIME(0),
|
||||
}
|
||||
|
||||
private fun getReference(instructions: List<BuilderInstruction>, offset: Int, opcode: Opcode) =
|
||||
instructions[instructions.indexOfFirst { it.opcode == opcode } + offset].reference
|
||||
|
||||
val Instruction.reference get() = (this as ReferenceInstruction).reference.toString()
|
||||
|
||||
private lateinit var speedSelectionInsertMethod: MutableMethod
|
||||
private var speedSelectionInsertIndex = 0
|
||||
private var speedSelectionValueRegister = 0
|
||||
|
||||
/**
|
||||
* Hook the video speed selected by the user.
|
||||
*/
|
||||
internal fun userSelectedPlaybackSpeedHook(targetMethodClass: String, targetMethodName: String) =
|
||||
speedSelectionInsertMethod.addInstruction(
|
||||
speedSelectionInsertIndex++,
|
||||
"invoke-static {v$speedSelectionValueRegister}, $targetMethodClass->$targetMethodName(F)V"
|
||||
)
|
||||
|
||||
/**
|
||||
* Used by [RememberPlaybackSpeedPatch]
|
||||
*/
|
||||
internal lateinit var setPlaybackSpeedContainerClassFieldReference: String
|
||||
internal lateinit var setPlaybackSpeedClassFieldReference: String
|
||||
internal lateinit var setPlaybackSpeedMethodReference: String
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package app.revanced.patches.youtube.misc.video.speed.remember.fingerprint
|
||||
package app.revanced.patches.youtube.misc.video.speed.current.fingerprint
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
|
||||
|
@ -5,7 +5,6 @@ import app.revanced.patcher.annotation.Description
|
||||
import app.revanced.patcher.annotation.Name
|
||||
import app.revanced.patcher.annotation.Version
|
||||
import app.revanced.patcher.data.BytecodeContext
|
||||
import app.revanced.patcher.extensions.addInstruction
|
||||
import app.revanced.patcher.extensions.addInstructions
|
||||
import app.revanced.patcher.extensions.instruction
|
||||
import app.revanced.patcher.patch.*
|
||||
@ -16,24 +15,20 @@ import app.revanced.patches.shared.settings.preference.impl.StringResource
|
||||
import app.revanced.patches.shared.settings.preference.impl.SwitchPreference
|
||||
import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch
|
||||
import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch
|
||||
import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch
|
||||
import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch.Companion.reference
|
||||
import app.revanced.patches.youtube.misc.video.speed.current.fingerprint.InitializePlaybackSpeedValuesFingerprint
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.annotation.RememberPlaybackSpeedCompatibility
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.InitializePlaybackSpeedValuesFingerprint
|
||||
import app.revanced.patches.youtube.misc.video.speed.remember.fingerprint.OnPlaybackSpeedItemClickFingerprint
|
||||
import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch
|
||||
import org.jf.dexlib2.Opcode
|
||||
import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction
|
||||
import org.jf.dexlib2.iface.instruction.Instruction
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
|
||||
|
||||
@Patch
|
||||
@Name("remember-playback-speed")
|
||||
@Description("Adds the ability to remember the playback speed you chose in the video playback speed flyout.")
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoIdPatch::class])
|
||||
@DependsOn([IntegrationsPatch::class, SettingsPatch::class, VideoIdPatch::class, VideoInformationPatch::class])
|
||||
@RememberPlaybackSpeedCompatibility
|
||||
@Version("0.0.1")
|
||||
class RememberPlaybackSpeedPatch : BytecodePatch(
|
||||
listOf(
|
||||
OnPlaybackSpeedItemClickFingerprint,
|
||||
InitializePlaybackSpeedValuesFingerprint
|
||||
)
|
||||
) {
|
||||
@ -59,38 +54,21 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
|
||||
|
||||
VideoIdPatch.injectCall("${INTEGRATIONS_CLASS_DESCRIPTOR}->newVideoLoaded(Ljava/lang/String;)V")
|
||||
|
||||
VideoInformationPatch.userSelectedPlaybackSpeedHook(
|
||||
INTEGRATIONS_CLASS_DESCRIPTOR, "userSelectedPlaybackSpeed")
|
||||
|
||||
/*
|
||||
* The following code works by hooking the method which is called when the user selects a playback speed
|
||||
* to remember the last selected playback speed.
|
||||
*
|
||||
* It also hooks the method which is called when the playback speeds are initialized.
|
||||
* Conveniently, at this point the playback speed is set to the remembered playback speed.
|
||||
* Hook the code that is called when the playback speeds are initialized, and sets the playback speed
|
||||
*/
|
||||
|
||||
|
||||
// Set the remembered playback speed.
|
||||
InitializePlaybackSpeedValuesFingerprint.result?.apply {
|
||||
// Infer everything necessary for calling the method setPlaybackSpeed().
|
||||
val instructions = OnPlaybackSpeedItemClickFingerprint.result!!.mutableMethod.implementation!!.instructions
|
||||
fun getReference(offset: Int = 0, opcode: Opcode) =
|
||||
instructions[instructions.indexOfFirst { it.opcode == opcode } + offset].reference
|
||||
|
||||
val setPlaybackSpeedContainerClassFieldReference =
|
||||
getReference(-1, Opcode.IF_EQZ)
|
||||
|
||||
val setPlaybackSpeedClassFieldReference =
|
||||
getReference(1, Opcode.IGET)
|
||||
|
||||
val setPlaybackSpeedMethodReference =
|
||||
getReference(2, Opcode.IGET)
|
||||
|
||||
val onItemClickListenerClassFieldReference = mutableMethod.instruction(0).reference
|
||||
|
||||
// Registers are not used at index 0, so they can be freely used.
|
||||
mutableMethod.addInstructions(
|
||||
0,
|
||||
"""
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getCurrentPlaybackSpeed()F
|
||||
invoke-static { }, $INTEGRATIONS_CLASS_DESCRIPTOR->getPlaybackSpeedOverride()F
|
||||
move-result v0
|
||||
|
||||
# Check if the playback speed is not 1.0x.
|
||||
@ -102,30 +80,18 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
|
||||
iget-object v1, p0, $onItemClickListenerClassFieldReference
|
||||
|
||||
# Get the container class field.
|
||||
iget-object v1, v1, $setPlaybackSpeedContainerClassFieldReference
|
||||
iget-object v1, v1, ${VideoInformationPatch.setPlaybackSpeedContainerClassFieldReference}
|
||||
|
||||
# Get the field from its class.
|
||||
iget-object v2, v1, $setPlaybackSpeedClassFieldReference
|
||||
iget-object v2, v1, ${VideoInformationPatch.setPlaybackSpeedClassFieldReference}
|
||||
|
||||
# Invoke setPlaybackSpeed on that class.
|
||||
invoke-virtual {v2, v0}, $setPlaybackSpeedMethodReference
|
||||
invoke-virtual {v2, v0}, ${VideoInformationPatch.setPlaybackSpeedMethodReference}
|
||||
""".trimIndent(),
|
||||
listOf(ExternalLabel("do_not_override", mutableMethod.instruction(0)))
|
||||
)
|
||||
} ?: return InitializePlaybackSpeedValuesFingerprint.toErrorResult()
|
||||
|
||||
// Remember the selected playback speed.
|
||||
OnPlaybackSpeedItemClickFingerprint.result?.apply {
|
||||
val setPlaybackSpeedIndex = scanResult.patternScanResult!!.startIndex - 3
|
||||
|
||||
val selectedPlaybackSpeedRegister =
|
||||
(mutableMethod.instruction(setPlaybackSpeedIndex) as FiveRegisterInstruction).registerD
|
||||
|
||||
mutableMethod.addInstruction(
|
||||
setPlaybackSpeedIndex,
|
||||
"invoke-static { v$selectedPlaybackSpeedRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR->setPlaybackSpeed(F)V"
|
||||
)
|
||||
} ?: return OnPlaybackSpeedItemClickFingerprint.toErrorResult()
|
||||
|
||||
return PatchResultSuccess()
|
||||
}
|
||||
@ -133,7 +99,5 @@ class RememberPlaybackSpeedPatch : BytecodePatch(
|
||||
private companion object {
|
||||
const val INTEGRATIONS_CLASS_DESCRIPTOR =
|
||||
"Lapp/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch;"
|
||||
|
||||
val Instruction.reference get() = (this as ReferenceInstruction).reference.toString()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user