@@ -7,12 +7,14 @@ import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
77import app.revanced.patcher.extensions.or
88import app.revanced.patcher.patch.BytecodePatch
99import app.revanced.patcher.patch.annotation.Patch
10+ import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
1011import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
1112import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
1213import app.revanced.patches.youtube.misc.integrations.IntegrationsPatch
1314import app.revanced.patches.youtube.video.information.fingerprints.*
1415import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
1516import app.revanced.patches.youtube.video.videoid.VideoIdPatch
17+ import app.revanced.util.alsoResolve
1618import app.revanced.util.exception
1719import app.revanced.util.getReference
1820import app.revanced.util.indexOfFirstInstructionOrThrow
@@ -45,9 +47,11 @@ object VideoInformationPatch : BytecodePatch(
4547 )
4648) {
4749 private const val INTEGRATIONS_CLASS_DESCRIPTOR = " Lapp/revanced/integrations/youtube/patches/VideoInformation;"
50+ private const val INTEGRATIONS_PLAYER_INTERFACE = " Lapp/revanced/integrations/youtube/patches/VideoInformation${' $' } PlaybackController;"
4851
4952 private lateinit var playerInitMethod: MutableMethod
50- private var playerInitInsertIndex = 4
53+ private var playerInitInsertIndex = - 1
54+ private var playerInitInsertRegister = - 1
5155
5256 private lateinit var mdxInitMethod: MutableMethod
5357 private var mdxInitInsertIndex = - 1
@@ -70,42 +74,43 @@ object VideoInformationPatch : BytecodePatch(
7074 with (PlayerInitFingerprint .resultOrThrow()) {
7175 playerInitMethod = mutableClass.methods.first { MethodUtil .isConstructor(it) }
7276
73- // hook the player controller for use through integrations
77+ // find the location of the first invoke-direct call and extract the register storing the 'this' object reference.
78+ val initThisIndex = playerInitMethod.indexOfFirstInstructionOrThrow {
79+ opcode == Opcode .INVOKE_DIRECT && getReference<MethodReference >()?.name == " <init>"
80+ }
81+ playerInitInsertRegister = playerInitMethod.getInstruction<FiveRegisterInstruction >(initThisIndex).registerC
82+ playerInitInsertIndex = initThisIndex + 1
83+
84+ // Hook the player controller for use through integrations.
7485 onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR , " initialize" )
7586
76- // seek method
7787 val seekFingerprintResultMethod =
78- SeekFingerprint .also { it.resolve(context, classDef) }.resultOrThrow().method
79-
80- // create helper method
81- val seekHelperMethod = generateSeekMethodHelper(seekFingerprintResultMethod)
88+ SeekFingerprint .alsoResolve(context, PlayerInitFingerprint ).method
89+ val seekRelativeFingerprintResultMethod =
90+ SeekRelativeFingerprint .alsoResolve(context, PlayerInitFingerprint ).method
8291
83- // add the seekTo method to the class for the integrations to call
84- mutableClass.methods.add(seekHelperMethod )
92+ // Create integrations interface methods.
93+ addSeekInterfaceMethods(mutableClass, seekFingerprintResultMethod, seekRelativeFingerprintResultMethod )
8594 }
8695
8796 with (MdxPlayerDirectorSetVideoStageFingerprint .resultOrThrow()) {
8897 mdxInitMethod = mutableClass.methods.first { MethodUtil .isConstructor(it) }
8998
90- // find the location of the first invoke-direct call and extract the register storing the 'this' object reference
9199 val initThisIndex = mdxInitMethod.indexOfFirstInstructionOrThrow {
92100 opcode == Opcode .INVOKE_DIRECT && getReference<MethodReference >()?.name == " <init>"
93101 }
94102 mdxInitInsertRegister = mdxInitMethod.getInstruction<FiveRegisterInstruction >(initThisIndex).registerC
95103 mdxInitInsertIndex = initThisIndex + 1
96104
97- // hook the MDX director for use through integrations
105+ // Hook the MDX director for use through integrations.
98106 onCreateHookMdx(INTEGRATIONS_CLASS_DESCRIPTOR , " initializeMdx" )
99107
100- // MDX seek method
101108 val mdxSeekFingerprintResultMethod =
102- MdxSeekFingerprint .apply { resolve(context, classDef) }.resultOrThrow().method
109+ MdxSeekFingerprint .alsoResolve(context, MdxPlayerDirectorSetVideoStageFingerprint ).method
110+ val mdxSeekRelativeFingerprintResultMethod =
111+ MdxSeekRelativeFingerprint .alsoResolve(context, MdxPlayerDirectorSetVideoStageFingerprint ).method
103112
104- // create helper method
105- val mdxSeekHelperMethod = generateSeekMethodHelper(mdxSeekFingerprintResultMethod)
106-
107- // add the seekTo method to the class for the integrations to call
108- mutableClass.methods.add(mdxSeekHelperMethod)
113+ addSeekInterfaceMethods(mutableClass, mdxSeekFingerprintResultMethod, mdxSeekRelativeFingerprintResultMethod)
109114 }
110115
111116 with (CreateVideoPlayerSeekbarFingerprint .result!! ) {
@@ -173,33 +178,42 @@ object VideoInformationPatch : BytecodePatch(
173178 userSelectedPlaybackSpeedHook(INTEGRATIONS_CLASS_DESCRIPTOR , " userSelectedPlaybackSpeed" )
174179 }
175180
176- private fun generateSeekMethodHelper (seekMethod : Method ): MutableMethod {
177-
178- // create helper method
179- val generatedMethod = ImmutableMethod (
180- seekMethod.definingClass,
181- " seekTo" ,
182- listOf (ImmutableMethodParameter (" J" , null , " time" )),
183- " Z" ,
184- AccessFlags .PUBLIC or AccessFlags .FINAL ,
185- null , null ,
186- MutableMethodImplementation (4 )
187- ).toMutable()
188-
189- // get enum type for the seek helper method
190- val seekSourceEnumType = seekMethod.parameterTypes[1 ].toString()
191-
192- // insert helper method instructions
193- generatedMethod.addInstructions(
194- 0 ,
195- """
196- sget-object v0, $seekSourceEnumType ->a:$seekSourceEnumType
197- invoke-virtual { p0, p1, p2, v0 }, $seekMethod
198- move-result p1
199- return p1
200- """
201- )
202- return generatedMethod
181+ private fun addSeekInterfaceMethods (targetClass : MutableClass , seekToMethod : Method , seekToRelativeMethod : Method ) {
182+ // Add the interface and methods that integrations calls.
183+ targetClass.interfaces.add(INTEGRATIONS_PLAYER_INTERFACE )
184+
185+ arrayOf(
186+ seekToMethod to " seekTo" ,
187+ seekToRelativeMethod to " seekToRelative"
188+ ).forEach { (method, name) ->
189+ // Add interface method.
190+ // Get enum type for the seek helper method.
191+ val seekSourceEnumType = method.parameterTypes[1 ].toString()
192+
193+ val interfaceImplementation = ImmutableMethod (
194+ targetClass.type,
195+ name,
196+ listOf (ImmutableMethodParameter (" J" , null , " time" )),
197+ " Z" ,
198+ AccessFlags .PUBLIC or AccessFlags .FINAL ,
199+ null , null ,
200+ MutableMethodImplementation (4 )
201+ ).toMutable()
202+
203+ // Insert helper method instructions.
204+ interfaceImplementation.addInstructions(
205+ 0 ,
206+ """
207+ # first enum (field a) is SEEK_SOURCE_UNKNOWN
208+ sget-object v0, $seekSourceEnumType ->a:$seekSourceEnumType
209+ invoke-virtual { p0, p1, p2, v0 }, $method
210+ move-result p1
211+ return p1
212+ """
213+ )
214+
215+ targetClass.methods.add(interfaceImplementation)
216+ }
203217 }
204218
205219 private fun MutableMethod.insert (insertIndex : Int , register : String , descriptor : String ) =
@@ -220,8 +234,8 @@ object VideoInformationPatch : BytecodePatch(
220234 internal fun onCreateHook (targetMethodClass : String , targetMethodName : String ) =
221235 playerInitMethod.insert(
222236 playerInitInsertIndex++ ,
223- " v0 " ,
224- " $targetMethodClass ->$targetMethodName (Ljava/lang/Object; )V"
237+ " v $playerInitInsertRegister " ,
238+ " $targetMethodClass ->$targetMethodName ($INTEGRATIONS_PLAYER_INTERFACE )V"
225239 )
226240
227241 /* *
@@ -234,7 +248,7 @@ object VideoInformationPatch : BytecodePatch(
234248 mdxInitMethod.insert(
235249 mdxInitInsertIndex++ ,
236250 " v$mdxInitInsertRegister " ,
237- " $targetMethodClass ->$targetMethodName (Ljava/lang/Object; )V"
251+ " $targetMethodClass ->$targetMethodName ($INTEGRATIONS_PLAYER_INTERFACE )V"
238252 )
239253
240254 /* *
0 commit comments