@@ -11,20 +11,23 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMu
1111import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint
1212import app.revanced.patches.shared.fingerprints.CreatePlayerRequestBodyWithModelFingerprint.indexOfModelInstruction
1313import app.revanced.patches.youtube.utils.compatibility.Constants
14+ import app.revanced.patches.youtube.utils.fingerprints.PlaybackRateBottomSheetBuilderFingerprint
1415import app.revanced.patches.youtube.utils.fix.client.fingerprints.BuildInitPlaybackRequestFingerprint
1516import app.revanced.patches.youtube.utils.fix.client.fingerprints.BuildPlayerRequestURIFingerprint
17+ import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlaybackSpeedMenuItemFingerprint
1618import app.revanced.patches.youtube.utils.fix.client.fingerprints.CreatePlayerRequestBodyFingerprint
1719import app.revanced.patches.youtube.utils.fix.client.fingerprints.NerdsStatsVideoFormatBuilderFingerprint
1820import app.revanced.patches.youtube.utils.fix.client.fingerprints.PlayerGestureConfigSyntheticFingerprint
1921import app.revanced.patches.youtube.utils.fix.client.fingerprints.SetPlayerRequestClientTypeFingerprint
2022import app.revanced.patches.youtube.utils.integrations.Constants.MISC_PATH
21- import app.revanced.patches.youtube.utils.playertype.PlayerTypeHookPatch
23+ import app.revanced.patches.youtube.utils.resourceid.SharedResourceIdPatch
2224import app.revanced.patches.youtube.utils.settings.SettingsPatch
2325import app.revanced.patches.youtube.video.information.VideoInformationPatch
2426import app.revanced.patches.youtube.video.playerresponse.PlayerResponseMethodHookPatch
2527import app.revanced.util.getReference
2628import app.revanced.util.getStringInstructionIndex
2729import app.revanced.util.getWalkerMethod
30+ import app.revanced.util.indexOfFirstInstructionOrThrow
2831import app.revanced.util.patch.BaseBytecodePatch
2932import app.revanced.util.resultOrThrow
3033import com.android.tools.smali.dexlib2.AccessFlags
@@ -42,11 +45,11 @@ object SpoofClientPatch : BaseBytecodePatch(
4245 name = " Spoof client" ,
4346 description = " Adds options to spoof the client to allow video playback." ,
4447 dependencies = setOf(
45- PlayerTypeHookPatch ::class,
4648 PlayerResponseMethodHookPatch ::class,
4749 SettingsPatch ::class,
4850 VideoInformationPatch ::class,
4951 SpoofUserAgentPatch ::class,
52+ SharedResourceIdPatch ::class,
5053 ),
5154 compatiblePackages = Constants .COMPATIBLE_PACKAGE ,
5255 fingerprints = setOf(
@@ -60,6 +63,10 @@ object SpoofClientPatch : BaseBytecodePatch(
6063 // Player gesture config.
6164 PlayerGestureConfigSyntheticFingerprint ,
6265
66+ // Player speed menu item.
67+ CreatePlaybackSpeedMenuItemFingerprint ,
68+ PlaybackRateBottomSheetBuilderFingerprint ,
69+
6370 // Nerds stats video format.
6471 NerdsStatsVideoFormatBuilderFingerprint ,
6572 )
@@ -257,26 +264,74 @@ object SpoofClientPatch : BaseBytecodePatch(
257264 // region fix player gesture.
258265
259266 PlayerGestureConfigSyntheticFingerprint .resultOrThrow().let {
260- arrayOf(3 , 9 ).forEach { offSet ->
261- it.getWalkerMethod(context, it.scanResult.patternScanResult!! .endIndex - offSet)
262- .apply {
263- val index = implementation!! .instructions.size - 1
264- val register = getInstruction<OneRegisterInstruction >(index).registerA
267+ val endIndex = it.scanResult.patternScanResult!! .endIndex
268+ val downAndOutLandscapeAllowedIndex = endIndex - 3
269+ val downAndOutPortraitAllowedIndex = endIndex - 9
265270
266- addInstructions(
267- index,
268- """
269- invoke-static {v$register }, $INTEGRATIONS_CLASS_DESCRIPTOR ->enablePlayerGesture(Z)Z
270- move-result v$register
271+ arrayOf(
272+ downAndOutLandscapeAllowedIndex,
273+ downAndOutPortraitAllowedIndex,
274+ ).forEach { index ->
275+ val gestureAllowedMethod = it.getWalkerMethod(context, index)
276+
277+ gestureAllowedMethod.apply {
278+ val isAllowedIndex = getInstructions().lastIndex
279+ val isAllowed = getInstruction<OneRegisterInstruction >(isAllowedIndex).registerA
280+
281+ addInstructions(
282+ isAllowedIndex,
271283 """
272- )
273- }
284+ invoke-static { v$isAllowed }, $INTEGRATIONS_CLASS_DESCRIPTOR ->enablePlayerGesture(Z)Z
285+ move-result v$isAllowed
286+ """ ,
287+ )
288+ }
289+ }
290+ }
291+
292+ // endregion
293+
294+ // region fix playback speed menu item.
295+
296+ // fix for iOS, Android Testsuite
297+ CreatePlaybackSpeedMenuItemFingerprint .resultOrThrow().let {
298+ val scanResult = it.scanResult.patternScanResult!!
299+ if (scanResult.startIndex != 0 ) throw PatchException (" Unexpected start index: ${scanResult.startIndex} " )
300+
301+ it.mutableMethod.apply {
302+ // Find the conditional check if the playback speed menu item is not created.
303+ val shouldCreateMenuIndex = indexOfFirstInstructionOrThrow(scanResult.endIndex) { opcode == Opcode .IF_EQZ }
304+ val shouldCreateMenuRegister = getInstruction<OneRegisterInstruction >(shouldCreateMenuIndex).registerA
305+
306+ addInstructions(
307+ shouldCreateMenuIndex,
308+ """
309+ invoke-static { v$shouldCreateMenuRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR ->forceCreatePlaybackSpeedMenu(Z)Z
310+ move-result v$shouldCreateMenuRegister
311+ """ ,
312+ )
313+ }
314+ }
315+
316+ // fix for Android TV
317+ PlaybackRateBottomSheetBuilderFingerprint .resultOrThrow().let {
318+ it.mutableMethod.apply {
319+ val targetIndex = it.scanResult.patternScanResult!! .endIndex
320+ val targetRegister = getInstruction<OneRegisterInstruction >(targetIndex).registerA
321+
322+ addInstructions(
323+ targetIndex,
324+ """
325+ invoke-static { v$targetRegister }, $INTEGRATIONS_CLASS_DESCRIPTOR ->forceCreatePlaybackSpeedMenuReversed(Z)Z
326+ move-result v$targetRegister
327+ """ ,
328+ )
274329 }
275330 }
276331
277332 // endregion
278333
279- // region append spoof info
334+ // region append spoof info.
280335
281336 NerdsStatsVideoFormatBuilderFingerprint .resultOrThrow().mutableMethod.apply {
282337 for (index in implementation!! .instructions.size - 1 downTo 0 ) {
0 commit comments